Перейти к содержанию

CMSIS

Когда в программе для STM32 написано NVIC_EnableIRQ() или SysTick_Config(), это не HAL от ST, а CMSIS — общий для всех Cortex-M слой от Arm. Он одинаков у STM32, GD32, NXP и Nordic, поэтому код работы с ядром переносится между ними без переделки.

Обновлено Редакция GAW

CMSIS (Common Microcontroller Software Interface Standard) — набор программных интерфейсов, компонентов и спецификаций Arm для микроконтроллеров на ядрах Cortex-M. По документации CMSIS 6 он начинался как независимый от производителя уровень абстракции для Cortex-M; при этом CMSIS не вводит толстого программного слоя и не стандартизует периферию (CMSIS 6, Introduction). Распространяется бесплатно по лицензии Apache 2.0.

Из чего состоит

КомпонентЧто даёт
CMSIS-Coreдоступ к ядру: регистры NVIC, SCB, SysTick, функции вроде NVIC_EnableIRQ, специальные команды
CMSIS-Driverобщие интерфейсы драйверов периферии для промежуточного ПО
CMSIS-RTOS2общий API операционных систем реального времени
CMSIS-DSP, CMSIS-NNоптимизированные функции обработки сигналов и нейросетей
CMSIS-DAPпрошивка отладочных адаптеров для порта отладки CoreSight
CMSIS-SVD, CMSIS-Packописание регистров устройства для отладчика и формат пакетов поддержки

По списку компонентов в документации CMSIS 6. Для повседневной работы важнее всего CMSIS-Core: это заголовок ядра вроде core_cm3.h или core_cm4.h. Для STM32 цепочка такая: заголовок устройства от ST (stm32f103xb.h) описывает регистры периферии и номера прерываний и подключает core_cm3.h от Arm, а HAL и LL построены поверх этих заголовков — см. статью «HAL, LL и регистры CMSIS в STM32».

Что внутри CMSIS-Core

Примеры из core_cm3.h версии 6.4.0:

  • Функции контроллера прерываний NVIC: NVIC_EnableIRQ(), NVIC_SetPriority(). Приоритет сдвигается на (8 − __NVIC_PRIO_BITS) бит, потому что у кристалла реализованы только старшие биты поля; число бит задаёт заголовок устройства, у STM32F1 их 4. Если оно не задано, CMSIS берёт 3 и выдаёт предупреждение.
  • SysTick_Config(ticks) — настраивает SysTick на прерывание каждые ticks тактов: пишет в LOAD значение ticks − 1, ставит прерыванию наименьший приоритет и запускает счётчик. Если значение не влезает в 24-битный регистр, функция возвращает 1.
  • ITM_SendChar() — вывод символа через ITM для отладочной печати.
  • Обёртки команд ядра: __enable_irq(), __disable_irq(), барьеры __DSB() и __ISB().

Код запуска, таблицу векторов и SystemInit() по шаблонам CMSIS даёт производитель — об этом статья «Код запуска». В версии 6.0.0 заголовки CMSIS-Core изменились несовместимо с CMSIS 5, поэтому старые проекты переносят по руководству Arm. Обзор семейства ядер — на странице «ARM Cortex-M».

Частые вопросы

Чем CMSIS отличается от HAL STM32?

CMSIS-Core от Arm описывает ядро: регистры NVIC, SCB, SysTick и функции работы с ними, одинаковые для всех Cortex-M. Периферию — GPIO, UART, таймеры — CMSIS не стандартизует, документация Arm говорит об этом прямо. Структуры регистров периферии даёт производитель в заголовке устройства, а HAL и LL — это уже его библиотеки поверх этих заголовков.

Можно ли писать под STM32 только на CMSIS, без HAL?

Да. Достаточно заголовка устройства от ST (например, stm32f103xb.h), который сам подключает core_cm3.h, кода запуска и файла system_stm32f1xx.c. Периферию тогда настраивают прямой записью в регистры по справочному руководству. Так пишут, когда нужен маленький и предсказуемый код.

Почему после перехода на CMSIS 6 перестал собираться старый проект?

Потому что в версии 6.0.0 заголовки CMSIS-Core для Cortex-M изменились несовместимо с прежними версиями, о чём предупреждает документация CMSIS 6 и даёт руководства по переносу. Проще всего взять версию CMSIS, которая идёт в пакете производителя вместе с заголовками устройства.

Источники

  1. Arm. CMSIS 6 Documentation: Introduction (arm-software.github.io/CMSIS_6) — Introduction: CMSIS (Common Microcontroller Software Interface Standard) — набор API, программных компонентов, инструментов и процессов; начинался как независимый от производителя уровень абстракции для Cortex-M, позже расширен на младшие Cortex-A; не вводит большой программный слой и не стандартизует периферию; компоненты: базовые CMSIS-Core, CMSIS-Driver, CMSIS-RTOS2 в одном пакете Arm::CMSIS; расширенные CMSIS-DSP, CMSIS-NN, CMSIS-View, CMSIS-Compiler; инструменты CMSIS-Toolbox, CMSIS-DAP, CMSIS-Zone, CMSIS-Stream; спецификации CMSIS-Pack и CMSIS-SVD; поставляется в формате CMSIS-Pack; в версии 6.0.0 заголовки CMSIS-Core для Cortex-M изменены несовместимо с прежними версиями; распространяется бесплатно по лицензии Apache 2.0
  2. Arm. CMSIS 6 v6.4.0: CMSIS/Core/Include/core_cm3.h (GitHub, Apache-2.0) — если в заголовке устройства не задан __NVIC_PRIO_BITS, берётся 3 с предупреждением; __NVIC_SetPriority сдвигает приоритет на (8 − __NVIC_PRIO_BITS) бит и пишет в NVIC->IPR или SCB->SHPR; SysTick_Config(ticks) пишет LOAD = ticks − 1, ставит SysTick наименьший приоритет, обнуляет VAL и включает счётчик с прерыванием, возвращает 1, если значение не влезает в регистр (маска SysTick_LOAD_RELOAD_Msk = 0xFFFFFF, 24 бита); при __Vendor_SysTickConfig = 1 функцию даёт производитель; ITM_SendChar — вывод символа через ITM; cmsis_gcc.h — __enable_irq, __disable_irq, __DSB, __ISB
  3. STMicroelectronics. CMSIS device headers cmsis-device-f1 (GitHub, Apache-2.0) — stm32f1xx-заголовки устройства: #define __NVIC_PRIO_BITS 4U — STM32 использует 4 бита уровней приоритета
  4. Arm. CMSIS 6 README (github.com/ARM-software/CMSIS_6) — структура репозитория: CMSIS/Core, CMSIS/Driver, CMSIS/RTOS2, документация; связанные репозитории CMSIS-DSP, CMSIS-NN, CMSIS-FreeRTOS, CMSIS-RTX, CMSIS-Driver; лицензия Apache-2.0

Нашли ошибку?