Olá caros leitores, continuando com a série de artigos sobre o MQX RTOS. No primeiro artigo foi apresentado o MQX RTOS e também criamos um projeto para FRDM-K22F.
Este artigo tem o intuito de apresentar um dos componentes mais importante de um RTOS, a tarefa (task). E serão apresentados alguns dos recursos que o MQX RTOS oferece para a sua manipulação. E, por fim, vamos trabalhar com o projeto que criamos. Utilizaremos a API para criar três tarefas, cada uma será responsável em acionar uma cor do LED RGB da Freedom Board K22F.
Task – Tarefa
Como já foi apresentado no primeiro artigo, as tarefas no MQX RTOS ou em qualquer outro RTOS se comporta como um programa independente das outras tarefas do sistema e fica a cargo do escalonador (será abordado com mais detalhe no próximo artigo) gerenciar o processamento de cada tarefa.
O MQX RTOS permite a criação de tarefas durante a sua execução. A aplicação pode alterar os atributos de uma tarefa em tempo de execução por meio de API’s fornecida pelo o MQX RTOS.
Uma tarefa quando é finalizada ou destruída todos os seus recursos (memória alocada dinamicamente, messages, mutexes, semáforos, etc) alocados serão automaticamente desalocados.
Normalmente uma tarefa é implementada com um loop infinito. A grande maioria das aplicações não retorna nada (void). A seguir temos um exemplo com esqueleto de uma tarefa.
// Protótipo de uma tarefa
void tarefa_A(uint32_t data);
//Esqueleto de uma tarefa
Void tarefa_A(uint32_t data)
{
while(1)
{
}
}
Estados das Tarefas no MQX RTOS
As tarefas no MQX RTOS possuem quatro estados:
- Bloqueada (Blocked) – tarefa aguardando um evento ou outra tarefa alterar o seu estado para pronta;
- Pronta (Ready) – é uma tarefa pronta para ser executada, mas que não esta ativa;
- Ativa (Active) – tarefa em execução;
- Finalizada (Terminated) – tarefa finalizada, porém os seus recursos ainda não foram deslocados pelo kernel do MQX.
Atributos de tarefas
As tarefas no MQX possuem os seguintes atributos:
- MQX_AUTO_START_TASK: tarefa é inicializa quando o MQX é iniciado;
- MQX_DSP_TASK: atribuem os registradores do DSP no contexto da tarefa;
- MQX_FLOATING_POINT_TASK: atribuem os registradores da FPU no contexto da tarefa;
- MQX_TIME_SLICE_TASK: habilita o escalonador do tipo Round Robin.
/* aloca e criar uma nova tarefa com estado pronto */ _task_id _task_create ( _processor_number processor_number, _mqx_uint template_index, uint32_t parameter); /* aloca e cria uma nova tarefa com estado bloqueada */ _task_id _task_create_blocked(_processor_number processor_number, _mqx_uint template_index, uint32_t parameter); /* muda para a tarefa para o estado pronto*/ void _task_ready(void *td_ptr); /* restarts a task at the beginning of the task's function; keeps the same task descriptor, task ID, and task stack */ _mqx_uint _task_restart(_task_id task_id, uint32_t * param_ptr, bool blocked); /* muda a tarefa para o estado bloqueado */ void _task_block(void); //Finalizando tarefa /* termina com a tarefa e libera o seu recurso */ _mqx_uint _task_destroy(_task_id task_id); /* set the task exit handler */ TASK_EXIT_FPTR _task_set_exit_handler(_task_id task_id, TASK_EXIT_FPTR exit_handler_address); /* terminates the task after running its task exit handler and releasing its resources */ _mqx_uint _task_abort(_task_id task_id);
Task Template List – Templates de Tarefas
No Task Tamplate List (Templates de Tarefas) é onde são informados os parâmetros de cada tarefa ao MQX RTOS. Isso é através do vetor MQX_template_list[]. A seguir temos a lista de parâmetros que devem ser preenchidos no template de tarefas:
- Task number – O némero da tarefa;
- Entry point – A função da tarefa;
- Stack – O tamanho da tarefa;
- Priority – A prioridade da tarefa;
- String – A string da tarefa;
- Attributes – Atributo da tarefa;
- Parameter – Parâmetro para tarefa;
- Time Slice – Tempo de execução (para política de escalonamento Round Robin).
typedef struct task_template_struct
{
_mqx_uint TASK_TEMPLATE_INDEX;
TASK_FPTR TASK_ADDRESS;
_mem_size TASK_STACKSIZE;
_mqx_uint TASK_PRIORITY;
char * TASK_NAME;
_mqx_uint TASK_ATTRIBUTES;
uint32_t CREATION_PARAMETER;
_mqx_uint DEFAULT_TIME_SLICE;
} TASK_TEMPLATE_STRUCT, *TASK_TEMPLATE_STRUCT_PTR;
Trabalhando com a Tarefa
Como já dissemos no início, iremos continuar com o projeto que criamos, vamos desenvolver uma aplicação que aciona o LED RGB presente na Freedom Board K22F. Serão desenvolvidas quatro tarefas. Serão três tarefas para acionar o LED, sendo uma para cada cor do LED RGB, e a última tarefa será responsável em inicializar os periféricos da placa e criar as demais tarefas.
Abra o arquivo main.h, onde criaremos ao protótipo da função de cada tarefa.
//----------------------------------------------------------------------- // Function Prototypes //----------------------------------------------------------------------- void main_task(uint32_t param ); void Led_Red (uint32_t param ); void Led_Green(uint32_t param ); void Led_Blue (uint32_t param );
Abra o arquivo main.h. Neste arquivo iremos implementar o algoritmo da nossa aplicação.
//-----------------------------------------------------------------------
// Projeto: Tarefas MQX RTOS
// Autor: Evandro Teixeira
//-----------------------------------------------------------------------
#include <stdio.h> // Standard C/C++ Includes
#include "main.h" // Inclue os arquivos da aplicação e KSDK
//-----------------------------------------------------------------------
// Numeros das tarefas
//-----------------------------------------------------------------------
#define MAIN_TASK 8U
#define LED_RED_TASK 9U
#define LED_BLUE_TASK 10U
#define LED_GREEN_TASK 11U
#define GREEN 0
#define RED 1
#define BLUE 2
//-----------------------------------------------------------------------
// Templates de Tarefas
//-----------------------------------------------------------------------
const TASK_TEMPLATE_STRUCT MQX_template_list[] =
{
/* Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */
{ MAIN_TASK, main_task, 0xC00, 20, "main_task", MQX_AUTO_START_TASK, 0, 0},
{ LED_RED_TASK, Led_Red, 0xC00, 21, "led_red_task", 0, 0, 0},
{ LED_GREEN_TASK, Led_Green, 0xC00, 22, "led_green_task", 0, 0, 0},
{ LED_BLUE_TASK, Led_Blue, 0xC00, 23, "led_blue_task", 0, 0, 0},
{ 0L, 0L, 0L, 0L, 0L, 0L }
};
//-----------------------------------------------------------------------
// Main task
//-----------------------------------------------------------------------
void main_task(uint32_t param)
{
hardware_init(); // Configure board specific pin muxing
dbg_uart_init(); // Initialize UART terminal
OSA_Init(); // Initializes the RTOS services.
OSA_Start(); // Starts the RTOS.
// criar task (variavel que recebe o numero da tarefa)
_task_id led_RED_id;
_task_id led_BLUE_id;
_task_id led_GREEN_id;
// Cria a tarefa
led_RED_id = _task_create(0, LED_RED_TASK, 0);
// Verifica se a tarefa foi criada sem nenhum erro
if (led_RED_id == MQX_NULL_TASK_ID)
{
printf ("\n\r Could not create led_red_task");
}
else
{
printf("\n\rled_red_task OK!");
}
// Cria a tarefa
led_GREEN_id = _task_create(0, LED_GREEN_TASK, 0);
// Verifica se a tarefa foi criada sem nenhum erro
if (led_GREEN_id == MQX_NULL_TASK_ID)
{
printf ("\n\r Could not create led_green_task");
}
else
{
printf("\n\rled_green_task OK!");
}
// Cria a tarefa
led_BLUE_id = _task_create(0, LED_BLUE_TASK, 0);
// Verifica se a tarefa foi criada sem nenhum erro
if (led_GREEN_id == MQX_NULL_TASK_ID)
{
printf ("\n\r Could not create led_blue_task");
}
else
{
printf("\n\rled_blue_task OK!");
}
//inicia loop infinito
for (;;)
{
//__asm("NOP");
// utiliza API para bloqueiar a tarefa main_task
_task_block();
}
}
//-----------------------------------------------------------------------
// Task Functions
//-----------------------------------------------------------------------
void Led_Red (uint32_t param )
{
// Variavel
uint8_t controle = 0;
// Imprimi msg
printf("\n\rTask Led Red");
// Inicializa IO como saida
GPIO_DRV_OutputPinInit(&ledPins[RED]);
// set IO com 1
GPIO_DRV_SetPinOutput(&ledPins[RED]);
while(1)
{
if(controle <= 2)
{
// Inverte IO
GPIO_DRV_TogglePinOutput(ledPins[RED].pinName);
}
if(controle == 5)
{
controle = 0;
// Inverte IO
GPIO_DRV_SetPinOutput(&ledPins[RED]);
}
controle++;
// utiliza API para bloqueiar a tarefa por 5 segundos
_time_delay(5000);
}
}
//-----------------------------------------------------------------------
// Task Functions
//-----------------------------------------------------------------------
void Led_Green (uint32_t param )
{
// Variavel
uint8_t controle = 0;
// Imprimi msg
printf("\n\rTask Led Green");
// Inicializa IO como saida
GPIO_DRV_OutputPinInit(&ledPins[GREEN]);
// set IO com 1
GPIO_DRV_SetPinOutput(&ledPins[GREEN]);
while(1)
{
if((controle >= 2)&&(controle <= 3))
{
// Inverte IO
GPIO_DRV_TogglePinOutput(ledPins[GREEN].pinName);
}
if(controle == 5)
{
controle = 0;
// Inverte IO
GPIO_DRV_SetPinOutput(&ledPins[GREEN]);
}
controle++;
// utiliza API para bloqueiar a tarefa por 5 segundos
_time_delay(5000);
}
}
//-----------------------------------------------------------------------
// Task Functions
//-----------------------------------------------------------------------
void Led_Blue (uint32_t param )
{
// Variavel
uint8_t controle = 0;
// Imprimi msg
printf("\n\rTask Led Blue");
// Inicializa IO como saida
GPIO_DRV_OutputPinInit(&ledPins[BLUE]);
// set IO com 1
GPIO_DRV_SetPinOutput(&ledPins[BLUE]);
while(1)
{
if((controle >= 4)&&(controle <= 5))
{
// Inverte IO
GPIO_DRV_TogglePinOutput(ledPins[BLUE].pinName);
}
if(controle == 5)
{
controle = 0;
// Inverte IO
GPIO_DRV_SetPinOutput(&ledPins[BLUE]);
}
controle++;
// utiliza API para bloqueiar a tarefa por 5 segundos
_time_delay(5000);
}
}
//-----------------------------------------------------------------------
Conclusão
Aplicação que acabamos de implementar foi possível explorar recursos de algumas API para a manipulação das tarefas no MQX RTOS. Também utilizamos recursos do KSDK para acionar o LED RGB. Nos próximos artigos iremos explorar recursos de outros componentes do MQX.
Para saber mais sobre MQX RTOS
Este artigo teve como referência os slides do treinamento do Sergio Prado sobre MQX RTOS.
Referências
MQX™ Software Solutions
MQX™ RTOS for Kinetis SDK v1.3
MQX Lite ™ RTOS – Reference Manual
Fonte das Imagens: NXP MQX™ RTOS









Olá Evandro,
Me parece que você usou como referência os slides do meu treinamento:
– tem muitas frases bem parecidas.
– os prototipos das funções são os mesmos que uso no material do treinamento (inclusive você esqueceu de traduzir os comentários dos protótipos das últimas 3 funções, mantendo exatamente os comentários que estão nos meus slides).
– o diagrama que explica os estados de uma tarefa está identico.
Neste caso, por favor coloque como referências os slides do treinamento da Embedded Labworks.
https://e-labworks.com/treinamentos/mqx/slides
Obrigado,
Sergio Prado
Ola Sergio,
Me desculpe.
Já foi incluído a referência aos slides do treinamento da Embedded Labworks.
OK Evandro, obrigado.