| /* |
| * FreeRTOS Kernel V10.2.0 |
| * Copyright (C) 2019 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. |
| * |
| * http://www.FreeRTOS.org |
| * http://aws.amazon.com/freertos |
| * |
| * 1 tab == 4 spaces! |
| */ |
| |
| /* 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 "board.h" |
| |
| #include "pin_mux.h" |
| #include "clock_config.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 specific RDC settings */ |
| BOARD_RdcInit(); |
| |
| BOARD_InitBootPins(); |
| BOARD_BootClockRUN(); |
| BOARD_InitDebugConsole(); |
| BOARD_InitMemory(); |
| |
| /* 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, signed 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. */ |
| } |
| } |