diff --git a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp index 692b352c4fec6146976af844e5aff0a8dfc3c904..5189e667c728126281ede7c9e0bb90d6a3c52478 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp +++ b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp @@ -59,6 +59,11 @@ void Scheduling::startUninterruptibleSynchronousTask() scheduling_start_uninterruptible_synchronous_task(); } +void Scheduling::stopUninterruptibleSynchronousTask() +{ + scheduling_stop_uninterruptible_synchronous_task(); +} + // Asynchronous tasks @@ -74,8 +79,10 @@ void Scheduling::startAsynchronousTask(uint8_t task_number) scheduling_start_asynchronous_task(task_number); } -#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS - +void Scheduling::stopAsynchronousTask(uint8_t task_number) +{ + scheduling_stop_asynchronous_task(task_number); +} // Suspend asynchronous tasks @@ -88,3 +95,5 @@ void Scheduling::suspendCurrentTaskUs(uint32_t duration_us) { k_sleep(K_USEC(duration_us)); } + +#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS diff --git a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h index 52a6e5f5524cc05c938a9ddedbe56b736500d2d6..1ebff44b450f85f67a912e4731f8977940789abf 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h +++ b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h @@ -46,6 +46,11 @@ public: * execute a periodic, non-interruptible user task. * Use this function to define such a task. * Only one task of this kind can be defined. + * This function can be used to redefine (replace) a + * previously defined uninterruptible synchronous task, + * but the previously defined task must have been suspended + * (or never started). An error will be returned if the + * previously defined task is still running. * * @param periodic_task Pointer to the void(void) function * to be executed periodically. @@ -65,6 +70,14 @@ public: */ void startUninterruptibleSynchronousTask(); + /** + * @brief Stop the previously started uninterruptible + * synchronous task. + * The task can be then resumed by calling + * startAsynchronousTask() again. + */ + void stopUninterruptibleSynchronousTask(); + #ifdef CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS @@ -86,10 +99,24 @@ public: /** * @brief Use this function to start a previously defined * asynchronous task using its task number. + * + * @param task_number + * Number of the task to start, obtained using the + * defineAsynchronousTask() function. */ void startAsynchronousTask(uint8_t task_number); -#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + /** + * @brief Use this function to stop a previously started + * asynchronous task using its task number. + * The task can be then resumed by calling + * startAsynchronousTask() again. + * + * @param task_number + * Number of the task to stop, obtained using the + * defineAsynchronousTask() function. + */ + void stopAsynchronousTask(uint8_t task_number); /** * @brief This function allows to suspend an asynchronous @@ -113,6 +140,8 @@ public: */ void suspendCurrentTaskUs(uint32_t duration_us); +#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + private: static const int DEFAULT_PRIORITY; diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp index 1156b155810fbd19166ee80c6cca8da88eb02b03..c6472f235a60a3fc2f470300f4886c441c3d5633 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp @@ -31,7 +31,7 @@ static K_THREAD_STACK_ARRAY_DEFINE(asynchronous_thread_stack, CONFIG_OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS, CONFIG_OWNTECH_SCHEDULING_ASYNCHRONOUS_TASKS_STACK_SIZE); -static task_information_t tasks_informations[CONFIG_OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS]; +static task_information_t tasks_information[CONFIG_OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS]; static uint8_t task_count = 0; static const int ASYNCHRONOUS_THREADS_PRIORITY = 14; @@ -53,11 +53,12 @@ int8_t scheduling_define_asynchronous_task(task_function_t routine) uint8_t task_number = task_count; task_count++; - tasks_informations[task_number].routine = routine; - tasks_informations[task_number].priority = ASYNCHRONOUS_THREADS_PRIORITY; - tasks_informations[task_number].task_number = task_number; - tasks_informations[task_number].stack = asynchronous_thread_stack[task_number]; - tasks_informations[task_number].stack_size = K_THREAD_STACK_SIZEOF(asynchronous_thread_stack[task_number]); + tasks_information[task_number].routine = routine; + tasks_information[task_number].priority = ASYNCHRONOUS_THREADS_PRIORITY; + tasks_information[task_number].task_number = task_number; + tasks_information[task_number].stack = asynchronous_thread_stack[task_number]; + tasks_information[task_number].stack_size = K_THREAD_STACK_SIZEOF(asynchronous_thread_stack[task_number]); + tasks_information[task_number].status = task_status_t::defined; return task_number; } @@ -71,7 +72,28 @@ void scheduling_start_asynchronous_task(uint8_t task_number) { if (task_number < task_count) { - scheduling_common_start_task(tasks_informations[task_number], _scheduling_user_asynchronous_task_entry_point); + if (tasks_information[task_number].status == task_status_t::defined) + { + scheduling_common_start_task(tasks_information[task_number], _scheduling_user_asynchronous_task_entry_point); + tasks_information[task_number].status = task_status_t::running; + } + else if (tasks_information[task_number].status == task_status_t::suspended) + { + scheduling_common_resume_task(tasks_information[task_number]); + tasks_information[task_number].status = task_status_t::running; + } + } +} + +void scheduling_stop_asynchronous_task(uint8_t task_number) +{ + if (task_number < task_count) + { + if (tasks_information[task_number].status == task_status_t::running) + { + scheduling_common_suspend_task(tasks_information[task_number]); + tasks_information[task_number].status = task_status_t::suspended; + } } } diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp index 0deca6573253ab323d6c1c4b851b27c59981f334..0e216d00a827609a871aeafa09b93ea75bebf9d1 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp @@ -35,6 +35,7 @@ int8_t scheduling_define_asynchronous_task(task_function_t routine); void scheduling_start_asynchronous_task(uint8_t task_number); +void scheduling_stop_asynchronous_task(uint8_t task_number); #endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp index 6630aac9c0ac1b5187aa14ac2da710c8d1f97c6d..9496612d6d061ac9e435c425427794b910db3987 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp @@ -39,3 +39,13 @@ void scheduling_common_start_task(task_information_t& task_info, k_thread_entry_ task_info.thread_id = tid; } + +void scheduling_common_suspend_task(task_information_t& task_info) +{ + k_thread_suspend(task_info.thread_id); +} + +void scheduling_common_resume_task(task_information_t& task_info) +{ + k_thread_resume(task_info.thread_id); +} diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp index e4c23f82c1c92340af83379b25a5097c80d8d5fc..0a902cd98432a9d9d22df67091116468ecd80ed3 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp @@ -29,6 +29,14 @@ // OwnTech Power API #include "Scheduling.h" +enum class task_status_t +{ + inexistent, + defined, + running, + suspended +}; + typedef struct { task_function_t routine; @@ -38,8 +46,11 @@ typedef struct size_t stack_size; k_tid_t thread_id; k_thread thread_data; + task_status_t status; } task_information_t; void scheduling_common_start_task(task_information_t& task_info, k_thread_entry_t entry_point); +void scheduling_common_suspend_task(task_information_t& task_info); +void scheduling_common_resume_task(task_information_t& task_info); #endif // SCHEDULING_COMMON_HPP_ diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.cpp b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.cpp index e2c1199e669e56205921152547f9dc7ca1bc0cdb..8e6da288696759463af795b5708ce3b3c9d43596 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.cpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.cpp @@ -25,26 +25,45 @@ // OwnTech Power API #include "timer.h" +#include "scheduling_common.hpp" + +///// +// Local variables + +// Timer device static const struct device* timer6 = DEVICE_DT_GET(TIMER6_DEVICE); -static bool uninterruptibleTaskDefined = false; + +// Task status +static task_status_t uninterruptibleTaskStatus = task_status_t::inexistent; + + +///// +// API int8_t scheduling_define_uninterruptible_synchronous_task(void (*periodic_task)(), uint32_t task_period_us) { - if ( (periodic_task != NULL) && (device_is_ready(timer6) == true) && (uninterruptibleTaskDefined == false) ) + if (device_is_ready(timer6) == true) { - // Configure and start timer + if ( (uninterruptibleTaskStatus == task_status_t::inexistent) || (uninterruptibleTaskStatus == task_status_t::suspended)) + { + // Configure and start timer - struct timer_config_t timer_cfg = {0}; - timer_cfg.timer_enable_irq = 1; - timer_cfg.timer_irq_callback = periodic_task; - timer_cfg.timer_irq_t_usec = task_period_us; + struct timer_config_t timer_cfg = {0}; + timer_cfg.timer_enable_irq = 1; + timer_cfg.timer_irq_callback = periodic_task; + timer_cfg.timer_irq_t_usec = task_period_us; - timer_config(timer6, &timer_cfg); + timer_config(timer6, &timer_cfg); - uninterruptibleTaskDefined = true; + uninterruptibleTaskStatus = task_status_t::defined; - return 0; + return 0; + } + else + { + return -1; + } } else { @@ -54,8 +73,24 @@ int8_t scheduling_define_uninterruptible_synchronous_task(void (*periodic_task)( void scheduling_start_uninterruptible_synchronous_task() { - if ( (device_is_ready(timer6) == true) && (uninterruptibleTaskDefined == true ) ) + if (device_is_ready(timer6) == true) + { + if ( (uninterruptibleTaskStatus == task_status_t::defined) || (uninterruptibleTaskStatus == task_status_t::suspended) ) + { + timer_start(timer6); + uninterruptibleTaskStatus = task_status_t::running; + } + } +} + +void scheduling_stop_uninterruptible_synchronous_task() +{ + if (device_is_ready(timer6) == true) { - timer_start(timer6); + if (uninterruptibleTaskStatus == task_status_t::running) + { + timer_stop(timer6); + uninterruptibleTaskStatus = task_status_t::suspended; + } } } diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp index 55a4cf41085dfe3af2b76c9a745dfd5ceb8b586d..6134011207770134ead65996add603960aee6bb2 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp +++ b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp @@ -29,7 +29,10 @@ // OwnTech Power API #include "Scheduling.h" + int8_t scheduling_define_uninterruptible_synchronous_task(void (*periodic_task)(), uint32_t task_period_us); void scheduling_start_uninterruptible_synchronous_task(); +void scheduling_stop_uninterruptible_synchronous_task(); + #endif // UNINTERRUPTIBLESYNCHRONOUSTASK_HPP_ diff --git a/zephyr/modules/owntech_timer_driver/zephyr/public_api/timer.h b/zephyr/modules/owntech_timer_driver/zephyr/public_api/timer.h index f65f7a4bd85283adc1b1078abeadf65c7ccaea88..a6cc88d1bb82dafeee201cf87c86346a75a09f9c 100644 --- a/zephyr/modules/owntech_timer_driver/zephyr/public_api/timer.h +++ b/zephyr/modules/owntech_timer_driver/zephyr/public_api/timer.h @@ -101,12 +101,14 @@ struct timer_config_t typedef void (*timer_api_config) (const struct device* dev, const struct timer_config_t* config); typedef void (*timer_api_start) (const struct device* dev); +typedef void (*timer_api_stop) (const struct device* dev); typedef uint32_t (*timer_api_get_count)(const struct device* dev); __subsystem struct timer_driver_api { - timer_api_config config; + timer_api_config config; timer_api_start start; + timer_api_stop stop; timer_api_get_count get_count; }; @@ -125,7 +127,8 @@ static inline void timer_config(const struct device* dev, const struct timer_con } /** - * Configure the timer dev with given time t_usec in microseconds. + * Start the timer dev. If timer is configured to provide a perdiodic + * interrupt, it will also enable it. * * @param dev Zephyr device representing the timer. */ @@ -136,6 +139,19 @@ static inline void timer_start(const struct device* dev) api->start(dev); } +/** + * Stop the timer dev. If timer is configured to provide a perdiodic + * interrupt, it will also disable it. + * + * @param dev Zephyr device representing the timer. + */ +static inline void timer_stop(const struct device* dev) +{ + const struct timer_driver_api* api = (const struct timer_driver_api*)(dev->api); + + api->stop(dev); +} + /** * Get the current timer counter value. * diff --git a/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.c b/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.c index 71d56ca96126219fe6c524df656b6cb5ac586980..803bff4019d3b02a0c8f30ca0b54b34a6f7546ca 100644 --- a/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.c +++ b/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.c @@ -76,6 +76,7 @@ static const struct timer_driver_api timer_funcs = { .config = timer_stm32_config, .start = timer_stm32_start, + .stop = timer_stm32_stop, .get_count = timer_stm32_get_count }; @@ -162,6 +163,28 @@ void timer_stm32_start(const struct device* dev) } } +void timer_stm32_stop(const struct device* dev) +{ + struct stm32_timer_driver_data* data = (struct stm32_timer_driver_data*)dev->data; + TIM_TypeDef* tim_dev = data->timer_struct; + + if ( (tim_dev == TIM6) || (tim_dev == TIM7) ) + { + if (data->timer_mode == periodic_interrupt) + { + LL_TIM_DisableCounter(tim_dev); + LL_TIM_DisableIT_UPDATE(tim_dev); + } + } + else if (tim_dev == TIM4) + { + if (data->timer_mode == incremental_coder) + { + LL_TIM_DisableCounter(tim_dev); + } + } +} + void timer_stm32_clear(const struct device* dev) { TIM_TypeDef* tim_dev = ((struct stm32_timer_driver_data*)dev->data)->timer_struct; diff --git a/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.h b/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.h index 50a280f313bf5175f88a267d6af726e0cbe64003..2235ffadf1cbe17f66c1ff59f6b004038badede4 100644 --- a/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.h +++ b/zephyr/modules/owntech_timer_driver/zephyr/src/stm32_timer_driver.h @@ -82,6 +82,7 @@ struct stm32_timer_driver_data static int timer_stm32_init(const struct device* dev); void timer_stm32_config(const struct device* dev, const struct timer_config_t* config); void timer_stm32_start(const struct device* dev); +void timer_stm32_stop(const struct device* dev); uint32_t timer_stm32_get_count(const struct device* dev); void timer_stm32_clear(const struct device* dev);