Окончание, начало № 62000
Использование «свободных» программных средств
для разработки встраиваемых систем на основе 32-разрядных к1БС-процессоров
Сергей Емец
Сборка eCos и примеров приложений
После того как компилятор собран (в рассматриваемом примере это arm-elf-gcc), можно компилировать операционную систему и приложения. Прежде всего, операционную систему следует сконфигурировать для требуемой архитектуры, платы, поддержки драйверов и т. д. Данный шаг различается для пользователей Windows и Linux. В Windows существует графическая оболочка — eCos Configuration Tool, назначение которой состоит в том, чтобы сформировать требуемые make-файлы для последующей сборки приложения. Чтобы запускать эту программу, не требуется компилятор и другие средства, поэтому для ознакомления с возможностями операционной системы eCos можно просто инсталлировать eCos и поиграть с eCos Configuration Tool. Для Linux данную работу исполняет утилита, работающая с командной строкой (в версии 1.2.1 для этих целей существовал TCL-скрипт с графическим интерфейсом, но в версии 1.3.1 он отсутствует).
В качестве примера рассмотрим сборку приложения для отладочной платы AEB-1 (ht tp://ww w.arm. c om/Documentation/Overviews/AEB).
При работе с графическим средством следует выбрать соответствующий hardware template — меню build/template... (в данном случае — AEB), далее следует сконфигурировать требуемые опции. Следует остановиться на структуре eCos — она представляет собой набор пакетов (package), каждый из которых может быть включен в текущую конфигурацию. Список пакетов в стандартной поставке такой: HAL — уровень, зависящий от конкретного железа. Для переноса eCos на новую платформу следует вносить изменения в файлы данного пакета. Infrastructure — поддержка отладочных средств; Kernel — ядро ОС — поддержка многозадачности; С library — набор стандартных функций библиотеки С + библиотека вычислений с плавающей точкой; ulTRON — поддержка стандарта ulTRON 3.02; и набор драйверов (драйвер последовательного порта имеется для всех платформ). Каждый из пакетов требует определенной настройки опций (число которых весьма велико).
Есть несколько предопределенных наборов пакетов — default, minimum, stubs и т. д., в которых предопределены наборы пакетов и опций для наиболее
распространенных приложений. В данном случае можно использовать default, заменив тип платы revision B на revision C.
После этого следует записать конфигурацию в отдельно взятый директорий и произвести сборку библиотеки, содержащей ядро ОС (меню build/library). После компиляции и линковки в данном директории будет создан поддиректорий с именем NAME_install (NAME — имя проекта), в котором будет находиться собранная ОС.
Для сборки ядра под Linux следует создать директорий, в котором предполагается собрать ядро, и запустить в нем утилиту /ecos-1.3.1/tools/bin/ecoscon-fig new aeb, после чего будет создан файл ecos.ecc. Этот файл содержит информацию о конфигурации ОС. С использованием текстового редактора в данный файл вносятся требуемые изменения. После чего исполняется команда /ecos-1.3.1/tools/bin/ecoscon-fig tree, которая создает makefile для сборки ядра. Затем make собирает ядро в директории install.
Сборка приложений происходит так же, как и в Windows.
Вместе с eCos поставляется несколько примеров, для иллюстрации работоспособности системы возьмем пример twothread.c:
include <cyg/kernel/kapi.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
/* now declare (and allocate space for) some kernel objects, like the two threads we will use */
cyg_thread thread_s[2]; /* space for two thread objects */
char stack[2][4096];
/* space for two 4K stacks */
/* now the handles for the threads */ cyg_handle_t simple_threadA, simple_threadB;
/* and now variables for the procedure which is the thread */ cyg_thread_entry_t simple_program;
/* and now a mutex to protect calls to the C library */ cyg_mutex_t cliblock;
/* we install our own startup routine which sets up threads */ void cyg_user_start(void)
{
printf(«Entering twothreads' cyg_user_start() function\n»); cyg_mutex_init(&cliblock);
cyg_thread_create(4, simple_program, (cyg_addrword_t) 0, «Thread A», (void *) stack[0], 4096,
&simple_threadA, &thread_s[0]);
cyg_thread_create(4, simple_program, (cyg_addrword_t) 1, «Thread B», (void *) stack[1], 4096,
&simple_threadB, &thread_s[1]);
cyg_thread_resume(simple_threadA);
cyg_thread_resume(simple_threadB);
}
/* this is a simple program which runs in a thread */ void simple_program(cyg_addrword_t data)
{
int message = (int) data; int delay;
printf(«Beginning execution; thread data is %od\n», message);
cyg_thread_delay(200);
for (;;) {
delay = 200 + (rand() % 50);
/* note: printf() must be protected by a call to cyg_mutex_lock() */ cyg_mutex_lock(&cliblock); {
printf(«Thread %od and now a delay of %d clock ticks\n», message, delay);
}
cyg_mutex_unlock(&cliblock);
cyg_thread_delay(delay);
}
}
Для того чтобы понять принцип работы этого примера, нужно посмотреть документацию на eCos API, которая выполнена подробно и грамотно. При запуске вызывается функция cyg_user_start (есть возможность сконфигурировать ОС так, что будет вызываться main), которая запускает два параллельных процесса simple_program, печатающих свое сообщение через случайный промежуток времени. Мутекс cliblock используется для того, чтобы обеспечить процессу монопольное использование libc. Это нужно хотя бы для того, чтобы исполнение printf не было прервано другим процессом.
Для сборки примера следует внести изменения в Makefile: указать расположение скомпилированного ядра ОС, которое было создано с помощью eCos Configuration Tool; указать, какой компилятор должен быть использован для сборки приложения (XCC = arm-elf-gcc-mcpu=arm7di # AEB). В Makefile символ # используется как начало однострочного комментария (аналог // в C++), поэтому достаточно «раскомментировать» требуемую строчку. Путь к NAME_install можно узнать, выполнив команду pwd (находясь в данном директории). В Makefile следует присвоить переменной PKG_INSTALL_DIR этот путь (например, PKG_INSTALL_DIR = /aeb/aeb_install). После этого можно исполнить команду make twothreads, после завершения которой будет создан исполняемый файл twothreads.exe, для загрузки в плату. Данный файл содержит отладочную информацию для gdb. Для того чтобы убрать ее и подготовить файл для автономного исполнения, используются следующие утилиты arm-elf-strip и arm-elf-objcopy. Так как при конфигурировании eCos для AEB по умолчанию используется RAM (код программы располагается в ОЗУ) можно воспользоваться встроенным в плату загрузчиком. Загрузчику требуются файлы в формате UUCODE (используется при пересылке файлов по электронной почте), поэтому потребуется утилита кодировщика. Для преобразования потребуются следующие команды:
$ arm-elf-strip.exe --strip-all twothreads.exe $ arm-elf-objcopy.exe -O binary twothreads.exe twothreads.bin $ uuencode twothreads.bin twothreads.bin I tr 'M ' ' > twothreads.UU
После чего можно загрузить файл в плату и исполнить его. (Мне пришлось выполнить операцию под Linux, так как не удалось сконфигурировать терминал в Windows.)
Выход программы twotheads:
(gdb)c Continuing.
Thread 0: and now a delay of 239 clock ticks Thread 1: and now a delay of 230 clock ticks Thread 1: and now a delay of 221 clock ticks Thread 0: and now a delay of 214 clock ticks Thread 1: and now a delay of 224 clock ticks Thread 0: and now a delay of 243 clock ticks Thread 1: and now a delay of 210 clock ticks Thread 0: and now a delay of 224 clock ticks Thread 1: and now a delay of 207 clock ticks
Отладка приложения с помощью GBD
Так как программа заработала, отладка не нужна. Но для иллюстрации работы gdb можно загрузить данный пример в плату под контролем gdb. Работа с симулятором в данном случае невозможна, потому что симулятор не поддерживает архитектуру платы (не будет работать драйвер последовательного порта). Для работы с платой возможен вариант использования разных мониторов. Стандартно отладочные платы с ARM процессорами поставляются с монитором ANGEL, который поддерживается gdb. Кроме этого можно загрузить в плату монитор gdb, бинарные скомпилированные образы которого для различных архитектур можно найти в директории loaders. Я предпочитаю использовать второй вариант, так как доступны исходные коды и можно установить любую скорость соединения. Запустив gdb (с графическим интерфейсом — Insight), нужно подключить его к плате, указав скорость соединения, порт и тип монитора, после чего нужно загрузить программу (download). Программа готова к отладке: для запуска из окна gdb-консоли следует отдать команду с (continue).
Следует заметить, что в gdb для ARM существуют некоторые недоработки, например многопоточная отладка или процедура запуска приложения, но программа работает устойчиво как под Linux, так и под Windows.
Таким образом, использование GNU средств eCos и GCC оправдано в больших проектах, разработка которых ведется на C++ (сама eCos также написана на C++). Так как в eCos поддерживаются все стандартные библиотеки, то возможна отладка приложений на ПК, а затем перенос их в «железо» без каких-либо изменений. Многозадачность в настоящее время является необходимым требованием для RTOS, и различные механизмы многозадачности реализованы в eCos. Для более простых приложений, не требующих многозадачности, можно использовать компилятор GCC отдельно. Наличие документации по структуре компилятора позволяет конфигурировать его для использования на большом количестве архитектур. Разработчикам, использующим в проектах 32-разрядные процессоры, имеет смысл обратить внимание на средства разработки GNU, которых существует гораздо больше, чем упоминалось в данной статье. NH
«■■■I * ■■■■■ ■........................................
Рис. 1. Пример конфигурирования и сборки eCos для ARM AEB-1C
' - и ■■■ ч______________________________________________________________I - ь - г. —| Ё
Рис. 2. Окна отладчика ARM-ELF-GDB и окно bash с командой сборки приложения twothreads