Ім'я: 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 /opt/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 із схожою помилкою. Побудований 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" з проханням виправити це становище.
(*) Звернення здійснено однак жодної реакції, та навіть відповіді на запит, не послідувало!