diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager')
5 files changed, 943 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.c new file mode 100644 index 0000000..d61497b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.c @@ -0,0 +1,543 @@ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(TASK_MANAGER) +#include "nrf_mpu.h" +#include "nrf_atomic.h" +#include "app_util_platform.h" +#include "task_manager.h" + +#if TASK_MANAGER_CLI_CMDS +#include "nrf_cli.h" +#endif + +#define NRF_LOG_MODULE_NAME task_manager + +#if TASK_MANAGER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL TASK_MANAGER_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR TASK_MANAGER_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR TASK_MANAGER_CONFIG_DEBUG_COLOR +#endif +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if TASK_MANAGER_CONFIG_STACK_GUARD +#define STACK_GUARD_SIZE (1 << (TASK_MANAGER_CONFIG_STACK_GUARD + 1)) +STATIC_ASSERT((TASK_MANAGER_CONFIG_STACK_SIZE % STACK_GUARD_SIZE) == 0); +#endif + +STATIC_ASSERT((TASK_MANAGER_CONFIG_MAX_TASKS) > 0); +STATIC_ASSERT((TASK_MANAGER_CONFIG_STACK_SIZE % 8) == 0); + +// Support older CMSIS avaiable in Keil 4 +#if (__CORTEX_M == 4) +# ifndef CONTROL_FPCA_Pos +# define CONTROL_FPCA_Pos 2u +# define CONTROL_FPCA_Msk (1ul << CONTROL_FPCA_Pos) +# endif + +# ifndef CONTROL_SPSEL_Pos +# define CONTROL_SPSEL_Pos 1u +# define CONTROL_SPSEL_Msk (1ul << CONTROL_SPSEL_Pos) +# endif +#endif + +/*lint -save -esym(526,task_switch)*/ +// Declare task switching function. +extern void task_switch(void); +/*lint -restore*/ + +/**@brief Idle Task ID */ +#define IDLE_TASK_ID TASK_MANAGER_CONFIG_MAX_TASKS +#define TASK_STACK_MAGIC_WORD 0xDEADD00E +#define TASK_FLAG_SIGNAL_MASK 0x00FFFFFF +#define TASK_FLAG_DESTROY 0x80000000 + +/** @brief Total number of tasks includes user configuration and idle task. */ +#define TOTAL_NUM_OF_TASKS (TASK_MANAGER_CONFIG_MAX_TASKS + 1) + +/**@brief Task stack with saved task state (does not include FPU state). */ +typedef struct +{ + uint32_t r0; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t lr; + uint32_t control; +} task_stack_t; + +/**@brief Task State */ +typedef struct +{ + void *p_stack; /**< Pointer to task stack. NULL if task does not exist. */ + const char *p_task_name; + nrf_atomic_u32_t flags; /**< Task flags */ +} task_state_t; + +/* Allocate space for task stacks: + * + * Layout: + * +---------------+ + * | Idle Task | + * +---------------+ + * | Stack Guard | + * +---------------+ + * | Task N | + * +---------------+ + * | Stack Guard | + * +---------------+ + * | ... | + * +---------------+ + * | Task 0 | + * +---------------+ + * | Stack Guard | + * +---------------+ + */ + +typedef struct +{ +#if TASK_MANAGER_CONFIG_STACK_GUARD + uint8_t guard[STACK_GUARD_SIZE]; +#endif + uint8_t stack[TASK_MANAGER_CONFIG_STACK_SIZE]; +} task_manager_stack_t; + +/**@brief Stack space for tasks */ +#if TASK_MANAGER_CONFIG_STACK_GUARD +/**@brief Handle to MPU region used as a guard */ +static nrf_mpu_region_t s_guard_region; +__ALIGN(STACK_GUARD_SIZE) +#else +__ALIGN(8) +#endif +static task_manager_stack_t s_task_stacks[TOTAL_NUM_OF_TASKS]; + +/**@brief Task States + * Addtional state reserved for idle task which is mandatory. + * */ +static task_state_t s_task_state[TOTAL_NUM_OF_TASKS]; + +/**@brief Mask indicating which tasks are runnable */ +static nrf_atomic_u32_t s_runnable_tasks_mask; + +/**@brief ID of currently executed task */ +static task_id_t s_current_task_id; + +/**@brief Guard page attributes: Normal memory, WBWA/WBWA, RO/RO, XN */ +#define TASK_GUARD_ATTRIBUTES ((0x05 << MPU_RASR_TEX_Pos) | (1 << MPU_RASR_B_Pos) | \ + (0x07 << MPU_RASR_AP_Pos) | (1 << MPU_RASR_XN_Pos)) + + +/**@brief Macro for getting pointer to bottom of stack for given task id */ +#define BOTTOM_OF_TASK_STACK(_task_id) ((void *)(&s_task_stacks[(_task_id)].stack[0])) + +/**@brief Macro for getting pointer to top of stack for given task id */ +#define TOP_OF_TASK_STACK(_task_id) ((void *)(&s_task_stacks[(_task_id)].stack[TASK_MANAGER_CONFIG_STACK_SIZE])) + +/**@brief Macro for getting pointer to base of stack guard for given task id */ +#define TASK_STACK_GUARD_BASE(_task_id) ((void *)(&s_task_stacks[(_task_id)].guard[0])) + +#define TASK_ID_TO_MASK(_task_id) (0x80000000 >> (_task_id)) + +/**@brief Puts task in RUNNABLE state */ +#define TASK_STATE_RUNNABLE(_task_id) \ + (void)nrf_atomic_u32_or(&s_runnable_tasks_mask, TASK_ID_TO_MASK(_task_id)) + +/**@brief Puts task in SUSPENDED state */ +#define TASK_STATE_SUSPENDED(_task_id) \ + (void)nrf_atomic_u32_and(&s_runnable_tasks_mask, ~TASK_ID_TO_MASK(_task_id)); + +static void task_stack_poison(task_id_t task_id) +{ +#if TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED + unsigned int i = TASK_MANAGER_CONFIG_STACK_SIZE / sizeof(uint32_t); + uint32_t *p_stack_top = TOP_OF_TASK_STACK(task_id); + + while (i--) + { + *(--p_stack_top) = TASK_STACK_MAGIC_WORD; + } +#endif +} + +static void task_stack_protect(task_id_t task_id) +{ +#if TASK_MANAGER_CONFIG_STACK_GUARD + APP_ERROR_CHECK(nrf_mpu_region_create(&s_guard_region, + TASK_STACK_GUARD_BASE(task_id), + STACK_GUARD_SIZE, + TASK_GUARD_ATTRIBUTES)); +#endif +} + +PRAGMA_OPTIMIZATION_FORCE_START +void task_manager_start(task_main_t idle_task, void *p_idle_task_context) +{ + unsigned long control; + + // Idle task must be specified. + ASSERT(idle_task != NULL); + + // Make sure that we are in privledged thread level using MSP stack. + ASSERT((__get_IPSR() & IPSR_ISR_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_SPSEL_Msk) == 0); + + // Prepare task state structure. + s_current_task_id = IDLE_TASK_ID; + s_task_state[s_current_task_id].p_task_name = "Idle Task"; + + // Prepare stack instrumentation and protection. + task_stack_poison(s_current_task_id); + task_stack_protect(s_current_task_id); + + NRF_LOG_INFO("Task %u created (name: '%s', stack: 0x%08X-0x%08X).", + s_current_task_id, + s_task_state[s_current_task_id].p_task_name, + (uint32_t)BOTTOM_OF_TASK_STACK(s_current_task_id), + (uint32_t)TOP_OF_TASK_STACK(s_current_task_id) - 1); + + // Prepare context for idle task. This must be done with all interrupts disabled. + __disable_irq(); + + // Set process and exception stacks. + __set_PSP((uint32_t)(TOP_OF_TASK_STACK(s_current_task_id))); + __set_MSP((uint32_t)(STACK_TOP)); + + // Update CONTROL register. + control = __get_CONTROL(); + control &= CONTROL_FPCA_Msk; // Clear FPCA since FPU state does not need to be preserved. + control |= CONTROL_SPSEL_Msk; // Use MSP only for excpetions, leaving PSP for tasks. + __set_CONTROL(control); + + // Context is ready. Enable interrupts. + __enable_irq(); + + // Perform task switch to run non-idle tasks as soon as possible. + task_switch(); + + // Jump to idle task. + idle_task(p_idle_task_context); + + // This should be never reached. + APP_ERROR_CHECK_BOOL(false); +} +PRAGMA_OPTIMIZATION_FORCE_END + +task_id_t task_create(task_main_t task, char const * p_task_name, void *p_context) +{ + task_state_t *p_state = NULL; + task_stack_t *p_stack; + task_id_t task_id; + + // Check arguments. + if (task == NULL) + { + return TASK_ID_INVALID; + } + + // Find free task state structure. + CRITICAL_REGION_ENTER(); + for (task_id = 0; task_id < TASK_MANAGER_CONFIG_MAX_TASKS; task_id++) + { + if (s_task_state[task_id].p_stack == NULL) + { + p_state = &s_task_state[task_id]; + p_state->p_stack = TOP_OF_TASK_STACK(task_id); + break; + } + } + CRITICAL_REGION_EXIT(); + + // Return invalid Task ID if new task cannot be created. + if (p_state == NULL) + { + return TASK_ID_INVALID; + } + + // Prepare initial stack for the task. + task_stack_poison(task_id); + + p_state->p_stack = (uint8_t *)(p_state->p_stack) - sizeof(*p_stack); + p_state->p_task_name = (char *)p_task_name; + p_state->flags = 0; + + p_stack = p_state->p_stack; + + p_stack->control = CONTROL_SPSEL_Msk; + p_stack->lr = (uint32_t)(task); // Start from this function. + p_stack->r0 = (uint32_t)(p_context); // Pass p_context as first argument. + + // Mark task as ready to run. + TASK_STATE_RUNNABLE(task_id); + + NRF_LOG_INFO("Task %u created (name: '%s', stack: 0x%08X-0x%08X).", + task_id, + p_task_name, + (uint32_t)BOTTOM_OF_TASK_STACK(task_id), + (uint32_t)TOP_OF_TASK_STACK(task_id) - 1); + + return task_id; +} + +/**@brief Task scheduler. + * + * @param[in] Pointer to task stack with saved task state. + * @return Pointer to new task stack with saved task state. + */ +void *task_schedule(void *p_stack) +{ + uint32_t runnable_tasks_mask; + +#if TASK_MANAGER_CONFIG_STACK_GUARD + // Destroy stack guard allocated for current task. + APP_ERROR_CHECK(nrf_mpu_region_destroy(s_guard_region)); +#endif + + // Save current task state if task if switching from valid task. + if ((s_task_state[s_current_task_id].flags & TASK_FLAG_DESTROY) == 0) + { + s_task_state[s_current_task_id].p_stack = p_stack; + } + else + { + TASK_STATE_SUSPENDED(s_current_task_id); + s_task_state[s_current_task_id].p_stack = NULL; + + NRF_LOG_INFO("Task %u terminated (name: '%s').", + s_current_task_id, + s_task_state[s_current_task_id].p_task_name); + } + + // Atomically fetch list of runnable tasks. + runnable_tasks_mask = s_runnable_tasks_mask; + + // Check if there are any tasks to execute. + if (runnable_tasks_mask != 0) + { + // Check if we could continue this round. + if ((runnable_tasks_mask << (s_current_task_id + 1)) != 0) + { + // There are tasks to execute in this round. Select next runnable task: + s_current_task_id += 1 + __CLZ((runnable_tasks_mask << (s_current_task_id + 1))); + } + else + { + // No more tasks in this round. Select first avaiable task: + s_current_task_id = __CLZ(runnable_tasks_mask); + } + } + else + { + // Fall back to idle task if other tasks cannot be run. + s_current_task_id = IDLE_TASK_ID; + } + + task_stack_protect(s_current_task_id); + + // Switch to new task. + return s_task_state[s_current_task_id].p_stack; +} + +void task_yield(void) +{ + // Make sure that we are in privledged thread level using PSP stack. + ASSERT((__get_IPSR() & IPSR_ISR_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_SPSEL_Msk) != 0); + + // Perform task switch. + task_switch(); +} + +uint32_t task_events_wait(uint32_t evt_mask) +{ + uint32_t current_events; + + ASSERT((evt_mask & ~TASK_FLAG_SIGNAL_MASK) == 0); + + for (;;) + { + current_events = s_task_state[s_current_task_id].flags & evt_mask; + if (current_events != 0) + { + (void)nrf_atomic_u32_and(&s_task_state[s_current_task_id].flags, ~current_events); + break; + } + + TASK_STATE_SUSPENDED(s_current_task_id); + task_yield(); + } + + return current_events; +} + +void task_events_set(task_id_t task_id, uint32_t evt_mask) +{ + ASSERT((task_id != TASK_ID_INVALID) && (task_id < TASK_MANAGER_CONFIG_MAX_TASKS)); + ASSERT((evt_mask & ~TASK_FLAG_SIGNAL_MASK) == 0); + ASSERT(s_task_state[task_id].p_stack != NULL); + + (void)nrf_atomic_u32_or(&s_task_state[task_id].flags, evt_mask); + TASK_STATE_RUNNABLE(task_id); +} + +void task_exit(void) +{ + // Make sure that we are in privledged thread level using PSP stack. + ASSERT((__get_IPSR() & IPSR_ISR_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_SPSEL_Msk) != 0); + + s_task_state[s_current_task_id].flags = TASK_FLAG_DESTROY; + task_switch(); +} + +task_id_t task_id_get(void) +{ + // Make sure that we are in privledged thread level using PSP stack. + ASSERT((__get_IPSR() & IPSR_ISR_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0); + ASSERT((__get_CONTROL() & CONTROL_SPSEL_Msk) != 0); + + return s_current_task_id; +} + +uint32_t task_stack_max_usage_get(task_id_t task_id) +{ +#if TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED + unsigned int stack_usage; + uint32_t *p_stack, *p_stack_top; + + ASSERT((task_id != TASK_ID_INVALID) || (task_id < TASK_MANAGER_CONFIG_MAX_TASKS)); + ASSERT(s_task_state[task_id].p_stack != NULL); + + p_stack_top = TOP_OF_TASK_STACK(task_id); + p_stack = BOTTOM_OF_TASK_STACK(task_id); + stack_usage = TASK_MANAGER_CONFIG_STACK_SIZE; + + while (p_stack < p_stack_top) + { + if (*(p_stack++) != TASK_STACK_MAGIC_WORD) + { + break; + } + + stack_usage -= sizeof(*p_stack); + } + + return stack_usage; +#else + return 0; +#endif +} + +#if TASK_MANAGER_CLI_CMDS +static void task_mnanager_info(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + task_id_t task_id; + + for (task_id = 0; task_id < TOTAL_NUM_OF_TASKS; task_id++) + { + const char *p_task_name = NULL; + + CRITICAL_REGION_ENTER(); + if (s_task_state[task_id].p_stack != NULL) + { + p_task_name = (s_task_state[task_id].p_task_name) ? s_task_state[task_id].p_task_name + : "<NULL>"; + } + CRITICAL_REGION_EXIT(); + + if (p_task_name) + { + uint32_t stack_usage = task_stack_max_usage_get(task_id); + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Task %u:\r\n", task_id); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\tName:\t'%s'\r\n", p_task_name); + + if (stack_usage) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\tStack:\t0x%08X-0x%08X used in %u%% (%u out of %u bytes)\r\n", + (uint32_t)BOTTOM_OF_TASK_STACK(task_id), + (uint32_t)TOP_OF_TASK_STACK(task_id) - 1, + 100 * stack_usage / TASK_MANAGER_CONFIG_STACK_SIZE, + stack_usage, + TASK_MANAGER_CONFIG_STACK_SIZE); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\tStack:\t0x%08X-0x%08X\r\n", + (uint32_t)BOTTOM_OF_TASK_STACK(task_id), + (uint32_t)TOP_OF_TASK_STACK(task_id) - 1); + } + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\tState:\t%s\r\n", + (s_current_task_id == task_id) ? "Running" : + (s_runnable_tasks_mask & TASK_ID_TO_MASK(task_id)) ? "Runnable" : "Suspended"); + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\tFlags:\t0x%08X\r\n\r\n", + s_task_state[task_id].flags); + + } + } +} + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_task_mngr) +{ + NRF_CLI_CMD(info, NULL, "tasks info", task_mnanager_info), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(task_manager, &m_sub_task_mngr, "commands for task manager", NULL); +#endif //TASK_MANAGER_CLI_CMDS +#else //TASK_MANAGER_ENABLED +void *task_schedule(void *p_stack) +{ + return (void *)0; +} +#endif //TASK_MANAGER_ENABLED diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.h new file mode 100644 index 0000000..54c3930 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager.h @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __TASK_MANAGER_H__ +#define __TASK_MANAGER_H__ + + +/** +* @defgroup task_manager Task manager (Cooperative Scheduler) +* @{ +* @ingroup app_common +* @brief Functions for managing tasks +*/ + +#include <stdbool.h> +#include <stdint.h> + +#include "nrf.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Main function of the task. */ +typedef void (* task_main_t)(void * p_context); + +/**@brief Task ID */ +typedef uint8_t task_id_t; + +/**@brief Invalid task ID */ +#define TASK_ID_INVALID ((task_id_t)(-1)) + +/**@brief Start task manager. + * + * @details This function starts the task manager and configures given function as idle task. + * This function never returns. + * + * @param[in] idle_task Main function of the task scheduled when no other tasks could be run. + * @param[in] p_idle_task_context Context passed to idle task. + */ +void task_manager_start(task_main_t idle_task, void * p_idle_task_context); + +/**@brief Create new task. + * + * @param[in] task Function which become main procedure of new task. + * @param[in] p_task_name Task name. + * @param[in] p_context Context passed to task procedure. + * + * @return ID of the task on success, otherwise TASK_ID_INVALID. + */ +task_id_t task_create(task_main_t task, char const * p_task_name, void * p_context); + +/**@brief Yield CPU to other tasks. + */ +void task_yield(void); + +/**@brief Complete current task. + * + * Task stack returns to the pool of available stacks. + */ +void task_exit(void); + +/**@brief Wait for events. Set events are cleared after this function returns. + * + * @param[in] evt_mask Mask of events to wait + * + * @return Mask with set events (can be a subset of evt_mask). + */ +uint32_t task_events_wait(uint32_t evt_mask); + +/**@brief Set events for given task. + * + * @param[in] task_id Id of the task which shall receive events. + * @param[in] evt_mask Events for the task. + * + */ +void task_events_set(task_id_t task_id, uint32_t evt_mask); + +/**@brief Returns maximum depth of task stack. + * + * @param[in] task_id Id of the task (use @ref TASK_ID_INVALID for current task). + * @return Number of bytes ever used on task stack. + */ +uint32_t task_stack_max_usage_get(task_id_t task_id); + +/**@brief Returns ID of currently running task. + * + * @return ID of active task. + */ +task_id_t task_id_get(void); + +/**@brief Set events for given task. + * + * @param[in] task_id Id of the task which name will be returned. + * @return Task name + * + */ +char const * task_name_get(task_id_t task_id); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TASK_MANAGER_H__ */ +/** @} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_armgcc.S b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_armgcc.S new file mode 100644 index 0000000..393e878 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_armgcc.S @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 - 2017, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + .syntax unified + .arch armv7-m + + .text + .thumb + .thumb_func + .align 1 + .global task_switch + .type task_switch, %function + +task_switch: + .fnstart + MRS R0, CONTROL /* Fetch CONTROL register to R0 */ + +#ifdef FLOAT_ABI_HARD + TST R0, #(1 << 2) /* Check FPCA flag. */ + ITTT NE + VMRSNE R1, FPSCR /* If FPCA set, fetch FPSCR. */ + STMDBNE SP!, {R0, R1} /* If FPCA set, save FPSCR (also pad stack to 8-byte alignment) */ + VSTMDBNE SP!, {S0-S31} /* If FPCA set, save FPU registers. */ +#endif + + STMDB SP!, {R0} /* Save CONTROL register. */ + AND R0, R0, #~(1 << 2) /* Clear FPCA bit. */ + MSR CONTROL, R0 /* Update CONTROL register. */ + + STMDB SP!, {R0, R4-R12, LR} /* Save CPU registers. Reserve space for R0, needed to pass argument to new task. */ + + MOV R0, SP /* Call task scheduler with current stack pointer as argument. */ + LDR R1, =task_schedule + BLX R1 + + MOV SP, R0 /* Switch to new stack, returned by task scheduler. */ + + LDMIA SP!, {R3, R4-R12, LR} /* Restore CPU registers. Argument to new task is in R3. */ + LDMIA SP!, {R0} /* Restore CONTROL register. */ + MSR CONTROL, R0 /* Update CONTROL register. */ + +#ifdef FLOAT_ABI_HARD + TST R0, #(1 << 2) /* Check FPCA flag. */ + ITTT NE + VLDMIANE SP!, {S0-S31} /* If FPCA set, restore FPU registers. */ + LDMIANE SP!, {R0, R1} /* If FPCA set, restore FPSCR (also remove padding). */ + VMSRNE FPSCR, R1 /* If FPCA set, update FPSCR */ +#endif + + MOV R0, R3 /* Place optional task argument in R0. */ + BX LR /* Return to new task. */ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_iar.s b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_iar.s new file mode 100644 index 0000000..8205d73 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_iar.s @@ -0,0 +1,83 @@ +; Copyright (c) 2017 - 2017, Nordic Semiconductor ASA +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +; are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form, except as embedded into a Nordic +; Semiconductor ASA integrated circuit in a product or a software update for +; such product, must reproduce the above copyright notice, this list of +; conditions and the following disclaimer in the documentation and/or other +; materials provided with the distribution. +; +; 3. Neither the name of Nordic Semiconductor ASA nor the names of its +; contributors may be used to endorse or promote products derived from this +; software without specific prior written permission. +; +; 4. This software, with or without modification, must only be used with a +; Nordic Semiconductor ASA integrated circuit. +; +; 5. Any software provided in binary form under this license must not be reverse +; engineered, decompiled, modified and/or disassembled. +; +; THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +; OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +; OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + + SECTION .text:CODE:REORDER:NOROOT(2) + THUMB + + PUBLIC task_switch + EXTERN task_schedule + +task_switch + MRS R0, CONTROL ; Fetch CONTROL register to R0 + +#ifdef FLOAT_ABI_HARD + TST R0, #(1 << 2) ; Check FPCA flag. + ITTT NE + VMRSNE R1, FPSCR ; If FPCA set, fetch FPSCR. + STMDBNE SP!, {R0, R1} ; If FPCA set, save FPSCR (also pad stack to 8-byte alignment) + VSTMDBNE SP!, {S0-S31} ; If FPCA set, save FPU registers. +#endif + + STMDB SP!, {R0} ; Save CONTROL register. + AND R0, R0, #~(1 << 2) ; Clear FPCA bit. + MSR CONTROL, R0 ; Update CONTROL register. + + STMDB SP!, {R0, R4-R12, LR} ; Save CPU registers. Reserve space for R0, needed to pass argument to new task. + + MOV R0, SP ; Call task scheduler with current stack pointer as argument. + LDR R1, =task_schedule ; + BLX R1 ; + + MOV SP, R0 ; Switch to new stack, returned by task scheduler. + + LDMIA SP!, {R3, R4-R12, LR} ; Restore CPU registers. Argument to new task is in R3. + LDMIA SP!, {R0} ; Restore CONTROL register. + MSR CONTROL, R0 ; Update CONTROL register. + +#ifdef FLOAT_ABI_HARD + TST R0, #(1 << 2) ; Check FPCA flag. + ITTT NE + VLDMIANE SP!, {S0-S31} ; If FPCA set, restore FPU registers. + LDMIANE SP!, {R0, R1} ; If FPCA set, restore FPSCR (also remove padding). + VMSRNE FPSCR, R1 ; If FPCA set, update FPSCR +#endif + + MOV R0, R3 ; Place optional task argument in R0. + BX LR ; Return to new task. + + END diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_keil.s b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_keil.s new file mode 100644 index 0000000..874b84d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_task_manager/task_manager_core_keil.s @@ -0,0 +1,85 @@ +; Copyright (c) 2017 - 2017, Nordic Semiconductor ASA +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +; are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form, except as embedded into a Nordic +; Semiconductor ASA integrated circuit in a product or a software update for +; such product, must reproduce the above copyright notice, this list of +; conditions and the following disclaimer in the documentation and/or other +; materials provided with the distribution. +; +; 3. Neither the name of Nordic Semiconductor ASA nor the names of its +; contributors may be used to endorse or promote products derived from this +; software without specific prior written permission. +; +; 4. This software, with or without modification, must only be used with a +; Nordic Semiconductor ASA integrated circuit. +; +; 5. Any software provided in binary form under this license must not be reverse +; engineered, decompiled, modified and/or disassembled. +; +; THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +; OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +; OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + + PRESERVE8 + THUMB + AREA |.text|, CODE, READONLY + +task_switch PROC + EXPORT task_switch + IMPORT task_schedule + + MRS R0, CONTROL ; Fetch CONTROL register to R0 + + IF :DEF: FLOAT_ABI_HARD + TST R0, #(1 << 2) ; Check FPCA flag. + ITTT NE + VMRSNE R1, FPSCR ; If FPCA set, fetch FPSCR. + STMDBNE SP!, {R0, R1} ; If FPCA set, save FPSCR (also pad stack to 8-byte alignment) + VSTMDBNE SP!, {S0-S31} ; If FPCA set, save FPU registers. + ENDIF + + STMDB SP!, {R0} ; Save CONTROL register. + AND R0, R0, #~(1 << 2) ; Clear FPCA bit. + MSR CONTROL, R0 ; Update CONTROL register. + + STMDB SP!, {R0, R4-R12, LR} ; Save CPU registers. Reserve space for R0, needed to pass argument to new task. + + MOV R0, SP ; Call task scheduler with current stack pointer as argument. + LDR R1, =task_schedule ; + BLX R1 ; + + MOV SP, R0 ; Switch to new stack, returned by task scheduler. + + LDMIA SP!, {R3, R4-R12, LR} ; Restore CPU registers. Argument to new task is in R3. + LDMIA SP!, {R0} ; Restore CONTROL register. + MSR CONTROL, R0 ; Update CONTROL register. + + IF :DEF: FLOAT_ABI_HARD + TST R0, #(1 << 2) ; Check FPCA flag. + ITTT NE + VLDMIANE SP!, {S0-S31} ; If FPCA set, restore FPU registers. + LDMIANE SP!, {R0, R1} ; If FPCA set, restore FPSCR (also remove padding). + VMSRNE FPSCR, R1 ; If FPCA set, update FPSCR + ENDIF + + MOV R0, R3 ; Place optional task argument in R0. + BX LR ; Return to new task. + + ENDP + END |