Avancemos un poco más y creemos un proyecto con 2 tareas. Para ello, tomamos el proyecto anterior, le damos click con el botón derecho y elegimos Copy, luego boton derecho nuevamente y Paste. Ahí cambiamos el nombre del proyecto y tendremos una copia funcional del anterior. Hacemos boton derecho y le damos a Clean.
Bueno, ahora agreguemos una segunda tarea que haga un toggle de otro LED pero con 500mseg de intervalo. Las dos con la misma prioridad:
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
void ToggleLED_Timer(void*);
void ToggleLED_IPC(void*);
void SystemClock_Config(void);
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
BSP_LED_Init(LED4);
BSP_LED_Init(LED3);
/* Create tasks */
xTaskCreate(
ToggleLED_Timer, /* Function pointer */
"Task1", /* Task name - for debugging only*/
configMINIMAL_STACK_SIZE, /* Stack depth in words */
(void*) NULL, /* Pointer to tasks arguments (parameter) */
tskIDLE_PRIORITY + 2UL, /* Task priority*/
NULL /* Task handle */
);
xTaskCreate(
ToggleLED_IPC,
"Task3",
configMINIMAL_STACK_SIZE,
(void*) NULL,
tskIDLE_PRIORITY + 2UL,
NULL);
/* Start the RTOS Scheduler */
vTaskStartScheduler();
/* HALT */
while(1);
}
/**
* TASK 1: Toggle LED via RTOS Timer
*/
void ToggleLED_Timer(void *pvParameters){
while (1)
{
BSP_LED_Toggle(LED4);
/*
Delay for a period of time. vTaskDelay() places the task into
the Blocked state until the period has expired.
The delay period is spacified in 'ticks'. We can convert
yhis in milisecond with the constant portTICK_RATE_MS.
*/
vTaskDelay(1500 / portTICK_RATE_MS);
}
}
/**
* TASK 3: Toggle LED via Inter-Process Communication (IPC)
*
*/
void ToggleLED_IPC(void *pvParameters) {
while (1)
{
BSP_LED_Toggle(LED3);
/*
Delay for a period of time. vTaskDelay() places the task into
the Blocked state until the period has expired.
The delay period is spacified in 'ticks'. We can convert
yhis in milisecond with the constant portTICK_RATE_MS.
*/
vTaskDelay(500 / portTICK_RATE_MS);
}
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
aquí, el secreto de estas dos tareas simples es la funcion vTaskDelay(500 / portTICK_RATE_MS); la cual bloquea la tarea durante el tiempo pasado como parámetro y al blouear la tarea permitimos que se ejecuten las demás.
Bueno, ahora empezamos con algo un poco más interesante. Comunicacion entre Tareas. Que pasa si queremos hacer un toggle de un led al presionar un pulsador. Pues la solucion es crear dos tareas, una que lea el estado del pulsador y la otra que haga el toggle del led, pero debemos sincronizarlas entre sí. Para ello se utilizan los message queue. La tarea del LED lee la queue ni bien arranca y si no encuentra el mensaje, se queda bloqueada hasta recivirlo. Por otra parte la tarea del pulsador espera detectar la pulsacion y cuando la detecta pone el mensaje en la queue que desbloqueará la otra tarea:
Creamos la queue
/* Create IPC variables */
pbq = xQueueCreate(10, sizeof(int));
if (pbq == 0)
{
while(1); /* fatal error */
}
Luego creamos las 3 tareas
/* Create tasks */
xTaskCreate(
ToggleLED_Timer, /* Function pointer */
"Task1", /* Task name - for debugging only*/
configMINIMAL_STACK_SIZE, /* Stack depth in words */
(void*) NULL, /* Pointer to tasks arguments (parameter) */
tskIDLE_PRIORITY + 2UL, /* Task priority*/
NULL /* Task handle */
);
xTaskCreate(
DetectButtonPress,
"Task2",
configMINIMAL_STACK_SIZE,
(void*) NULL,
tskIDLE_PRIORITY + 2UL,
NULL);
xTaskCreate(
ToggleLED_IPC,
"Task3",
configMINIMAL_STACK_SIZE,
(void*) NULL,
tskIDLE_PRIORITY + 2UL,
NULL);
y finalmente las 3 funciones de las 3 tareas:
/**
* TASK 1: Toggle LED via RTOS Timer
*/
void ToggleLED_Timer(void *pvParameters){
while (1)
{
BSP_LED_Toggle(LED4);
/*
Delay for a period of time. vTaskDelay() places the task into
the Blocked state until the period has expired.
The delay period is spacified in 'ticks'. We can convert
yhis in milisecond with the constant portTICK_RATE_MS.
*/
vTaskDelay(1500 / portTICK_RATE_MS);
}
}
/**
* TASK 2: Detect Button Press
* And Signal Event via Inter-Process Communication (IPC)
*/
void DetectButtonPress(void *pvParameters){
int sig = 1;
while (1) {
/* Detect Button Press */
if(BSP_PB_GetState(BUTTON_KEY)>0) {
while(BSP_PB_GetState(BUTTON_KEY)>0)
vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */
while(BSP_PB_GetState(BUTTON_KEY)==0)
vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */
xQueueSendToBack(pbq, &sig, 0); /* Send Message */
}
}
}
/**
* TASK 3: Toggle LED via Inter-Process Communication (IPC)
*
*/
void ToggleLED_IPC(void *pvParameters)
{
int sig;
portBASE_TYPE status;
while (1)
{
status = xQueueReceive(pbq, &sig, portMAX_DELAY); /* Receive Message */
/* portMAX_DELAY blocks task indefinitely if queue is empty */
if(status == pdTRUE) {
BSP_LED_Toggle(LED3);
}
}
}
Notar que hay una pequeña rutina de debounce. De este modo podemos crear tareas simples que se encarguen de diversas cosas e interconectarlas entre sí por medio de mensajes.
Saludos