Имя: 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.
Процессор контроллера имеет следующие технические характеристики:
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_xscale.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 (работа проверена).
UI.WebVision — Модуль визуализатора пользовательских интерфейсов в UI.VCAEngine посредством Web-интерфейса (работа проверена).
UI.WebUser — Модуль свободной пользовательской визуализации посредством Web-интерфейса (работа проверена).
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 мкс, в сравнении с ~15 мкс на 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" с просьбой исправить данное положение дел.
(*) Обращение осуществлено однако никакой реакции, вплоть до ответа на запрос, не последовало!