CMSIS2000  0.0.7
 Указатель Структуры данных Файлы Функции Переменные Определения типов Перечисления Элементы перечислений Макросы Группы Страницы
По следам CMSIS

CMSIS – Cortex Microcontroller Software Interface Standard (стандарт на интерфейс ПО микроконтроллеров Cortex) ARM Обеспечивает в качестве части CMSIS следующие программные уровни доступные в реализациях для нескольких компиляторов

  • Уровень Доступа к Основной Периферии: содержит определения имён, определения адресов и вспомогательные функции для доступа к базовым регистрам и периферии. Содержит также аппаратно независимый интерфейс для ядер ОСРВ который включает определения для канала отладки.

Программные уровни предоставляемые партнёрами по производству Чипов представлены как:

  • Уровень Доступа к Периферии Устройств: обеспечивает определение всех устройств
  • Функции Доступа к Периферии (не обязателен): обеспечивает дополнительные вспомогательные функции для периферии

CMSIS определяет для Микроконтроллерных Систем на базе Cortex-M:

  • Общий способ для доступа к периферийным регистрам и общий доступ для определения векторов исключений
  • Имена регистров базовой периферии и имена базовых векторов исключений
  • Не зависимый от чипов интерфейс для ядер ОСРВ, включающий канал отладки

Используя CMSIS совместимые программные компоненты пользователь может легче повторно использовать шаблонный код. CMSIS стремиться обеспечить комбинацию нескольких программных компонентов от нескольких поставщиков промежуточного ПО.

Правила Кодирования и Соглашения CMSIS

Требования

  • Си код CMSIS соответствует правилам MISRA. В случае исключений MISRA отключающие и включающие спец. директивы вставлены для PC-LINT.
  • Используются Стандартные ANSI типы данных включённые в заголовочный ANSI файл Си <stdint.h>.
  • Константы #define включающие выражения обрамлены скобками.
  • Переменные и параметры имеют полные типы данных.
  • Все функции входящие в уровень доступа к основной периферий повторно входимы.
  • Код и уровеня доступа к основной периферий не имеет блокирующего кода, что означает ожидающие/опрашивающие функции переносятся на другие уровни ПО.
  • Для каждого исключения/прерывания определён:
    • обработчик исключения/прерывания с суффиксом _Handler (для исключений) или _IRQHandler (для прерываний)
    • обработчик по умолчанию (определён как weak), что содержит бесконечный цикл.
    • макрос #define с номером прерывания с суффиксом _IRQn.

Рекомендации

CMSIS рекомендует следующие правила для идентификаторов:

  • ЗАГЛАВНЫЕ БУКВЫ для идентификации Базовых Регистров, Периферийных Регистров, Инструкций ЦП.
  • ВербльюжиИмена для идентификации функций доступа к периферий и прерываний.
  • Приставка ПРИРЕФЕРИЯ_для идентификации функций что принадлежат соответствующей периферии.
  • Комментарии Doxygen для всех включаемых функций как описано ниже:

Требования к комментариям:

  • Комментарии использую стиль стандарта ANSI C90 (/ * такие комментарии * /) или стиль C++ (// такие комментарии). Предполагается, что программные средства на сегодня поддерживают стиль комментариев С++.
  • Комментарии Функций обеспечивают для каждой функции следующую информацию:

    • однострочное короткое описание функции.
    • детальное объяснение параметров.
    • детальное описание возвращаемых значений .
    • детальное описание собственно функции.

    Пример Doxygen:

      /**
       * @brief  Enable Interrupt in NVIC Interrupt Controller
       * @param  IRQn  interrupt number that specifies the interrupt
       * @return none.
       * Enable the specified interrupt in the NVIC Interrupt Controller.
       * Other settings of the interrupt such as priority are not affected.
       */

/**

Типы данных и Описатели типа Ввода/Вывода CMSIS

HAL Cortex-M использует стандартные типы данных из заголовочного файла стандарта ANSI <stdint.h>. Описатели типа ВВ используются для доступа к периферийным переменным. Описатели типа ВВ составлены для использования автоматической генерации отладочной информации от периферийных регистров.

IO Type Qualifier #define Описание
__I volatile constДоступны только на чтение
__O volatile Доступны только на запись
__IO volatile Доступны на чтение и на запись

номер версии CMSIS

Файлы core_cm0.h, core_cm3.h, core_cm4.h содержат номера версии CMSIS в виде следующих определений:

core_cm0.h:

#define __CM0_CMSIS_VERSION_MAIN (0x02) /* [31:16] main version * /
#define __CM0_CMSIS_VERSION_SUB (0x00) /* [15:0] sub version * /
#define __CM1_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | __CM4_CMSIS_VERSION_SUB)

core_cm3.h:

#define __CM3_CMSIS_VERSION_MAIN (0x02) /* [31:16] main version * /
#define __CM3_CMSIS_VERSION_SUB (0x00) /* [15:0] sub version * /
#define __CM3_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | __CM4_CMSIS_VERSION_SUB)

core_cm4.h:

#define __CM4_CMSIS_VERSION_MAIN (0x02) /* [31:16] main version * /
#define __CM4_CMSIS_VERSION_SUB (0x00) /* [15:0] sub version * /
#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | __CM4_CMSIS_VERSION_SUB)

номер ядра Cortex

Файлы core_cm0.h, core_cm3.h, core_cm4.h содержат номер версии ядра Cortex в виде следующих определений:

core_cm0.h:

#define __CORTEX_M (0x00)

core_cm3.h:

#define __CORTEX_M (0x03)

core_cm4.h:

#define __CORTEX_M (0x04)

файлы CMSIS

Далее описаны созданные в проекте CMSIS файлы, для того чтобы обеспечивать доступ к ядру Cortex-M и периферии.

FileСопровождающий Описание
device.h Device specific (provided by silicon partner) Defines the peripherals for the actual device. The file may use several other include files to define the peripherals of the actual device.
core_cm0.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет основную периферию под ЦП семейства Cortex-M0 CPU.
core_cm3.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет основную периферию под ЦП семейства Cortex-M3 CPU.
core_cm4.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет основную периферию под ЦП семейства Cortex-M4 CPU.
core_cm4_simd.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет SIMD функции для ядра Cortex-M4.
core_cmFunc.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет функции доступа к регистрам ядра Cortex-M.
core_cmInstr.h ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Определяет инструкции для ядра Cortex-M.
core_cm0.c ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Обеспечивает вспомогательные функции для доступа к регистрам ядра.
core_cm3.c ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Обеспечивает вспомогательные функции для доступа к регистрам ядра.
core_cm4.c ARM (для компиляторов RealView ARMCC, IAR, и GNU GCC) Обеспечивает вспомогательные функции для доступа к регистрам ядра.
startup_device ARM (адаптировано партнёром соответствующего компилятора / производителем чипов) Provides the Cortex-M startup code and the complete (device specific) Interrupt Vector Table
system_device ARM (адаптировано производителем чипов) Обеспечивает устройство-специфичный файл настройки для устройства. Настраивает устройство, запуская обычно тактовый генератор (ФАПЧ), являющийся частью микроконтроллерного устройства.

файл device.h

Файл device.h создаётся производителем чипов и является главным фалом, который вкладывает и использует программист в коде на языке Си. Файл содержит:

  • Номера Прерываний : объявляются номера прерываний и исключений специфичных и для ядра и устройства .

Настройки для core_cm0.h / core_cm3.h / core_cm4.h: Путём настройки и включения заголовочных файлов core_cm0.h / core_cm3.h / core_cm4.h is обеспечивается доступ к регистрам процессора и периферии.

  • Уровень Доступа к Основной Периферии: Содержит определения всех структур данных и привязку адресов для переферии спицифичной для чипа.
  • Функции доступа к периферии (не обязательна): обеспечивает дополнительные вспомогательные функции, которые полезны для программирования периферии. Функции могут быть сделаны как inline функции или в качестве внешних ссылок на библиотеки обеспечиваемые производителем чипа.

Определение номеров прерываний

Для доступа к спецефичным для устройства прерываниям файл device.h определяет номера прерываний IRQn для всего устройства используя enum typedef как показано далее

typedef enum IRQn
{
/****** Cortex-M3 Processor Exceptions/Interrupt Numbers ************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
HardFault_IRQn = -13, /*!< 3 Cortex-M3 Hard Fault Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers ****************************************************************/
WWDG_STM_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_STM_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
:
:

Определения специфичные для устройств

Следующие определения специфичные для устройств устанавливаются в заголовочном файле устройства и используются для настройки ядра Cortex-M. Некоторые из настроек отражены уровнем CMSIS в виде использования #define как описано далее.

Несколько опций в core_cm#.h настраиваются следующими определениями, которые должны быть определены перед командой препроцессора include <core_cm#.h>. Если определения пропущены то используются настройки по умолчанию.

#define Ядро Значение По умолчанию Определение
__CM0_REV M0 0x0000 0x0000 номер ревизии ядра ([15:8] номер ревизии , [7:0] номер заплатки)
__CM3_REV M3 0x0101 | 0x0200 0x0200 номер ревизии ядра ([15:8] номер ревизии , [7:0] номер заплатки)
__CM4_REV M4 0x0000 0x0000 номер ревизии ядра ([15:8] омер ревизии, [7:0] номер заплатки)
__NVIC_PRIO_BITS M0, M3, M4 2 .. 8

2 (M0)

4 (CM3, CM4)

Число битов приоритета реализованных в NVIC (специфично для устройства)

__MPU_PRESENT M0, M3, M4 0 | 1 0 Определяет наличие MPU
__FPU_PRESENT M4 0 | 1 0 Определяет наличие FPU
__Vendor_SysTickConfig M0, M3, M4 0 | 1 0 Когда определение установлено в 1 функция SysTickConfig в core_cm3.h исключается. В этом случае файл device.h должен содержать реализацию данной функции определяемую поставщиком чипа.

Уровень доступа к основной периферии

Каждая периферия использует префикс который состоит из<аббревиатуры устройства>_ и <имени периферии>_ для обозначения регистров которые предоставляет доступ к соответствующей перифериии. Суть этого состоит в том чтобы избежать коллизий происходящий из-за коротких имён. Если существует более чем одно периферийное устройство одного типа, идентификаторы должны иметь суффикс (число или букву). Например:

  • <аббревиатура устройства>_UART_Type: определеят общее расположения регистров все каналов UART в устройстве.
typedef struct
{
union {
__I uint8_t RBR; /*!< Offset: 0x000 (R/ ) Receiver Buffer Register */
__O uint8_t THR; /*!< Offset: 0x000 ( /W) Transmit Holding Register */
__IO uint8_t DLL; /*!< Offset: 0x000 (R/W) Divisor Latch LSB */
uint32_t RESERVED0;
};
union {
__IO uint8_t DLM; /*!< Offset: 0x004 (R/W) Divisor Latch MSB */
__IO uint32_t IER; /*!< Offset: 0x004 (R/W) Interrupt Enable Register */
};
union {
__I uint32_t IIR; /*!< Offset: 0x008 (R/ ) Interrupt ID Register */
__O uint8_t FCR; /*!< Offset: 0x008 ( /W) FIFO Control Register */
};
__IO uint8_t LCR; /*!< Offset: 0x00C (R/W) Line Control Register */
uint8_t RESERVED1[7];
__I uint8_t LSR; /*!< Offset: 0x014 (R/ ) Line Status Register */
uint8_t RESERVED2[7];
__IO uint8_t SCR; /*!< Offset: 0x01C (R/W) Scratch Pad Register */
uint8_t RESERVED3[3];
__IO uint32_t ACR; /*!< Offset: 0x020 (R/W) Autobaud Control Register */
__IO uint8_t ICR; /*!< Offset: 0x024 (R/W) IrDA Control Register */
uint8_t RESERVED4[3];
__IO uint8_t FDR; /*!< Offset: 0x028 (R/W) Fractional Divider Register */
uint8_t RESERVED5[7];
__IO uint8_t TER; /*!< Offset: 0x030 (R/W) Transmit Enable Register */
uint8_t RESERVED6[39];
__I uint8_t FIFOLVL; /*!< Offset: 0x058 (R/ ) FIFO Level Register */
  • <device abbreviation>_UART1: указывает на структуру регистров, которая соотвествует конкретному UART. Например UART1->DR является регистром данных для UART1.
#define LPC_UART2 ((LPC_UART_TypeDef *) LPC_UART2_BASE )
#define LPC_UART3 ((LPC_UART_TypeDef *) LPC_UART3_BASE )

Минимальные требования

Для доступа к периферийным регистра и соответствующей функции в устройстве файлы и device.h and core_cm0.h / core_cm3.h определяют как минимум:

  • Расположение Регистров в виде Typedef для каждого периферийного устройство со всеми именами регистров . Имена начинающиеся на RESERVE используются для обозначения пробелов в структуре для выравнивания адресов периферийных регистров. Например:
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
  • Базовый Адрес для каждого периферийного устройства (в случае если несколько периферийных устройств используют тот же набор регистров, должны быть определены несколько базовых адресов ). Например:
#define SysTick_BASE (SCS_BASE + 0x0010) /* SysTick Base Address */
  • Определение для каждого периферийного устройства (в случае если несколько периферийных устройств используют тот же набор регистров, определены несколько определений, т. е. LPC_UART0, LPC_UART2). . Например:
#define SysTick ((SysTick_Type *) SysTick_BASE) /* SysTick access definition */

Эти определения позволяют иметь доступ к периферийным регистром из кода пользователя простым присваиванием в виде:

SysTick->CTRL = 0;

Дополнительные определения

Дополнительно файл device.h может определять:

  • константы #define для упрощения доступа к периферийным регистром. Эти константы определяют позиции битов или другие специфические шаблоны и маски которые требуются для доступа к регистрам. Эти идентификаторы начинаются с <аббревиатуры устройства>_ и <имени периферии>_. Рекомендуется использовать ЗАГЛАВНЫЕ буквы в таких константах #define.
  • Фнкции которые обеспечивают более сложные взаимодействия с периферией(например опрос статуса перед отправкой данных в регистр). Опять же, эти функции начинаются с <аббревиатуры устройства>_ и <имени периферии>_.

Запуск устройства

Шаблонный файл для запуска устройства сопровождается ARM для каждого поддерживаемого компилятор. Он адаптируется производителем чипов для включения векторов прерываний под все специфичные для устройства обработчики прерываний. Каждый обработчик прерывания объявлен как функция типа weak как пустой обработчик. Однако обработчик прерывания может быть использован прямо в прикладном ПО без каких либо требования для доработки файла запуска (файл startup_device).

Следующие имена исключений зафиксированы и определены в начале таблицы векторов прерываний для Cortex-M0:

__Vectors DCD __initial_sp ; Top of Stack
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler

Следующие имена исключений зафиксированы и определены в начале таблицы векторов прерываний для Cortex-M3:

__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler

Далее представлены примеры перываний специфичных для конекретных устройств

; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper

Устройствоспецифичные прерывания должны иметь неопределённые обработчики, которые могут быть переопределены в коде разработчика. Далее представлен пример таких неопределенных функций.

EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMPER_IRQHandler [WEAK]
:
:
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
:
:
B .
ENDP

Приложение пользователя может просто определить функцию обработки прерывания используя имя обработчика, как показано далее:

void WWDG_IRQHandler(void)
{
:
:
}

/**

файл system_device.с

Шаблон файла system_device предоставляется ARM, но адаптируется производителем чипов для соотвествия их конкретному устройству. В качесве минимальных требований файл должен обеспечивать функцию конфигурации устройства, а также глобальную переменную настройки частоты. Он настраивает устройство и обычно инициализирует тактовый генератор (ФАПЧ) который является частью микроконтроллерного устройства.

Файл system_device.c должен обеспечивать в как минимум функцию SystemInit как показано далее.

Определение функцииОписание
void SystemInit (void)

Установка микроконтроллерной системы. Обычно эта функция устаноавливает тактовый генератор (ФАПЧ), являющийся частью микроконтроллера. Для систем с переменной частотой часов функция также обнавляет значение переменной SystemCoreClock. SystemInit вызвается и файла запуска.

void SystemCoreClockUpdate (void)

Обновляет переменную SystemCoreClock и должна быть вызываема всегда когда частота ядра меняется в течений выполнения программы. SystemCoreClockUpdate() оценивает настройки регистра часов и вычисляет текущую частоту ядра.

Также частью файла system_device.c является переменная SystemCoreClock, которая содержит текущую частоту ядра ЦП как показано далее.

Определение переменнойОписание
uint32_t SystemCoreClock

Содержит частоту ядра (ту которая обеспечивает частоту вызова системного таймера SysTick и частоту процессора). Эта переменная может быть использована приложениями пользователя для установки системного таймера или для настройки других параметров. Она также может быть использована отладчиком для опроса частоты во время выполнения отладки или для настройки скорости отладки. SystemCoreClock устанавливается в правильное предопредленное значение.

Компилятор должен быть настроен так, чтобы не удалять эту переменную даже если приложение ее не использует. Для отладочных систем важно, чтобы переменная физически присутсвовала в памяти так, чтобы отладчик мог быть сконфигурирован ею.

Замечание:

  • Эти определения содержат минимальные требования для файла system_device.c. Этот файл может также содержать и другие функции и переменные для более гибкой настройки микроконтроллера.