projects/freertos/periodic_task_freertos.c (88 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #include <stdlib.h> #include <stddef.h> #include <string.h> #include "periodic_task_freertos.h" #include "system/system_logging.h" /** * Initialize a periodic handler task. The actual FreeRTOS task will not be allocated until a call * to one of the task allocation functions is made. * * @param task The periodic handler task to initialize. * @param state Variable context for the task. This must be uninitialized. * @param handlers The list of handlers that can be used with this task instance. * @param num_handlers The number of handlers in the list. * @param log_id Identifier for this task in log messages. * * @return 0 if the task was initialized or an error code */ int periodic_task_freertos_init (struct periodic_task_freertos *task, struct periodic_task_freertos_state *state, const struct periodic_task_handler **handlers, size_t num_handlers, int log_id) { if (task == NULL) { return PERIODIC_TASK_INVALID_ARGUMENT; } memset (task, 0, sizeof (struct periodic_task_freertos)); task->state = state; task->handlers = handlers; task->num_handlers = num_handlers; task->id = log_id; return periodic_task_freertos_init_state (task); } /** * Initialize only the variable state for a periodic handler task. The rest of the task instance is * assumed to have already been initialized. The actual FreeRTOS task will not be allocated until a * call to one of the task allocation functions is made. * * This would generally be used with a statically initialized instance. * * @param task The task instance that contains the state to initialize. * * @return 0 if the state was successfully initialized or an error code. */ int periodic_task_freertos_init_state (const struct periodic_task_freertos *task) { if ((task == NULL) || (task->state == NULL) || (task->handlers == NULL) || (task->num_handlers == 0)) { return PERIODIC_TASK_INVALID_ARGUMENT; } memset (task->state, 0, sizeof (struct periodic_task_freertos_state)); return 0; } /** * Stop the periodic task and release all resources used by the task. No handlers will be released. * * There is no synchronization done to ensure a task is only stopped when nothing is running. A * released task will be stopped immediately. * * @param task The task to release. */ void periodic_task_freertos_release (const struct periodic_task_freertos *task) { if (task) { vTaskDelete (task->state->task); } } /** * Task routine to call periodic actions for registered handlers. * * @param task The task context for processing event notifications. */ static void periodic_task_freertos_loop (struct periodic_task_freertos *task) { int status; int last_error = 0; /* Wait for the task to be started before executing anything in the task context. */ ulTaskNotifyTake (pdTRUE, portMAX_DELAY); periodic_task_prepare_handlers (task->handlers, task->num_handlers); while (1) { status = periodic_task_execute_next_handler (task->handlers, task->num_handlers); if ((status != 0) && (status != last_error)) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_SYSTEM, SYSTEM_LOGGING_PERIODIC_FAILED, task->id, status); } last_error = status; } } #if configSUPPORT_DYNAMIC_ALLOCATION == 1 /** * Allocate the periodic handler task using dynamic allocation of task resources. No handlers will * be prepared or executed until {@link periodic_task_freertos_start} is called. * * @param task The periodic task to allocate. * @param stack_words The size of the task stack. The stack size is measured in words. * @param task_name An identifying name to assign to the task. The maximum length is determined by * the FreeRTOS configuration for the platform. * @param priority The priority to assign to this task. * * @return 0 if the task was allocated or an error code. */ int periodic_task_freertos_allocate (const struct periodic_task_freertos *task, uint16_t stack_words, const char *task_name, int priority) { int status; if (task == NULL) { return PERIODIC_TASK_INVALID_ARGUMENT; } status = xTaskCreate ((TaskFunction_t) periodic_task_freertos_loop, task_name, stack_words, (void*) task, priority, &task->state->task); if (status != pdPASS) { task->state->task = NULL; return PERIODIC_TASK_NO_MEMORY; } return 0; } #endif #if configSUPPORT_STATIC_ALLOCATION == 1 /** * Allocate the periodic handler task using static allocation of task resources. No handlers will * be prepared or executed until {@link periodic_task_freertos_start} is called. * * @param task The periodic task to allocate. * @param context The statically allocated FreeRTOS context for the task. * @param stack A buffer to use for the task's stack. * @param stack_words The number of words in the stack buffer. * @param task_name An identifying name to assign to the task. The maximum length is determined by * the FreeRTOS configuration for the platform. * @param priority The priority to assign to this task. * * @return 0 if the task was allocated or an error code. */ int periodic_task_freertos_allocate_static (const struct periodic_task_freertos *task, StaticTask_t *context, StackType_t *stack, uint32_t stack_words, const char *task_name, int priority) { if (task == NULL) { return PERIODIC_TASK_INVALID_ARGUMENT; } task->state->task = xTaskCreateStatic ((TaskFunction_t) periodic_task_freertos_loop, task_name, stack_words, (void*) task, priority, stack, context); if (task->state->task == NULL) { return PERIODIC_TASK_INVALID_ARGUMENT; } return 0; } #endif /** * Start running a periodic handler task that was previously allocated. No handlers will be called * until the task has been started. * * @param task The periodic task to start. If this is null, nothing will be done. */ void periodic_task_freertos_start (const struct periodic_task_freertos *task) { if (task != NULL) { xTaskNotifyGive (task->state->task); } }