Ім'я: LP-5xxx Засновано: серпень 2011р Завершено: вересень 2011р Версія: 1.0.0 Учасники:Роман Савоченко Опис: Проект присвячено збірці OpenSCADA та прошивки для ARM контролерів серії LP-5xxx та LP-8x{3|4}x фірми ICP DAS. Матеріали:ftp://ftp.oscada.org/OpenSCADA/PLC/LP5xx1
Вступ
Фірма ICP_DAS достатньо давно випускає контролери на процесорах ARM архітектури з передвстановленим оточенням ОС Linux, що робить цікавим створення збірки OpenSCADA або нової прошивки з OpenSCADA.
До останнього часу низка причин ставали на перепоні збірки OpenSCADA для ARM-контролерів ICP DAS:
відсутність на руках жодного із ARM-контролерів;
неготовність OpenSCADA для роботи на ARM-архітектурі;
дуже застаріле оточення Linux ARM-контролерів фірми "ICP DAS".
На цей час всі ці перепони було усунено. Так, завдяки Петру Літковцю на руках з'явився контролер LP-5141, а до цього часу OpenSCADA у значній мірі було вже адаптовано до роботи на ARM-архітектурі, за посередництвом відпрацювання та стабілізації на долонному комп'ютері фірми Nokia - N800. У наслідок же роботи з контролером LP-5141 було усунено останню перепону шляхом оновлення початкового програмного оточення із збереженням поточного функціоналу.
В цілому, метою даного проекту є відпрацювання механізмів та створення збірки OpenSCADA для контролерів сімейства ARM фірми "ICP DAS", а також створення прошивок під контролери "ICP DAS", які потраплятимуть до рук розробників OpenSCADA.
1. ПЛК LP-5141
ПЛК (рис.1) конструктивно виконано у вигляді моноблоку, який не містить вбудованого УСО, окрім можливості встановлення однієї спеціальної плати розширення IO, а підключення зовнішнього здійснюється за посередництвом вбудованого інтерфейсу RS-485, наприклад, у вигляді модулів серії I-7000, фірми "ICP DAS".
Рис. 1. ПЛК серії LP-5xxx.
Процесор контролеру має наступні технічні характеристики:
CPU
PXA270 або сумісний (32-біт та 520МГц)
SDRAM
128 MB
Flash
64 MB
EEPROM
16 KB
Зберігання даних: 40 років; 1,000,000 циклів видалення/запису.
Розширена Flash пам'ять
microSD сокет з однією microSD картою на 2GB (може підтримувати 16 GB microSDHC картки)
64-біт Серійний Номер Обладнання
Наявний
Подвійний Watchdog таймер
Наявний
VGA
800 × 600
Ethernet порти
RJ-45 x 2, 10/100 Base-TX Ethernet Контролер (Авто-узгодження, авто MDI/MDI-X, LED індикатор)
USB 1.1 (хост)
1
COM1 (/dev/ttySA0)
RS-232 (RxD, TxD and GND); Не ізольовано
COM2 (/dev/ttySA1)
RS-485 (D2+,D2-); 2500 VDC; Ізольовано
COM3 (/dev/ttySA3)
RS-232 (RxD, TxD and GND); Не ізольовано
Робоча температура
-25 ~ +75 °C
2. Програмне оточення на основі OpenSCADA.
Програмне оточення, основане на ОС Linux, для ARM контролерів фірми ICP DAS за звичай мають: ядро Linux 2.6.19, GLibC 2.2.5 та GCC 2.95. Для збірки стороннього ПЗ фірмою ICP-DAS надається SDK з кроскомпілятором, набором бібліотек та заголовків до них (Linux toolchain). Як можна бачити, версії GLibC та GCC дуже старі, а саме 2001 року. Збірка OpenSCADA у такому оточені фактично неможлива. Якщо використання GLibC версії 2.2.5 ще можливе, то GCC версії 2.95 має C++ компілятор, який на збірці коду OpenSCADA просто рушиться, а стандартна бібліотека C++ або STL дуже обмежена та під неї потрібна значна і головне безглузда адаптація. З цієї причини потрібне було оновлення первинного програмного оточення до версії GCC компілятору, або бібліотеки C++, не менш 3.
Оскільки внутрішня флеш-пам'ять має порівняно невеликий об'єм (64 Мб), а повна перезбірка початкового програмного оточення контролера — достатньо трудомісткий процес, то було вирішено забезпечити сумісність базових бібліотек нового та старого оточення. А саме, можливість використовувати бібліотеки на зразок fontconfig, i8k з первинного оточення та роботу програм первинного оточення з новими бібліотеками.
У процесі підбору нового програмного оточення для процесору PXA-270 контролера "ICP DAS" було апробовано декілька варіантів, оскільки частина з них мала ті або інші недоліки:
crosstool-0.43 — цікавий хоча і застарілий проект (остання версія 2006 року) по збірці Linux кросоточення під потрібне обладнання. Було відкладено після декількох невдалих спроб зібрати нове оточення для роботи з "Software FP" та "VFP". Як надалі виявилося для об'єктних файлів попереднього оточення некоректно відображається інформація про начебто наявність там "Software FP" та "VFP", хоча насправді операції з реальними числами там відбуваються за посередництвом "FPA". На протязі вирішення проблеми, описанної у разділі "Зауваження", за допомогою цього інструменту було зібрано ToolChain на основі профилю "arm-xscale.dat" та "gcc-4.0.2-glibc-2.3.6-tls.dat", який у кінцевому рахунку було покладено у основу нової прошивки.
PXA-Linux Project — проект по створенню незалежного набору інструментів Linux для збірки під процесор PXA. Має бінарну збірку 02-25-2005/bin/arm-linux-toolchain-bin-12-15-04-driscoll.tar.gz. Виявилося, що цю збірку зібрано із "Software FP" та "VFP", а також наявно проблеми у вигляді виключення низки розширень компілятору gcc, наприклад: __attribute__((packed)).
Voipac — бінарна збірка інструментів кроскомпіляції (arm-linux-gcc-3.4.1.tar.gz) від фірми "Voipac" для власного обладнання на процесорі PXA-270. Цей ToolChain було зібрано за допомогою раніш розглянутого crosstool.
Збірка OpenSCADA з використанням кросскомпілятору здійснюється наступним чином:
# Розпакування архіву інструментарію $ cd /opt $ tar --lzma -xvf lincon.tlz # Ініціалізація оточення збірки $ . /opt/lincon/linpac_new.sh # Перехід до дерева вихідних текстів OpenSCADA, конфігурація та збірка $ cd /lincon/OpenSCADA $ ./configure --host=arm-xscale-linux-gnu CXXFLAGS="-O2 -D_REENTRANT" CFLAGS="-O2 -D_REENTRANT" --disable-QTStarter --disable-QTCfg --disable-Vision --disable-MySQL --disable-FireBird --disable-PostgreSQL --disable-SoundCard --enable-ICP_DAS $ make
Результуюче оточення контролеру з OpenSCADA було сформовано шляхом заміни базових бібліотек первинного оточення на бібліотеки з нового набору інструментів, збірки OpenSCADA та розташування файлів OpenSCADA у дереві первинного оточення.
OpenSCADA було зібрана з виключенням низки бібліотек та модулів. Так, були зібрані та перевірені модулі та функції OpenSCADA:
Ядро OpenSCADA — зібрано із бібліотекою LibGD2 (роботу перевірено). У процесі перевірки та адаптації розширено функції зберігання конфігурації OpenSCADA у конфігураційному файлі.
DB.SQLite — БД SQLite (роботу перевірено). Зібрано бібліотеку та модуль OpenSCADA для роботи з БД SQLite. У процесі перевірки виявлено та виконано обхід помилки у GLibC 2.3.2, яку пов'язано із відсутністю перевірки на взаємо-блокування "rw"-ресурсів.
DB.DBF — БД DBF (роботу перевірено). Модуль роботи з DBF-файлами версії 3.
Transport.Sockets — Модуль транспорту Сокетів TCP, UDP та Unix (роботу перевірено). У процесі використання TCP-сокетів виявлено та усунено неініціалізацію структури перевірки стану сокету.
Transport.SSL — Модуль транспорту безпечних сокетів: SSL, TLS (роботу перевірено).
Transport.Serial — Модуль транспорту послідовних інтерфейсів (роботу перевірено). Виявилося, що COM3 чомусь розташовано на пристрої /dev/ttySA3.
Protocol.SelfSystem — Модуль власного протоколу OpenSCADA (роботу перевірено).
Protocol.HTTP — Модуль реалізації протоколу HTTP (роботу перевірено).
Protocol.ModBus — Модуль реалізації протоколу ModBus (роботу перевірено). Конфігурація станції як серверу даних за посередництвом протоколу ModBus.
Protocol.OPC_UA — Модуль реалізації протоколу OPC UA (роботу перевірено). Конфігурація станції як серверу даних за посередництвом протоколу OPC UA. Виявлено проблему різниці представлення реального на x86 та ARM FPA!
Protocol.UserProtocol — Модуль вільної реалізації простих протоколів користувачем, за посередництвом мови програмування OpenSCADA (роботу перевірено).
DAQ.System — Модуль даних операційної системи (роботу перевірено). Зібрано без використання бібліотеки LibSensors.
DAQ.JavaLikeCalc — Модуль реалізації подібної до Java користувацької мови та обчислень на її основі (роботу перевірено).
DAQ.BlockCalc — Модуль реалізації блочних обчислень (роботу перевірено).
DAQ.LogicLev — Модуль реалізації джерел даних логічного рівня (роботу перевірено).
DAQ.ModBus — Модуль роботи з джерелами даних за посередництвом протоколу ModBus (роботу перевірено).
DAQ.DCON — Модуль роботи з джерелами даних за посередництвом протоколу DCON (роботу перевірено). Наприклад, з пристроями ICP_DAS серії I-7000. Виявлено та виправлено падіння під час отримання негативного розміру відповіді. Результат відповіді тепер завжди повертає >= 0.
DAQ.ICP_DAS — Модуль джерел даних ICP_DAS (немає обладнання для перевірки). Послідовні серії: I-87000 та I-7000; паралельні (швидкі): серії I-8000. Модуль зібрано з бібліотекою libi8k.a для ARM-архітектури.
DAQ.DAQGate — Модуль реалізації шлюзування джерел даних інших станцій OpenSCADA (роботу перевірено).
DAQ.OPC_UA — Модуль роботи з джерелами даних за посередництвом протоколу OPC_UA (роботу перевірено). Виявлено проблему різниці представлення реального на x86 та ARM FPA - додано перетворення під час передачі!
DAQ.Siemens — Модуль роботи з контролерами Siemens, за посередництвом Industrial Ethernet (ISO_TCP) (роботу перевірено).
DAQ.SNMP — Модуль збору даних мережевого обладнання за протоколом SNMP (роботу перевірено).
Archive.DBArch — Модуль архівації на БД (роботу перевірено).
Archive.FSArch — Модуль архівації на файлову систему (роботу перевірено). Виявлено проблему при перевірці архіву, видача повідомлень під час запуску: "Error archive file structure: <ARCHIVES/VAL/1s/CPULoad_load 2011-09-12 17:47:17.val>. Margin = -8 byte. Will try fix it!". У результаті з'ясовано, що алгоритм швидкого підрахунку бітів не вирівняно на 4 байта під час читання буферу пам'яті - виправлено.
UI.WebCfg — Модуль заснованого на Web конфігуратору OpenSCADA (роботу перевірено).
UI.WebCfgD — Модуль заснованого на Web динамічного конфігуратору OpenSCADA (роботу перевірено).
Special.FLibComplex1 — Бібліотека функцій сумісності з Complex1(ООО НИП "ДІЯ") (роботу перевірено). Використовується для блокового програмування.
Special.FLibMath — Бібліотека стандартних математичних функцій (роботу перевірено).
Special.FLibSYS — Бібліотека системних функцій розширення OpenSCADA (роботу перевірено).
З метою зручного розповсюдження та застосування отриманої збірки OpenSCADA для ARM-контролерів фірми "ICP DAS" було виконано розбір формату прошивок для цих контролерів та формування нової, яка включає OpenSCADA. Прошивка ARM-контролерів "ICP DAS" представляє з себе бінарний файл з назвою схожу на "lp5x4x_1.1.bin". Структурно цей файл містить ядро та кореневу файлову систему типа JFFS2. Дізнатися точне їх розташування можна за допомогою команди у попередньому оточені контролеру, наприклад, для LP-5141:
Із отриманого результату команди можна зробити висновок, що точка поєднання образу ядра та файлової системи знаходиться за зсувом файлу прошивки 0x280000, а розмір блоку стирання флешу складає 0x80000 (512кБ). Маючи цю інформацію ми можемо розібрати прошивку та внести зміни до образу її файлової системи:
# Вилучення попередніх образів ядра та кореневої файлової системи $ dd if=lp5x4x_1.1.bin of=kernel_orig bs=1K count=2560 $ dd if=lp5x4x_1.1.bin of=jffs2_orig bs=1K skip=2560
# Підключення попереднього образу файлової системи # Створення емуляції блокового пристрою у пам'яті. # Може викликати помилку у випадку використання неперервної області пам'яті іншими програмами та малим її розміром. # Для вирішення цієї проблеми потрібно додати параметр командного рядка ядра, під час завантаження, "vmalloc=512MB". $ modprobe mtdram total_size=65536 erase_size=512 $ modprobe mtdblock $ dd if=root_orig.img of=/dev/mtdblock0 $ mount -t jffs2 /dev/mtdblock0 /mnt/tmp # Копіюємо зміни та файли OpenSCADA у кореневу файлову систему контролеру # Створюємо нову файлову систему із змінами. $ mkfs.jffs2 --root=/mnt/tmp --pad=$((61952*1024)) --eraseblock=512 --output=root.img # Збираємо новий образ прошивки # cat kernel_orig.img root.img > lp5x4x_oscada_1.1.bin
Таким чином ми отримуємо нову прошивку з OpenSCADA у файлі lp5x4x_oscada_1.1.bin, яку можна завантажити до контролеру стандартним чином, описаним у документації "ICP DAS".
3. Зауваження
Оскільки з'ясувалося, що операції з реальними числами виконуються за посередництвом команд сопроцесору FPA (Float Point Acceleration), якого у цьому процесорі просто немає, а виклики самих команд здійснюються через виключення, шляхом імітації у ядрі Linux, то продуктивність математичних обчислень виявляється дуже низькою, навіть у порівнянні з прямим "Software FP", "VFP". Наприклад, обчислення однієї операції sin(pi) здійснюється ~200 мкс, у порівняні із ~20 мкс на N800 з VFP та ~2 мкс на x86, детальніше у таблиці за цим посиланням. Таким чином, розглядати цей контролер як платформу для хоч якихось серйозних обчислень не можна! Мало того, реальні числа, при роботі із FPA, зберігаються по іншому, а саме особливий big-endian, що вимагає перетворення, у випадку із бінарним зовнішнім обміном, до типового little-endian вигляду, наприклад, для DAQ.OPC_UA.
У первинній конфігурації порт COM1 (/dev/ttySA0) використовується у ролі консолі, яка ініціалізується командою ядра "console=/dev/ttySA0". Однак після налаштування це не потрібно, а часто і бажано звільнити ще один COM-порт для інших цілей. Звільнити COM1 від роботи на консоль можно перепризначивши інший пристрій для цієї ролі, наприклад, командою: $ busybox setconsole /dev/tty1. Однак цей метод не повністю звільняє COM-порт та запити втрачаються, вичитуючися паралельним підключенням. Ймовірно потрібно відригувати параметри рядка запуску ядра у завантажувачі U-Boot, хоча увійти до нього можна тільки у положені RS=2, для якого однак параметри ініціалізації відокремлено від основного режиму роботи RS=0. Потрібно добитися входу до U-Boot від основного режиму роботи RS=0!
Переклад триває
В процессе использования созданного программного окружения с OpenSCADA обнаружена странная проблема, которая заключается в падении OpenSCADA при доступе к экземпляру ресурсной строки из разных потоков. Проблема воспроизводится при опросе контроллера по протоколу ModBus/RTU с периодичностью 100мс, опросе отсутствующего модуля посредством DCON на том-же интерфейсе RS485, что и ModBus/RTU. В этот же момент осуществляется периодическая (1 секунда) запись двух регистров в опрашиваемый по протоколу ModBus/RTU контроллер. Падение происходит не сразу, а в течении 10 минут - 5 часов. Разбор проблемы:
(*) В случае отключения записи в контроллер по протоколу ModBus/RTU падения не наблюдаются.
(*) Выяснено, что падения начинают происходить в случае достижения функции TMdContr::modBusReq() модуля DAQ.ModBus, а именно параллельного доступа к свойству объекта контроллера "mPrt", в контексте конструктора "XMLNode req(mPrt);" из разных потоков чтения и записи.
(*) Для выяснения природы проблемы была настроена генерация предсмертного дампа памяти, а так-же собран кроссовый отладчик gdb. При изучении предсмертного дампа памяти выяснено, что происходит разрушение стека и разумных причин в OpenSCADA для данного явления нет, а значит это проблема системного окружения для специфических условий.
(*) При доступе к свойству "mAddr", в первой строке функции TMdContr::modBusReq() и проблемном контексте "XMLNode req(mPrt);" (при неполной записи), падения не замечено.
(*) Проверка вызова второй строки "XMLNode req(mPrt);", при записи и в целом, с постоянной "RTU". При замене на "RTU" в целом падение замечается уже в другом месте. При замене только неполной записи падение не замечается. Вторым и последним местом падения оказалась следующая строка req.setAttr("id",id()). Общее между ними то, что осуществляется доступ к элементу конфигурации строкового типа, использующий объект ресурсного типа "ResString". Вывод, текущее программное окружение некорректно работает с объектом "ResString" при доступе на чтение (немодифицирующий) из двух разных потоков.
(*) Способ хранения объекта "ResString" в элементе конфигурационного поля "TCfg" значения не имеет, а именно — падение наблюдается при прямом хранении "ResString" в "TCfg", а так-же при прямом обращении к объекту "string" внутри "ResString", в случае с "id()".
(*) Проверка при отключении охвата ресурсом — проблемы не решает.
(*) Сборка нового окружения с помощью "PTXDist", и запуск его через "chroot" — при запуске EABI окружения, для TionPro270 из под chroot, происходит ошибка "Illegal instruction!". Не запускается EABI ядро от TionPro270 c похожей ошибкой. Собранный ToolChain из профиля "arm-xscale_hardfloat-linux-gnu_gcc-4.0.4_glibc-2.3.6_binutils-2.17_kernel-2.6.18.ptxconfig" в "OSELAS.Toolchain-2011.11.0" падает с ошибкой сегментации, при запуска OpenSCADA собранной под исходное окружение.
(*) Сборка OpenSCADA с включением всех нужных модулей в библиотеку ядра OpenSCADA проблему так-же не решает.
(*) Осуществлена проверка той же конфигурации на другом PXA270-устройстве (TionPro270) для окончательного выяснения источника проблемы (аппаратного или программного окружения) — конфигурация проработала беспроблемно двое суток.
(*) Заменить в объекте TCfg "ResString" на обычный "string" с выносом ресурса доступа в объект контейнера TConfig, за одно и уменьшив потребление памяти посредством обобщения ресурса доступа к объекту строки — замена осуществлена, проблема осталась.
(*) Вычитать сборку с заменой "ResString" на обычный "string" в TCfg и проверить место текущего падения — место падения тоже.
(*) Взять "crosstool" и собрать несколько более свежий toolchain — собран toolchain "gcc-4.0.2-glibc-2.3.6-arm-xscale-linux-gnu", проблема воспроизводится, скорее всего проблема в работе с памятью текущего ядра. В процессе изучения найдены прецеденты с подобными проблемами в glibc-2.2 — 2.7, которые содержат реализацию malloc небезопасную для потоков (nothread-safe).
(*) Замена аллокатора памяти — не удалось найти рабочей и при этом прозрачной реализации стороннего аллокатора, ptmalloc3 просто падает.
(*) Сборка ToolChain и OpenSCADA со всеми возможными параметрами включения thread-safe — во всех вариантах проблема присутствует, а именно на ToolChain с параметрами GLibC: "--with-tls --with-__thread" и OpenSCADA собрана с параметрами: "-pthread -D_REENTERANT".
(*) Перехват обращений аллокации памяти и оборачивание глобальным ресурсом, функций "С" malloc, free и " new, delete — падения наблюдаются.
(+) Проверка гипотезы проблемности реализации (атомарности) COW (Copy on Write) алгоритма в объекте "string" — копирование из объекта "string" хранилища выполнено посредством val.c_str(), что исключает выполнение COW: подтверждено, что данная проблема связана с алгоритмом COW, а именно с атомарностью доступа к счётчику строк "_Atomic_word _M_refcount;", вероятно из-за устаревшей системы потоков linuxthread.
4. Заключення
У результаті було отримано збірку OpenSCADA для Linux контролерів, ARM-архітектури, фірми "ICP DAS". Збірку можна завантажити безпосередньо на будь який Linux-ARM контролер, розпакувавши її у корні працюючої первинної системи. При цьому однак залишаться дублікати старих базових бібліотек (/lib/*), які, після вдалого перевантаження, можна видалити.
Для контролерів сімейства LP-5x4x створено прошивку зі збіркою OpenSCADA, яку можна завантажити стандартним для даних контролерів чином, який описано у фірмовій документації "ICP DAS". Прошивка для LP-5x4x можливо підійде і для LP-5x3x, однак це не перевірялося!
У зв'язку із застарілою та неоптимальною початковою збіркою Linux оточення від "ICP_DAS", що накладає обмеження на свободу збірки оптимального оточення, по завершенню проекта планується звернутися до фірми "ICP_DAS" з проханням виправити це становище.
(*) Звернення здійснено однак жодної реакції, та навіть відповіді на запит, не послідувало!