Sistema mínimo da API CMSIS RTOS para ARM Cortex STM32
- Publicado em Eletrônica
Conforme já sabemos, a arquitetura de microcontroladores ARM Cortex de 32 bits é bem mais potente e também mais complexa em relação a microcontroladores comuns de 8 ou 16 bits como, por exemplo, um Microchip PIC. Exatamente por essa maior complexidade, o software para esses dispositivos é usualmente programado em linguagem C e, recentemente, houve um esforço de várias indústrias no desenvolvimento e adoção do padrão CMSIS (Cortex Microcontroller Software Standard) que consiste um framework para aplicações embarcadas que visa padronizar a API utilizada na programação desses microcontroladores, simplificando todos os passos no desenvolvimento e manutenção do código-fonte.
Para demonstrarmos o início da utilização do padrão CMSIS e programação dos microcontroladores Cortex-M para leigos, publicamos a seguir um exemplo de código-fonte escrito em C com o intuito de piscar um LED conectado no pino 6 da porta I/O de propósito geral C (GPIOC) para demonstrar o quanto o código fica mais inteligível em relação a uma programação menos profissional com referências diretas a constantes binárias ou hexadecimais. Para o software não ficar muito trivial, estabelecemos um sistema operacional de tempo real (RTOS), também padronizado pelo CMSIS, e configuramos uma thread (código de execução paralela) com prioridade normal para execução do código de acendimento e desligamento do LED com atraso de tempo.
O leitor pode estranhar a ausência de código para programação da inicialização do microcontrolador. Pois uma das finalidades do CMSIS é justamente padronizar e facilitar também o código-fonte de toda a inicialização do microcontrolador (e independente da fabricante, família e modelo da melhor maneira possível). Neste exemplo, bastamos selecionar as opções "ARM::CMSIS:CORE:", "ARM::CMSIS:RTOS:", "Keil::Startup", "Keil::GPIO", "Keil::Device:StdPeriph Drives:GPIO"e "Keil::Device:StdPeriph Drives:RCC" em "Manage Run-Time Environment" na IDE Keil uVision e criarmos um novo arquivo template main em C. Impossível ser mais simples e inteligível: procure um código-fonte similar sem a utilização do CMSIS e perceba a dificuldade em ler o código, compreender rapidamente seu propósito e ter que decorar inúmeras constantes e posicionamento de bits que foram substituídos por estruturas (struct) com descrições melhores em C no CMSIS:
/*---------------------------------------------------------------------------- * CMSIS-RTOS 'main' function template *---------------------------------------------------------------------------*/ #define osObjectsPublic // define objects in main module #include "osObjects.h" // RTOS object definitions #include "stm32f10x.h" // Device header #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #define LEDG GPIO_Pin_6 #define LEDPORT GPIOC #define LEDPORTCLK RCC_APB2Periph_GPIOC // Função thread piscar led void Piscar (void const *argumento){ while (1){ GPIO_SetBits(LEDPORT, LEDG); osDelay(100); GPIO_ResetBits(LEDPORT, LEDG); osDelay(100); } } // Definir prioridade e definir thread osThreadDef(Piscar, osPriorityNormal, 1, 0); /* * main: initialize and start the system */ int main (void) { GPIO_InitTypeDef GPIO_InitStructure; //SystemCoreClockUpdate(); osKernelInitialize (); // initialize CMSIS-RTOS //GPIO structure used to initialize port RCC_APB2PeriphClockCmd(LEDPORTCLK, ENABLE); //select pins to initialize LED GPIO_InitStructure.GPIO_Pin = LEDG; //select output push-pull mode GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //highest speed available GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(LEDPORT, &GPIO_InitStructure); //using same structure we will initialize button pin // create 'thread' functions that start executing, // example: tid_name = osThreadCreate (osThread(name), NULL); osThreadCreate (osThread(Piscar), NULL); osKernelStart (); // start thread execution }