- PVSM.RU - https://www.pvsm.ru -

Arm Mbed OS — популярный проект с открытым исходным кодом ускоряющий разработку устройств для интернета вещей (IoT). Если вы создали свое уникальное процессорное устройство, то первой задачей будет портирование на него какой либо операционной системы (OS).
Здесь представлена пошаговая инструкция по запуску Arm Mbed OS на плате с микроконтроллером семейства NXP Kinetis.
является собственность фирмы ARM и предназначен только для архитектуры ARM. Вопреки распространенному мнению Mbed не написан полностью на C++, не заточен исключительно для Cortex-M и не такой уж новый. Его истоки лежат в далеких 90-х когда фирма Keil создала RTX — операционную систему реального времени (RTOS) для I8051. Впоследствии RTX была Keil-ом перенесена на ARM7 и ARM9, а потом появились Cortex-ы.
Фирма ARM приобрела Keil и RTOS получила название CMSIS-RTOS. Она все еще была целиком написана на С. И наконец с приходом бума IoT и Arduino появился Mbed. Веяния Arduino подвигли сделать оболочку на C++ и упрощенное API со знакомым набором из нескольких десятков пинов, UART-ом и светодиодом, а IoT наполнил проект стеками TCP/IP, Bluetooth Low Energy, 6LoWPAN, Thread… Но RTX5 по прежнему сидит в глубине исходников Mbed OS.
Марка Keil продолжает существовать и в дистрибутиве средств разработки Keil можно найти CMSIS-RTOS с большим выбором промежуточного ПО и примеров портирования на больший ассортимент семейств микроконтроллеров чем предлагает Mbed. Однако это закрытый коммерческий проект.
на которую производится портирование взята здесь для примера и ее схема не имеет большого значения. Важнее микроконтроллер который на ней установлен. Это MKE18F512VLL16 семейства Kinetis фирмы NXP. Основные его параметры:
Ядро — ARM Cortex-M4F 32-Bit
Максимальная частота ядра — 168MHz
Flash 512KB (512K x 8)
RAM 64 KB
100-LQFP (14x14)

Этого микроконтроллера нет в списке поддерживаемых ARM Mbed OS. Можно объяснить тем, что он сравнительно новый.
Микроконтроллер интересен хорошим набором периферии при достаточно скромной цене и высокой частоте ядра. Модуль FlexIO дает возможность создавать нестандартные интерфейсы, которые на обычных микроконтроллерах недоступны.
![]()
Это будет 30-и мегабайтный архив MKE18F512xxx16.zip с таким содержимым:
![]()


Там ищем плату с микроконтроллером максимально похожим на выбранный нами.
Это самый простой пример и его будет легче всего адаптировать для другой платы.

Экспортируем в формате предназначенном для IDE IAR
![]()

Теперь мы получили исходники рабочего проекта Mbed для IAR. Однако полученный проект неудобен для работы.
Все файлы в проекте оказались собраны в одну группу и перемешаны. Проводить поиск и идентификацию какой файл к какому функциональному пакету относится невозможно. В проекте задействованы исходники почти всего middleware проекта Mbed, хотя большинство из них нам сейчас не нужно.
![]()
— С помощью специально написанных утилит на Python проводим несколько операций преобразования.
Во-первых, удаляем из директорий демонстрационного проекта все исходники, не попавшие в проект. Перечень исходников получаем из файла mbed-os-example-blinky.ewp. Утилита называется Clear_from_unused_files_and_dirs.py. Она также удаляет пустые директории, образовавшиеся после удаления файлов.
Во-вторых, с помощью утилиты Convert_ewp_file.py мы переконфигурируем файл проекта mbed-os-example-blinky.ewp так чтобы группы в нем соответствовали директориям проекта. Получаем проект уже с более понятной структурой, где можно удалять или добавлять пакеты. Тут же можем переименовать проект. Для этого редактируем тэг
<configuration> <name>mbed-os-example-blinky</name>
в файле mbed-os-example-blinky.ewp. Изменяем название файла mbed-os-example-blinky.ewp ( в данном случае Test_proj.ewp), исправляем тэг
<path>$WS_DIR$/mbed-os-example-blinky.ewp</path>
в файле mbed-os-example-blinky.eww ( в данном случае на Test_proj.ewp) и изменяем название файла mbed-os-example-blinky.eww на выбранное нами ( в данном случае Test_proj.eww)
В результате имеет такую структуру проекта
![]()

— Изучаем исходники чтобы определить те из них, которые зависят от особенностей микроконтроллера. Для этого удобнее использовать более специализированные редакторы, например SlickEdit или Eclipse. Редактору также стоит сообщить о макросах, объявленных в настройках IDE. Для этого создаем дополнительный заголовочный файл Extra_options.h и копируем туда содержимое Extra Options из IDE IAR.
![]()
Мы готовы к редактированию проекта. Начнем с анализа макросов в файле Extra_options.h. Это делаем в редакторе с соответствующими возможностями, можно делать и в среде IAR.
— Удаляем неиспользуемые макросы, чтобы они не отвлекали внимания при дальнейшем анализе. Остальные сортируем. Около половины макросов оказалось неиспользуемыми.
— В Extra Options вводим новый макрос — TARGET_MKE18F. Он определяет начальный адрес стека в файле mbed_rtx.h. Стек растет в сторону уменьшения адресов. В Mbed принято стек начинать с верхней границы доступной RAM. Для MKE18F ставим эту границу равной 0x20008000UL
— Находим директорию TARGET_K66F. Там хранятся файлы, зависящие от типа микроконтроллера. Их там довольно много — 136 файлов. Создаем рядом с директорией TARGET_K66F свою с названием TARGET_MKE18F .
— Из директории демонстрационного проекта SDK led_blinkyCMSIS копируем в директорию Mbed-ostargetsTARGET_FreescaleTARGET_MCUXpresso_MCUSTARGET_MKE18Fdevice файлы:
• fsl_device_registers.h. (макрос CPU_MK66FN2M0VMD18 в Extra Options заменяем на CPU_MKE18F512VLL16)
• MKE18F16.h
• MKE18F16_features.h
• system_MKE18F16.h
• system_MKE18F16.c
— Удаляем файлы
• MK66F18.h
• MK66F18_features.h
• system_MK66F18.c
• system_MK66F18.h
— В директории TOOLCHAIN_IAR заменяем содержимое на файлы startup_MKE18F16.s и MKE18F512xxx16_flash.icf.
— В проекте IDE IAR также для линкера указываем путь к новому файлу MKE18F512xxx16_flash.icf
— Содержимое директории Mbed-ostargetsTARGET_FreescaleTARGET_MCUXpresso_MCUSTARGET_MKE18Fdrivers стираем и заполняем файлами из директории devicesMKE18F16drivers находящейся в SDK семейства MKE18F512xxx16
— Заменяем файл mbed-ostargetsTARGET_FreescaleTARGET_MCUXpresso_MCUSfsl_common.c на аналогичный из директории devicesMKE18F16drivers, находящейся в SDK семейства MKE18F512xxx16. В директории Mbed-ostargetsTARGET_FreescaleTARGET_MCUXpresso_MCUSTARGET_MKE18Fdrivers такой же файл удаляем.
— Из директории mbed-ostargetsTARGET_FreescaleTARGET_MCUXpresso_MCUSTARGET_MKE18Fdrivers удаляем файлы в названии которых присутствует FreeRTOS.
— Из директории mbed-osfeaturesnetsocketemac-drivers удаляем все файлы связанные с периферией EMAC микроконтроллера K66, поскольку в новом микроконтроллере нет EMAC.
— Cнова применяем утилиту Convert_ewp_file.py
— Компилируем и получаем 267 ошибок. Они все в файлах, находящихся в директории TARGET_MCUXpresso_MCUS и имеющих в большинстве своем в названии суффикс api. С каждым файлом надо разбираться по отдельности. Всего появляется 12 файлов с ошибками.
Это самый важный файл на данном этапе. В нем происходит инициализация тактирования всех подсистем чипа. Функция инициализации RTOS mbed_sdk_init вызывает из этого файла функцию BOARD_BootClockRUN. Заменяем файл fsl_clock_config.c на проверенный файл из проекта led_blinky. Там он называется clock_config.c (переименовываем после копирования в fsl_clock_config.h и исправляем #include в нем там где надо ), а вызов функции BOARD_BootClockRUN в файлах RTOS заменяем на BOARD_BootClockHSRUN, поскольку хотим завести чип на максимальной частоте 168 МГц.
— Рассматриваем оставшиеся файлы. Сразу вызывают сомнения их необходимость. Действительно многие из них представляют собой простые обертки над функциями работы с периферией с упрощенным интерфейсом. Скорее всего, они сделаны для аудитории начинающих программистов, для которых важно подобие API системам на базе Arduino. Мы можем пренебречь этими файлами как не несущими полезной нагрузки, хотя за это нас не примут в сообщество Mbed.
Удаляемые файлы:
API
• analogin_api.c
• analogout_api.c
• dma_api.c
• i2c_api.c
• pwmout_api.c
• spi_api.c
• dma_api_hal.hDrivers
• AnalogIn.cpp
• I2C.cpp
• I2CSlave.cpp
• SPI.cpp
• SPISlave.cpp
• AnalogIn.h
• AnalogOut.h
• I2C.h
• I2CSlave.h
• PwmOut.h
• SPI.h
• SPISlave.hHAL
• analogin_api.h
• analogout_api.h
• i2c_api.h
• pwmout_api.h
• spi_api.h
Список оставшихся файлов, требующих коррекции:
• serial_api.c
• trng_api.c
• flash_api.c
• sleep.c
• us_ticker.c
Эти файлы нельзя просто удалить, так как от них зависят важные сервисы RTOS. Проблема в основном в том, что в семействе MKE18F512xxx16 применяется другое именование периферии чем в MK66FN2M0VMD18, хотя периферия для основных API практически осталась неизменной.
В нем в основном меняем имена функций и перечислений, доставшиеся от чипа K66. Данный файл определяет низкоуровневые функции для отладочного вывода RTOS через UART.
важен тем, что определяет механизм получения точного времени в тиках для RTOS( в нашем примере значение тика равно 1 мкс). Это API используется в функциях задержки RTOS и в сервисах очереди событий с заданным временем активизации на шкале времени. Для организации непрерывного счетчика времени используются связанные каналы 0 и 1 модуля PIT. Канал 0 имеет период в 1 мкс, канал 1 заканчивает цикл через 429 сек (в него загружается 0xFFFFFFFF, счетчик канала декрементируется). Для организации очереди событий используются каналы 2 и 3 модуля PIT с прерываниями от канала 3. Таким образов выясняется, что Mbed занял весь модуль PIT и его больше ни для чего другого использовать нельзя.
реализует аппаратную генерацию случайных чисел. В чипе MKE18F512xxx16 нет такого генератора, поэтому ставим заглушки из стандартной С функции rand. Хороший генератор случайных чисел нужен для протоколов шифрации данных SSL и TLS. Пока такие применять не планируем на нашей плате.
реализует функции входа и выхода из sleep режима. При этом затрагивается работа ускорителя работы с Flash памятью. Нужно скорректировать названия функций, разрешающих и запрещающих кэш Flash памяти.
реализует функции для программирования внутренней Flash памяти. Здесь натолкнулись на то, что в чипах семейства MKE18F512xxx16 могут быть два раздела Flash памяти. Выбрали работу с разделом 0.
— Корректируем макросы со значениями внутренних частот чипа в файле system_MKE18F16.h
В нем должно быть объявление символа __VECTOR_RAM. Это адрес с которого будет размещаться таблица векторов прерываний в RAM. В Mbed OS таблица векторов прерываний всегда копируется из Flash в RAM поскольку она в течении работы может программно модифицироваться системой.
Уперлись в то, что на векторе SVC_Handler стоит заглушка и зациклена на себя. А инициализация Mbed OS вызывает именно этот вектор. Где-то пропущен момент установки правильного вектора. Оказывается забыли подключить к IAR ассемблерные файлы с расширением с большой буквой S. А там самый важный файл с переключателем контекста — irq_cm4f.S. Спасибо Python-у. Исправляем утилиту Convert_ewp_file.py и снова запускаем. Перекомпилируем проект.
Инициализируя порты GPIO можно случайно неправильно инициализировать линии ввода/вывода для отладчика и кварца. В этом случае чип перестает отлаживаться и даже перестает программироваться SWD адаптером J-Link. В нашем случае решить проблему можно просто. Закорачиваем один вывод внешнего кварца на землю, снимаем питание и снова подаем. Наша программа не дойдет до неправильной инициализации GPIO поскольку застрянет на ожидании включения кварца. В это время становится вновь доступным программирование SWD адаптером.
Измерив период мигания светодиода обнаружилось замедление выполнения функции wait дольше чем положено ровно в два раза. Для проверки правильности настроек внутренних частот инициализируем выдачу на внешний вывод клока внутреннего PLL деленного на 8. Видим частоту 21 МГц. Все правильно.
При инициализации частоты тиков RTX параметры которой задаются в файле RTX_Config.h используется переменная SystemCoreClock, а она в свою очередь присваивается в функции BOARD_BootClockHSRUN при инициализации системы и равна 168000000. Тут тоже все правильно.
Проверено в окне TimeLine отладчика IAR частота прерываний системного тика, она равна 1 КГц, тоже правильно.
Оказалась был неправильно инициализирован модуль PIT. Он переставал считать когда RTX переходил в режим SLEEP. А в этот режим RTX переходит при каждом тике если нет активных задач. Таким образом таймер останавливался, но его значения использовались в функции wait чтобы обеспечить максимально точную задержку. А ведь эту ошибку мы унаследовали от официального порта Mbed для K66!
На третий день портирование ARM Mbed OS успешно завершено и светодиод мигает.

Автор: Indemsys
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/mikrokontrollery/290886
Ссылки в тексте:
[1] www.nxp.com: https://www.nxp.com
[2] os.mbed.com/platforms: https://os.mbed.com/platforms/
[3] os.mbed.com/platforms/FRDM-K66F: https://os.mbed.com/platforms/FRDM-K66F/
[4] опыт работы: https://habr.com/post/392839/
[5] os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-blinky/?platform=FRDM-K66F: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-blinky/?platform=FRDM-K66F
[6] os.mbed.com/compiler: https://os.mbed.com/compiler/
[7] Источник: https://habr.com/post/262839/?utm_campaign=262839
Нажмите здесь для печати.