EL68E Prog Concorrente - dainf.ct.utfpr.edu.brdainf.ct.utfpr.edu.br/~douglas/EL68E Prog Concorrente...

60
EL68E Sistemas Embarcados Prof. Douglas RENAUX

Transcript of EL68E Prog Concorrente - dainf.ct.utfpr.edu.brdainf.ct.utfpr.edu.br/~douglas/EL68E Prog Concorrente...

EL68ESistemas Embarcados

Prof. Douglas RENAUX

Programação Concorrente1 – Infra-estrutura

• Prog. Sequencial x Prog Concorrente• Pessoa x Equipe

• Processadores Virtuais

• Regiões de Memória de Prog. Sequencial

• Regiões de Memória de Prog. Concorrente• Multi-processo / MMU / mem. Virtual

• Multi-threaded

Problema da Exclusão Mútua• Soluções em SW

• Soluções com Semáforos

• Soluções com Mensagens

Problema da Exclusão Mútua –Soluções em SW

1. Porta

2. Porta 1 e Porta 21. Duas ordens de acesso possíveis

3. Vez

4. Porta 1, Porta 2 e Vez

SemáforosDefinição

Tipos: binário, contador, mutex

Conceito de propriedade – só a tarefa “dona” do semáforo pode liberá-lo

Suporte em HW

Ciclos RMW

Solução no Cortex – instruções de LD/ST exclusivo

Comunicação e Sincronização via Mensagens

• Assíncrono

• Síncrono

• Síncrono com Resposta

Comunicação Assíncrona

Tarefa 1

Executando

Receive

Bloqueado em receive

Tarefa 2

Executando

Pronto

Pronto

Put

Comunicação Síncrona

Comunicação Síncrona com Resp

Bloqueado em receive

Tarefa 1

Executando

Receive

Tarefa 2

Executando

Pronto

Pronto

Send

Bloqueado em send

Executando

Reply

Por que o seu próximo RTOS

será compatível com CMSIS-RTOS ?

)

Problema realSistema embarcado com:

3 portas seriais 115kbps = 1 char / 100u

USB = 1 pacote de 1K a cada 125us

IHM – touch

IHM – LCD

5 atividades:

A1: 2 ms leitura touch

A2: 7 ms processamento numérico dados USB

A3: 500 us protocolo USB

A4: 100 ms – sistema de menus

A5: …

Como seria o fluxo de controle num algoritmo

único para tratar de todas estas atividades ?

Douglas Renaux – ESC 2014

Implementando Concorrência

Douglas Renaux – ESC 2014

PV

PV

PV

Multithreading(múltiplas linhas de execução)

PV1 PV2 … PVn

RTOS

HW Proc.

Mem.

Perif

Proc 1

Memória Compartilhada

Periféricos Compartilhados

Proc n…

Douglas Renaux – ESC 2014

Multithreading(múltiplas linhas de execução)

PV1 PV2 … PVn

RTOS

HW

Douglas Renaux – ESC 2014

Mas afinal, qual a mágica por trás do RTOS ?Cria processadores virtuais idênticos

Cada qual com seus registradores e sua pilha

Soma da capacidade de processamento de todos eles é igual ao do MCU

Multicore Muito mais proc. Virtuais do que cores

Douglas Renaux – ESC 2014

Regiões de Memória

Flash

CODE(.text)

(.const)

RAMHEAP

STACK

DATA(.data)(.bss)

CPU

Registradores

Douglas Renaux – ESC 2014

para um programa sequencial:

FlashCODE(.text)

(.const)

RAM

HEAP

DATA(.data)(.bss)

CPURegistradores

RAM

Multithreading(múltiplas linhas de execução)

STACK 1

Regs 1

RAM

STACK n

Regs n…

Douglas Renaux – ESC 2014

Estados das Tarefas

Douglas Renaux – ESC 2014

Olhando no tempo:granularidade grossa

Douglas Renaux – ESC 2014

Thread 1

Thread 2

Thread 3

Thread 4

t0 t0 +1s t0 +2s t0 +3s

Olhando no tempo:granularidade fina

Douglas Renaux – ESC 2014t0 t0 +1ms t0 +2ms t0 +3ms

RTOSA área de Engenharia de Sistemas Embarcados

já descobriu há décadas a importância de se usar um RTOS (70s)

Nestes 40 anos, inúmeros RTOS surgiram no mercado Comerciais

FOSS (Free and Open Source SW)

Silicon vendor

Douglas Renaux – ESC 2014

• v 1.0 (2008)– Drivers API

• v 2.0– DSP Lib

• v 3.0 (2012)– API RTOS– DAP (Debug)

• V 4.0 (2014)– CMSIS-Driver– CMSIS-Pack

• V 5.0 (2016)

CMSIS (Cortex Microcontroller Software Interface Standard)

Douglas Renaux – ESC 2014

CMSIS-RTOShttp://www.keil.com/pack/doc/cmsis/rtos/html/index.html

www.arm.com

CMSIS-RTOS RTXhttp://www.keil.com/pack/doc/cmsis_rtx/index.html

www.arm.com

CMSIS-RTOS

www.arm.com

CMSIS-RTOS

www.arm.com

Task Management

Timing (delay, timers)

Signals

Semaphore / Mutex

Memory Pool

Message Queue

Mail Queue

CMSIS-RTOS Funcionalidades

Douglas Renaux – ESC 2014

CMSIS-RTOS - Prioridades

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0049a/gs_ma_rtos.htm

enum osPriority {osPriorityIdle = -3,osPriorityLow = -2,osPriorityBelowNormal = -1,osPriorityNormal = 0,osPriorityAboveNormal = +1,osPriorityHigh = +2,osPriorityRealtime = +3,osPriorityError = 0x84

}

Planejando uma Aplicação com RTOS

Douglas Renaux – ESC 2014

<<mutex>>

CMSIS-RTOS: Overview 1/4Kernel 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.

Douglas Renaux – ESC 2014

CMSIS-RTOS: Overview 2/4Generic 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.

Douglas Renaux – ESC 2014

CMSIS-RTOS: Overview 3/4Signal 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.

Douglas Renaux – ESC 2014

CMSIS-RTOS: Overview 4/4

Douglas Renaux – ESC 2014

• 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 dadoscomo acessar ?

2. Inicialização destas estruturas

3. OperaçãoYieldGetIdSetPriority

4. Término (opcional)

Ciclo de Vida dos Elementos do Kernel – exemplo: Thread

Douglas Renaux – ESC 2014

1. Definição de estruturas de dadoscomo acessar ?

2. Inicialização destas estruturas

3. OperaçãoYieldGetIdSetPriority

4. Término (opcional)

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

Douglas Renaux – ESC 2014

1. Definição de estruturas de dadoscomo acessar ?

2. Inicialização destas estruturas

3. OperaçãoYieldGetIdSetPriority

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

Douglas Renaux – ESC 2014

1. Definição de estruturas de dadoscomo acessar ?

2. Inicialização destas estruturas

3. OperaçãoYieldGetIdSetPriority

4. Término (opcional)

Ciclo de Vida dos Elementos do Kernel – exemplo: Thread

Douglas Renaux – ESC 2014

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

1. Definição de estruturas de dadoscomo acessar ?

2. Inicialização destas estruturas

3. OperaçãoYieldGetIdSetPriority

4. Término (opcional)

Ciclo de Vida dos Elementos do Kernel – exemplo: Thread

Douglas Renaux – ESC 2014

osThreadTerminate( id );

- Destrói o TCB eliminando esta tarefa do sistema

Ciclo de Vida dos Elementos do Kernel

Douglas Renaux – ESC 2014

Thread Timer Mutex Semaphore MemoryPool

MessageQueue

MailQueue

Tipos (*) osThreadIdos_pthread

osTimerIdos_ptimer

osMutexId osSemaphoreId osPoolId osMessageQId osMailQId

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 osThreadYieldosThreadGetId

osTimerStartosTimerStop

osMutexWaitosMutexRelease

osSemaphoreWaitosSemaphoreRelease

osPoolAllocosPoolFree

osMessagePutosMessageGet

osMailAllocosMailFreeosMailPutosMailGet

Término osThreadTerminate osTimerDelete osMutexDelete osSemaphoreDelete

(*) os Id são ponteiros para structs

Exercício 1• Familiarização com o exemplo de CMSIS-

RTOS

• Apresente um diagrama de classes com as tarefas deste exemplo

#include "cmsis_os.h" // CMSIS RTOS header file

void job1 (void const *argument) { // thread function 'job1'

while (1) {

: // execute some codeosDelay (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

Douglas Renaux – ESC 2014

Exercício 2• Implementar um programa utilizando o CMSIS-

RTOS RTX que acione as 3 cores do LED RGB da placa base em intervalos de tempo ligeiramente diferentes.

– tR = 500ms, tG = 550ms, tB = 600ms

1. Utilizar osDelay em cada tarefa.

2. Utilizar 3 tarefas independentes, uma para cada cor do LED RGB.

Exemplo: Acesso a recurso compartilhado

Douglas Renaux – ESC 2014

<<mutex>>

Duas tarefas que compartilham um recurso

Douglas Renaux – ESC 2014

#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) { // main thread

: // setup and initialize peripherals

osMutexId mutLCDid = osMutexCreate (osMutex(mutLCD));

osThreadCreate (osThread(job1),NULL);

osThreadCreate (osThread(job2),NULL);

}

Exemplo: Comunicação por Mensagem

Douglas Renaux – ESC 2014

<<mutex>>

Comunicação ISR -> Tarefa

Douglas Renaux – ESC 2014

#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) { // main thread

: // setup and initialize peripherals

MsgBox = osMessageCreate(osMessageQ(MsgBox), NULL);

osThreadCreate (osThread(PacMan));

}

Alocação de MemóriaMesmo 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.

Douglas Renaux – ESC 2014

Alocação de Memória

Douglas Renaux – ESC 2014

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());

}

CMSIS-RTOS - Temporizadores

www.arm.com

Macro de definição de temporizador: osTimerDef

Macro para acesso ao temporizador: osTimer

Tipos de dados: os_timer_type, osTimerId, osStatus

Funções: osTimerCreate, osTimerStart, osTimerStop, osTimerDelete

Função de Callback

one-shot x repetitivo

Exercício 3 - repetir com temporizadores• Implementar um programa utilizando o CMSIS-

RTOS RTX que acione as 3 cores do LED RGB da placa base em intervalos de tempo ligeiramente diferentes.

– tR = 500ms, tG = 550ms, tB = 600ms

1. Utilizar timers do CMSIS-RTOS em cada tarefa.

2. Utilizar 3 tarefas independentes, uma para cada cor do LED RGB.

CMSIS-RTOS

www.arm.com

CMSIS-RTOS

www.arm.com

CMSIS-RTOS - EventosEventos são de 3 tipos:

Sinais – um flag (setado ou resetado)

Mensagens – um int de 32 bits / ponteiro

Mail – um bloco de memória

osEvent status osStatus(osEventSignal / osEventMessage / osEventMail)

value int / ptr / grupo flags

def id (do mail ou da msg)

CMSIS-RTOS - Eventosvoid Thread_2 (void const *arg);

osThreadDef (Thread_2, osPriorityHigh, 1, 0);

static void EX_Signal_1 (void) {

int32_t signals;

uint32_t exec;osThreadId thread_id;

thread_id = osThreadCreate (osThread(Thread_2), NULL);

if (thread_id == NULL) {

// Failed to create a thread.

} else {

signals = osSignalSet (thread_id, 0x00000005); // Send signals to the created thread

}

}

void Thread_3 (void const *arg);

osThreadDef (Thread_3, osPriorityHigh, 1, 0);

static void EX_Signal_1 (void) {osThreadId thread_id;osEvent evt;

thread_id = osThreadCreate (osThread(Thread_2), NULL);

if (thread_id == NULL) {

// Failed to create a thread.

} else {

// wait for a signal

evt = osSignalWait (0x01, 100); // espera pelo sinal 0x1 por até 100 ms

if (evt.status == osEventSignal) {

// handle event status

}

}

}

ver RTX_Conf_CM.C pela def do número max de sinais

CMSIS-RTOS - Semáforos• osSemaphore - para sincronização entre

tarefas e/ou tarefa/ISR

• osMutex - para exclusão Mútua. Apenas a tarefa que fez osMutexWait pode fazer osMutexRelease

osSemaphoreWait

osSemaphoreWait

osSemaphoreRelease

Mutex// 1 – definição da estrutura de dados do Mutex (em geral é uma variável global)

osMutexDef(mut_GLCD);

// 2 – definição de um ponteiro para o Mutex (também costuma ser uma var global)

osMutexId mut_lcd;

// 3 – Inicialização do Mutex (em geral na função main)

mut_lcd = osMutexCreate(osMutex(mut_GLCD));

// 4 – Uso do Mutex sem timeout (a partir de uma thread)

osMutexWait(mut_lcd, osWaitForever);

...

osMutexRelease(mut_lcd);

obs:osMutex(mut_GLCD) é umachamada de MACROesta chamada retorna o endereço

da estrutura

Projeto – Arquitetura da SoluçãoElementos que compõem a arquitetura da solução:

• objetos/classes passivas

• Tarefas (threads) – objetos/classes ativas

• Tarefas Periódicas

• Message Queue – envia

• Event Queue – envia

• Temporizador – objeto passive + callback

• Semáforos (binário, contador e mutex)

• ISR – objeto/classe ativa

Projeto - DetalhamentoO que cada Tarefa faz ?

O que cada objeto/classe faz ?

• Diagramas de Estado

• Diagramas de atividades

• Estrutura de controle de cada tarefa• Loop infinito com temporização

• Loop infinito com recebimento de msg/evento

• Função com final de execução