396 lines
14 KiB
C
396 lines
14 KiB
C
/*
|
|
* FreeRTOS Kernel V10.4.3
|
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
* the Software without restriction, including without limitation the rights to
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* https://www.FreeRTOS.org
|
|
* https://github.com/FreeRTOS
|
|
*
|
|
*/
|
|
|
|
/* Kernel includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "queue.h"
|
|
#include "timers.h"
|
|
#include "semphr.h"
|
|
|
|
/* TODO Add any manufacture supplied header files necessary for CMSIS functions
|
|
to be available here. */
|
|
/* Freescale includes. */
|
|
#include "fsl_device_registers.h"
|
|
#include "fsl_debug_console.h"
|
|
#include "pin_mux.h"
|
|
#include "clock_config.h"
|
|
#include "board.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/* Priorities at which the tasks are created. The event semaphore task is
|
|
given the maximum priority of ( configMAX_PRIORITIES - 1 ) to ensure it runs as
|
|
soon as the semaphore is given. */
|
|
#define mainQUEUE_RECEIVE_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
|
|
#define mainQUEUE_SEND_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
|
#define mainEVENT_SEMAPHORE_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
|
|
|
/* The rate at which data is sent to the queue, specified in milliseconds, and
|
|
converted to ticks using the portTICK_PERIOD_MS constant. */
|
|
#define mainQUEUE_SEND_PERIOD_MS (200 / portTICK_PERIOD_MS)
|
|
|
|
/* The period of the example software timer, specified in milliseconds, and
|
|
converted to ticks using the portTICK_PERIOD_MS constant. */
|
|
#define mainSOFTWARE_TIMER_PERIOD_MS (1000 / portTICK_PERIOD_MS)
|
|
|
|
/* The number of items the queue can hold. This is 1 as the receive task
|
|
will remove items as they are added, meaning the send task should always find
|
|
the queue empty. */
|
|
#define mainQUEUE_LENGTH (1)
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
/*
|
|
* The queue send and receive tasks as described in the comments at the top of
|
|
* this file.
|
|
*/
|
|
static void prvQueueReceiveTask(void *pvParameters);
|
|
static void prvQueueSendTask(void *pvParameters);
|
|
|
|
/*
|
|
* The callback function assigned to the example software timer as described at
|
|
* the top of this file.
|
|
*/
|
|
static void vExampleTimerCallback(TimerHandle_t xTimer);
|
|
|
|
/*
|
|
* The event semaphore task as described at the top of this file.
|
|
*/
|
|
static void prvEventSemaphoreTask(void *pvParameters);
|
|
|
|
/*******************************************************************************
|
|
* Globals
|
|
******************************************************************************/
|
|
/* The queue used by the queue send and queue receive tasks. */
|
|
static QueueHandle_t xQueue = NULL;
|
|
|
|
/* The semaphore (in this case binary) that is used by the FreeRTOS tick hook
|
|
* function and the event semaphore task.
|
|
*/
|
|
static SemaphoreHandle_t xEventSemaphore = NULL;
|
|
|
|
/* The counters used by the various examples. The usage is described in the
|
|
* comments at the top of this file.
|
|
*/
|
|
static volatile uint32_t ulCountOfTimerCallbackExecutions = 0;
|
|
static volatile uint32_t ulCountOfItemsReceivedOnQueue = 0;
|
|
static volatile uint32_t ulCountOfReceivedSemaphores = 0;
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
/*!
|
|
* @brief Main function
|
|
*/
|
|
int main(void)
|
|
{
|
|
TimerHandle_t xExampleSoftwareTimer = NULL;
|
|
|
|
/* Init board hardware. */
|
|
BOARD_ConfigMPU();
|
|
BOARD_InitBootPins();
|
|
BOARD_InitBootClocks();
|
|
BOARD_InitDebugConsole();
|
|
|
|
/* Create the queue used by the queue send and queue receive tasks. */
|
|
xQueue = xQueueCreate(/* The number of items the queue can hold. */
|
|
mainQUEUE_LENGTH,
|
|
/* The size of each item the queue holds. */
|
|
sizeof(uint32_t));
|
|
|
|
/* Enable queue view in MCUX IDE FreeRTOS TAD plugin. */
|
|
if (xQueue != NULL)
|
|
{
|
|
vQueueAddToRegistry(xQueue, "xQueue");
|
|
}
|
|
|
|
/* Create the semaphore used by the FreeRTOS tick hook function and the
|
|
event semaphore task. */
|
|
vSemaphoreCreateBinary(xEventSemaphore);
|
|
|
|
/* Create the queue receive task as described in the comments at the top
|
|
of this file. */
|
|
if (xTaskCreate(/* The function that implements the task. */
|
|
prvQueueReceiveTask,
|
|
/* Text name for the task, just to help debugging. */
|
|
"Rx",
|
|
/* The size (in words) of the stack that should be created
|
|
for the task. */
|
|
configMINIMAL_STACK_SIZE + 166,
|
|
/* A parameter that can be passed into the task. Not used
|
|
in this simple demo. */
|
|
NULL,
|
|
/* The priority to assign to the task. tskIDLE_PRIORITY
|
|
(which is 0) is the lowest priority. configMAX_PRIORITIES - 1
|
|
is the highest priority. */
|
|
mainQUEUE_RECEIVE_TASK_PRIORITY,
|
|
/* Used to obtain a handle to the created task. Not used in
|
|
this simple demo, so set to NULL. */
|
|
NULL) != pdPASS)
|
|
{
|
|
PRINTF("Task creation failed!.\r\n");
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
/* Create the queue send task in exactly the same way. Again, this is
|
|
described in the comments at the top of the file. */
|
|
if (xTaskCreate(prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE + 166, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL) !=
|
|
pdPASS)
|
|
{
|
|
PRINTF("Task creation failed!.\r\n");
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
/* Create the task that is synchronised with an interrupt using the
|
|
xEventSemaphore semaphore. */
|
|
if (xTaskCreate(prvEventSemaphoreTask, "Sem", configMINIMAL_STACK_SIZE + 166, NULL,
|
|
mainEVENT_SEMAPHORE_TASK_PRIORITY, NULL) != pdPASS)
|
|
{
|
|
PRINTF("Task creation failed!.\r\n");
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
/* Create the software timer as described in the comments at the top of
|
|
this file. */
|
|
xExampleSoftwareTimer = xTimerCreate(/* A text name, purely to help
|
|
debugging. */
|
|
"LEDTimer",
|
|
/* The timer period, in this case
|
|
1000ms (1s). */
|
|
mainSOFTWARE_TIMER_PERIOD_MS,
|
|
/* This is a periodic timer, so
|
|
xAutoReload is set to pdTRUE. */
|
|
pdTRUE,
|
|
/* The ID is not used, so can be set
|
|
to anything. */
|
|
(void *)0,
|
|
/* The callback function that switches
|
|
the LED off. */
|
|
vExampleTimerCallback);
|
|
|
|
/* Start the created timer. A block time of zero is used as the timer
|
|
command queue cannot possibly be full here (this is the first timer to
|
|
be created, and it is not yet running). */
|
|
xTimerStart(xExampleSoftwareTimer, 0);
|
|
|
|
/* Start the tasks and timer running. */
|
|
vTaskStartScheduler();
|
|
|
|
/* If all is well, the scheduler will now be running, and the following line
|
|
will never be reached. If the following line does execute, then there was
|
|
insufficient FreeRTOS heap memory available for the idle and/or timer tasks
|
|
to be created. See the memory management section on the FreeRTOS web site
|
|
for more details. */
|
|
for (;;)
|
|
;
|
|
}
|
|
|
|
/*!
|
|
* @brief Timer callback.
|
|
*/
|
|
static void vExampleTimerCallback(TimerHandle_t xTimer)
|
|
{
|
|
/* The timer has expired. Count the number of times this happens. The
|
|
timer that calls this function is an auto re-load timer, so it will
|
|
execute periodically. */
|
|
ulCountOfTimerCallbackExecutions++;
|
|
}
|
|
|
|
/*!
|
|
* @brief Task prvQueueSendTask periodically sending message.
|
|
*/
|
|
static void prvQueueSendTask(void *pvParameters)
|
|
{
|
|
TickType_t xNextWakeTime;
|
|
const uint32_t ulValueToSend = 100UL;
|
|
|
|
/* Initialise xNextWakeTime - this only needs to be done once. */
|
|
xNextWakeTime = xTaskGetTickCount();
|
|
|
|
for (;;)
|
|
{
|
|
/* Place this task in the blocked state until it is time to run again.
|
|
The block time is specified in ticks, the constant used converts ticks
|
|
to ms. While in the Blocked state this task will not consume any CPU
|
|
time. */
|
|
vTaskDelayUntil(&xNextWakeTime, mainQUEUE_SEND_PERIOD_MS);
|
|
|
|
/* Send to the queue - causing the queue receive task to unblock and
|
|
increment its counter. 0 is used as the block time so the sending
|
|
operation will not block - it shouldn't need to block as the queue
|
|
should always be empty at this point in the code. */
|
|
xQueueSend(xQueue, &ulValueToSend, 0);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief Task prvQueueReceiveTask waiting for message.
|
|
*/
|
|
static void prvQueueReceiveTask(void *pvParameters)
|
|
{
|
|
uint32_t ulReceivedValue;
|
|
|
|
for (;;)
|
|
{
|
|
/* Wait until something arrives in the queue - this task will block
|
|
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
|
|
FreeRTOSConfig.h. */
|
|
xQueueReceive(xQueue, &ulReceivedValue, portMAX_DELAY);
|
|
|
|
/* To get here something must have been received from the queue, but
|
|
is it the expected value? If it is, increment the counter. */
|
|
if (ulReceivedValue == 100UL)
|
|
{
|
|
/* Count the number of items that have been received correctly. */
|
|
ulCountOfItemsReceivedOnQueue++;
|
|
PRINTF("Receive message counter: %d.\r\n", ulCountOfItemsReceivedOnQueue);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief task prvEventSemaphoreTask is waiting for semaphore.
|
|
*/
|
|
static void prvEventSemaphoreTask(void *pvParameters)
|
|
{
|
|
for (;;)
|
|
{
|
|
/* Block until the semaphore is 'given'. */
|
|
if (xSemaphoreTake(xEventSemaphore, portMAX_DELAY) != pdTRUE)
|
|
{
|
|
PRINTF("Failed to take semaphore.\r\n");
|
|
}
|
|
|
|
/* Count the number of times the semaphore is received. */
|
|
ulCountOfReceivedSemaphores++;
|
|
|
|
PRINTF("Event task is running.\r\n");
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief tick hook is executed every tick.
|
|
*/
|
|
void vApplicationTickHook(void)
|
|
{
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
static uint32_t ulCount = 0;
|
|
|
|
/* The RTOS tick hook function is enabled by setting configUSE_TICK_HOOK to
|
|
1 in FreeRTOSConfig.h.
|
|
|
|
"Give" the semaphore on every 500th tick interrupt. */
|
|
ulCount++;
|
|
if (ulCount >= 500UL)
|
|
{
|
|
/* This function is called from an interrupt context (the RTOS tick
|
|
interrupt), so only ISR safe API functions can be used (those that end
|
|
in "FromISR()".
|
|
|
|
xHigherPriorityTaskWoken was initialised to pdFALSE, and will be set to
|
|
pdTRUE by xSemaphoreGiveFromISR() if giving the semaphore unblocked a
|
|
task that has equal or higher priority than the interrupted task. */
|
|
xSemaphoreGiveFromISR(xEventSemaphore, &xHigherPriorityTaskWoken);
|
|
ulCount = 0UL;
|
|
}
|
|
|
|
/* If xHigherPriorityTaskWoken is pdTRUE then a context switch should
|
|
normally be performed before leaving the interrupt (because during the
|
|
execution of the interrupt a task of equal or higher priority than the
|
|
running task was unblocked). The syntax required to context switch from
|
|
an interrupt is port dependent, so check the documentation of the port you
|
|
are using.
|
|
|
|
In this case, the function is running in the context of the tick interrupt,
|
|
which will automatically check for the higher priority task to run anyway,
|
|
so no further action is required. */
|
|
}
|
|
|
|
/*!
|
|
* @brief Malloc failed hook.
|
|
*/
|
|
void vApplicationMallocFailedHook(void)
|
|
{
|
|
/* The malloc failed hook is enabled by setting
|
|
configUSE_MALLOC_FAILED_HOOK to 1 in FreeRTOSConfig.h.
|
|
|
|
Called if a call to pvPortMalloc() fails because there is insufficient
|
|
free memory available in the FreeRTOS heap. pvPortMalloc() is called
|
|
internally by FreeRTOS API functions that create tasks, queues, software
|
|
timers, and semaphores. The size of the FreeRTOS heap is set by the
|
|
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
|
|
for (;;)
|
|
;
|
|
}
|
|
|
|
/*!
|
|
* @brief Stack overflow hook.
|
|
*/
|
|
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
|
{
|
|
(void)pcTaskName;
|
|
(void)xTask;
|
|
|
|
/* Run time stack overflow checking is performed if
|
|
configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
|
|
function is called if a stack overflow is detected. pxCurrentTCB can be
|
|
inspected in the debugger if the task name passed into this function is
|
|
corrupt. */
|
|
for (;;)
|
|
;
|
|
}
|
|
|
|
/*!
|
|
* @brief Idle hook.
|
|
*/
|
|
void vApplicationIdleHook(void)
|
|
{
|
|
volatile size_t xFreeStackSpace;
|
|
|
|
/* The idle task hook is enabled by setting configUSE_IDLE_HOOK to 1 in
|
|
FreeRTOSConfig.h.
|
|
|
|
This function is called on each cycle of the idle task. In this case it
|
|
does nothing useful, other than report the amount of FreeRTOS heap that
|
|
remains unallocated. */
|
|
xFreeStackSpace = xPortGetFreeHeapSize();
|
|
|
|
if (xFreeStackSpace > 100)
|
|
{
|
|
/* By now, the kernel has allocated everything it is going to, so
|
|
if there is a lot of heap remaining unallocated then
|
|
the value of configTOTAL_HEAP_SIZE in FreeRTOSConfig.h can be
|
|
reduced accordingly. */
|
|
}
|
|
}
|