– CMSIS-Pack
CMSIS
(Cortex Microcontroller Software Interface Standard)
• Task Management
• Timing (delay, timers)
• Signals
• Semaphore / Mutex
• Memory Pool
• Message Queue
• Mail Queue
CMSIS-RTOS Funcionalidades
CMSIS-RTOS Evaluation
CMSIS POSIX VxWorks FreeRTOS X Real-Time
Kernel Process x Thread
Single Threaded Process Multiple Threaded Process Multi Threaded
Preemption
Priority Levels 7 ≥ 32 256 config.(typ. 5) 32
Multiple tasks at same priority level
Static x Dynamic priorities both both both both both
Timers
Resolution / Precision 1ms/1tick - config. config.(typ. 4ms) 1ns/1clk
Single-Shot x Periodic both single-shot single-shot both both
Notification Callback Signal Signal Callback Callback / IRQ /
Assync. Msg Timing services
Delay (Resolution / Precision) 1ms/1tick ticks ticks ticks 1ns/1clk
Microseconds Delay Semaphore / Mutex
Binary/ Counter both both both both both
Mutex
Priority Inheritance (PIP) Priority Ceiling Protocol (PCP) Posix Signals
Flags
(*) implemented with signals
(*) (*) (*)
Memory Pool Malloc/Free only
Message Queue (integers) (*) implemented with Mail Queue
(*) (*) (*) (*)
Douglas Renaux – ESC 2014
Então só funciona para Cortex ?
• A ARM propôs com esta intenção
• Tem a funcionalidade esperada de um RTOS para MCU no segmento 1
• Se fabricantes de RTOS usarem esta API para os RTOS de todos as
arquiteturas, o mercado só tem a ganhar.
Porque é bom para o mercado ?
• Desenvolvedores
– Interface padronizada
• Facilita reuso
• Portabilidade
• Treinamento / Cultura
• Middleware vendors
– Uma biblioteca para todos os RTOS ! – Redução de custo de portabilidade – Mercado tem mais opções a melhor
preço
Planejando uma Aplicação
com RTOS
CMSIS-RTOS: Overview 1/4
• Kernel Information and Control
• osKernelInitialize : Initialize the RTOS kernel.
• osKernelStart : Start the RTOS kernel.
• osKernelRunning : Query if the RTOS kernel is running.
• osKernelSysTick $ : Get RTOS kernel system timer counter.
• osKernelSysTickFrequency $ : RTOS kernel system timer frequency in Hz.
• osKernelSysTickMicroSec $ : Convert microseconds value to RTOS kernel system timer value.
• Thread Management
• osThreadCreate : Start execution of a thread function.
• osThreadTerminate : Stop execution of a thread function.
• osThreadYield : Pass execution to next ready thread function.
• osThreadGetId : Get the thread identifier to reference this thread.
• osThreadSetPriority : Change the execution priority of a thread function.
• osThreadGetPriority : Obtain the current execution priority of a thread function.
CMSIS-RTOS: Overview 2/4
• Generic Wait Functions
• osDelay : Wait for a specified time.
• osWait $ : Wait for any event of the type Signal, Message, or Mail.
• Timer Management $
• osTimerCreate : Define attributes of the timer callback function.
• osTimerStart : Start or restart the timer with a time value.
• osTimerStop : Stop the timer.
• osTimerDelete : Delete a timer.
CMSIS-RTOS: Overview 3/4
• Signal Management
• osSignalSet : Set signal flags of a thread.
• osSignalClear : Reset signal flags of a thread.
• osSignalWait : Suspend execution until specific signal flags are set.
• Mutex Management $
• osMutexCreate : Define and initialize a mutex.
• osMutexWait : Obtain a mutex or Wait until it becomes available.
• osMutexRelease : Release a mutex.
• osMutexDelete : Delete a mutex.
• Semaphore Management $
• osSemaphoreCreate : Define and initialize a semaphore.
• osSemaphoreWait : Obtain a semaphore token or Wait until it becomes available.
• osSemaphoreRelease : Release a semaphore token.
• osSemaphoreDelete : Delete a semaphore.
CMSIS-RTOS: Overview 4/4
• Memory Pool Management $
• osPoolCreate : Define and initialize a fix-size memory pool.
• osPoolAlloc : Allocate a memory block.
• osPoolCAlloc : Allocate a memory block and zero-set this block.
• osPoolFree : Return a memory block to the memory pool.
• Message Queue Management $
• osMessageCreate : Define and initialize a message queue.
• osMessagePut : Put a message into a message queue.
• osMessageGet : Get a message or suspend thread execution until message arrives.
• Mail Queue Management $
• osMailCreate : Define and initialize a mail queue with fix-size memory blocks.
• osMailAlloc : Allocate a memory block.
• osMailCAlloc : Allocate a memory block and zero-set this block.
• osMailPut : Put a memory block into a mail queue.
• osMailGet : Get a mail or suspend thread execution until mail arrives.
• osMailFree : Return a memory block to the mail queue.
•
1. Definição de estruturas de dados como acessar ?
2. Inicialização destas estruturas 3. Operação
Yield GetId
SetPriority
4. Término (opcional)
Ciclo de Vida dos Elementos
do Kernel – exemplo: Thread
1. Definição de estruturas de dados como acessar ?
2. Inicialização destas estruturas 3. Operação
Yield GetId
SetPriority
4. Término (opcional)
osThreadCreate(osThread(job1),NULL);
- Ponteiro para a struct com configuração da tarefa - Ponteiro para argumento da função job1
osThreadDef(job1, osPriorityAboveNormal, 1, 0);
macro
Cria uma struct com:
-nome da função principal desta thread -prioridade
-número máximo de instâncias
-tamanho da pilha (em bytes) obs: 0 = tamanho default
osThread(job1):
uma macro que é substituida por um ponteiro para a estrutura acima
Ciclo de Vida dos Elementos
do Kernel – exemplo: Thread
1. Definição de estruturas de dados como acessar ?
2. Inicialização destas estruturas 3. Operação
Yield GetId
SetPriority
4. Término (opcional)
osThreadCreate(osThread(job1),NULL);
- Ponteiro para a struct com configuração da tarefa - Ponteiro para argumento da função job1
Ciclo de Vida dos Elementos do Kernel – exemplo: Thread
osThreadYield( );
- Libera o processador para a próxima tarefa osThreadGetId( );
- Retorna o identificador desta tarefa (ThreadId) osThreadSetPriority( id, priority);
- Altera o nível de prioridade de uma tarefa osThreadTerminate( id );
- Destrói o TCB eliminando esta tarefa do sistema
Ciclo de Vida dos Elementos do Kernel
Thread Timer Mutex Semaphore Memory
Pool
Message Queue
Mail Queue Definição
osThreadDef osTimerDef osMutexDef osSemaphoreDef osPoolDef osMessageQDef osMailQDef
Acesso
osThread osTimer osMutex osSemaphore osPool osMessageQ osMailQ
Inicializ.
osThreadCreate osTimerCreate osMutexCreate osSemaphoreCreate osPoolCreate osMessageCreate osMailQCreate
Operação
osThreadYield osThreadGetId
osTimerStart osTimerStop
osMutexWait osMutexRelease
osSemaphoreWait osSemaphoreRelease
osPoolAlloc osPoolFree
osMessagePut osMessageGet
osMailAlloc osMailFree osMailPut osMailGet
Término
osThreadTerminate osTimerDelete osMutexDelete osSemaphoreDelete
#include "cmsis_os.h" // CMSIS RTOS header file
void job1 (void const *argument) { // thread function 'job1' while (1) {
: // execute some code
osDelay (10); // delay execution for 10 milliseconds }
}
osThreadDef(job1, osPriorityAboveNormal, 1, 0); // define job1 as thread function
void job2 (void const *argument) { // thread function 'job2' while (1) {
: // execute some code }
}
osThreadDef(job2, osPriorityNormal, 1, 0); // define job2 as thread function int main (void) { // program execution starts here
osKernelInitialize (); // initialize RTOS kernel : // setup and initialize peripherals
osThreadCreate (osThread(job1),NULL); // higher priority osThreadCreate (osThread(job2),NULL);
osKernelStart (); // start kernel with job1 execution }
Duas tarefas independentes
Exemplo:
Acesso a recurso compartilhado
Duas tarefas que
compartilham um recurso
#include "cmsis_os.h" // CMSIS RTOS header file osMutexDef (mutLCD);
void job1 (void const *argument) { // thread function 'job1' while (1) {
osMutexWait (mutLCDid,osWaitForever);
: // resource usage osMutexRelease (mutLCDid);
} }
osThreadDef(job1, osPriorityNormal, 1, 0); // define job1 as thread function
void job2 (void const *argument) { // thread function 'job2' }
osThreadDef(job2, osPriorityNormal, 1, 0); // define job2 as thread function int main (void) { // program execution starts here
osKernelInitialize (); // initialize RTOS kernel : // setup and initialize peripherals
osMutexId mutLCDid = osMutexCreate (osMutex(mutLCD));
osThreadCreate (osThread(job1),NULL);
osThreadCreate (osThread(job2),NULL);
osKernelStart (); // start kernel
Exemplo:
Comunicação por Mensagem
Comunicação ISR -> Tarefa
#include "cmsis_os.h" // CMSIS RTOS header file
enum JoystickMovement {Up, Down, Left, Right, Center, Last = 0x12345678};
osMessageQDef (MsgBox, 2, JoystickMovement ); // Define message queue osMessageQId MsgBox;
void JoySt_ISR(void) {
JoystickMovement JS_value = ReadJoyStick( );
osMessagePut(MsgBox, &JS_value, 0);
}
void PacMan (void const *argument) {
osEvent evt; // osEventMessage,valor, id da MsgBox :
evt = osMessageGet(MsgBox, 5); // timeout 5 ms if (evt == ...) {
: }
osThreadDef(PacMan, osPriorityNormal,1,0); //define PacMan as thread function
int main (void) { // program execution starts here
osKernelInitialize (); // initialize RTOS kernel : // setup and initialize peripherals
MsgBox = osMessageCreate(osMessageQ(MsgBox), NULL);
osThreadCreate (osThread(PacMan));
osKernelStart (); // start kernel with execution of PacMan
Alocação de Memória
• Mesmo papel de malloc e free
• A biblioteca padrão do C não foi concebida para tolerar
chaveamento de contexto, ou seja, não é thread-safe.
Alocação de Memória
void th_alloc_ex (void const *argument) {
uint32_t *address;
osStatus status; // códigos de retorno osPoolId MemPool_Id; // ponteiro para o Pool
osPoolDef(MemPool,8,uint32_t); // Pool para 8 inteiros
MemPool_Id = osPoolCreate(osPool (MemPool)); // NULL = erro address = (uint32_t *) osPoolAlloc(MemPool_Id); //aloca 1
*address = 0xffaabbcc; // acesso escrita status = osPoolFree(MemPool_Id, address); // libera
// osOK, osErrorValue, osErrorParameter osThreadTerminate(osThreadGetId());
}
Conclusão
(1/2)• Por que usar um RTOS ?
• O que se pretende com o CMSIS-RTOS ?
• O papel do CMSIS-RTOS.
• Vários exemplos de uso.