diff --git a/zephyr/modules/owntech_scheduling/zephyr/CMakeLists.txt b/zephyr/modules/owntech_scheduling/zephyr/CMakeLists.txt index 9d62d3efaed96f3c2ee82b60c252b391ffa27d83..a4c85d0d3372dcfdc2c6935b707f28f18597d132 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/CMakeLists.txt +++ b/zephyr/modules/owntech_scheduling/zephyr/CMakeLists.txt @@ -8,5 +8,8 @@ if(CONFIG_OWNTECH_SCHEDULING) # Select source files to be compiled zephyr_library_sources( public_api/Scheduling.cpp + src/scheduling_common.cpp + src/uninterruptible_synchronous_task.cpp + src/asynchronous_tasks.cpp ) endif() diff --git a/zephyr/modules/owntech_scheduling/zephyr/Kconfig b/zephyr/modules/owntech_scheduling/zephyr/Kconfig index eb85f1c49288b8d54b945a2ea66b28d84ed8be34..de1af3274c87c31149885b9fd0375af6c72e739a 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/Kconfig +++ b/zephyr/modules/owntech_scheduling/zephyr/Kconfig @@ -1,4 +1,25 @@ config OWNTECH_SCHEDULING - bool "Enable OwnTech sceduling" + bool "Enable OwnTech scheduling" default y depends on OWNTECH_TIMER_DRIVER + +if OWNTECH_SCHEDULING + + config OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + bool "Enable support for asychronous tasks" + help + Asynchronous tasks are run in background when no synchronous task is running. + default y + + config OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS + int "Maximum number of asychronous tasks" + help + The higher this value, the more RAM will be reserved for tasks and unavailable to the main program. + default 3 + range 1 5 + + config OWNTECH_SCHEDULING_ASYNCHRONOUS_TASKS_STACK_SIZE + int "Stack size for asynchronous threads" + default 512 + +endif diff --git a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp index cc5777ca37ed85f6cc92358abe50e857c380d195..8a122a0efb0ac36ad719cd7de64568eabb427b79 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp +++ b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.cpp @@ -24,7 +24,9 @@ // OwnTech Power API -#include "timer.h" +#include "../src/uninterruptible_synchronous_task.hpp" +#include "../src/asynchronous_tasks.hpp" + // Current class header #include "Scheduling.h" @@ -33,19 +35,8 @@ ///// // Static variables -const struct device* Scheduling::timer6 = DEVICE_DT_GET(TIMER6_DEVICE); - const int Scheduling::DEFAULT_PRIORITY = 5; -k_tid_t Scheduling::communicationThreadTid; -k_tid_t Scheduling::applicationThreadTid; - -k_thread Scheduling::communicationThreadData; -k_thread Scheduling::applicationThreadData; - -K_THREAD_STACK_DEFINE(communication_thread_stack, 512); -K_THREAD_STACK_DEFINE(application_thread_stack, 512); - ///// // Public object to interact with the class @@ -54,54 +45,33 @@ Scheduling scheduling; ///// -// Private API +// Public API -void Scheduling::threadEntryPoint(void* thread_function_p, void*, void*) +// Non-interruptible control task + +int8_t Scheduling::defineUninterruptibleSynchronousTask(void (*periodic_task)(), uint32_t task_period_us) { - thread_function_t thread_function = (thread_function_t)thread_function_p; - thread_function(); + return scheduling_define_uninterruptible_synchronous_task(periodic_task, task_period_us); } - -///// -// Public API - -void Scheduling::startControlTask(void (*periodic_task)(), uint32_t task_period_us) +void Scheduling::startUninterruptibleSynchronousTask() { - if ( (periodic_task != NULL) && (device_is_ready(timer6) == true) ) - { - // 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; - - timer_config(timer6, &timer_cfg); - timer_start(timer6); - } + scheduling_start_uninterruptible_synchronous_task(); } -void Scheduling::startCommunicationTask(thread_function_t routine, int priority) + +// Asynchronous tasks + +#ifdef CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + +int8_t Scheduling::defineAsynchronousTask(task_function_t routine) { - communicationThreadTid = k_thread_create(&communicationThreadData, - communication_thread_stack, - K_THREAD_STACK_SIZEOF(communication_thread_stack), - threadEntryPoint, - (void*)routine, NULL, NULL, - priority, - 0, - K_NO_WAIT); + return scheduling_define_asynchronous_task(routine); } -void Scheduling::startApplicationTask(thread_function_t routine, int priority) +void Scheduling::startAsynchronousTask(uint8_t task_number) { - applicationThreadTid = k_thread_create(&applicationThreadData, - application_thread_stack, - K_THREAD_STACK_SIZEOF(application_thread_stack), - threadEntryPoint, - (void*)routine, NULL, NULL, - priority, - 0, - K_NO_WAIT); + scheduling_start_asynchronous_task(task_number); } + +#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 dca2ceaf489445e4f09ba00fdf4184d778d89cf4..eb3be2d78fae36d4799d85ea92c1e32a7fcbbadc 100644 --- a/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h +++ b/zephyr/modules/owntech_scheduling/zephyr/public_api/Scheduling.h @@ -33,63 +33,68 @@ #include <zephyr.h> -typedef void (*thread_function_t)(); +typedef void (*task_function_t)(); ///// // Static class definition class Scheduling { -private: - static void threadEntryPoint(void* thread_function_p, void*, void*); - public: /** - * @brief This function uses Timer 6 to execute the periodic user task. - * The task is immediately started. + * @brief Uninterruptible synchronous task uses a timer to + * execute a periodic, non-interruptible user task. + * Use this function to define such a task. + * Only one task of this kind can be defined. * * @param periodic_task Pointer to the void(void) function * to be executed periodically. - * Can be NULL if no task has to be executed. * @param task_period_us Period of the function in µs. * Allowed range: 1 to 6553 µs. * Value is ignored if first parameter is NULL. + * @return 0 if everything went well, + * -1 if there was an error defining the task. + * An error can occur notably when an uninterruptible + * task has already been defined previously. */ - static void startControlTask(void (*periodic_task)(), uint32_t task_period_us); + int8_t defineUninterruptibleSynchronousTask(void (*periodic_task)(), uint32_t task_period_us); + + /** + * @brief Use this function to start the previously defined + * uninterruptible synchronous task. + */ + void startUninterruptibleSynchronousTask(); + + +#ifdef CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS /** - * @brief Schedule the communication thread. - * The task is immediately started. + * @brief Define an asynchronous task. + * Asynchronous tasks are run in background when there + * is no synchronous task running. * * @param routine Pointer to the void(void) function - * that will act as the thread main function. - * @param priority Priority of the thread. This - * parameter can be omitted and will take - * its default value. + * that will act as the task main function. + * @return Number assigned to the task. Will be -1 + * if max number of asynchronous task has been reached. + * In such a case, the task definition is cancelled. + * Increase maximum number of asynchronous tasks in + * prj.conf if required. */ - static void startCommunicationTask(thread_function_t routine, int priority = DEFAULT_PRIORITY); + int8_t defineAsynchronousTask(task_function_t routine); /** - * @brief Schedule the application thread. - * The task is immediately started. - * - * @param routine Pointer to the void(void) function - * that will act as the thread main function. - * @param priority Priority of the thread. This - * parameter can be omitted and will take - * its default value. + * @brief Use this function to start a previously defined + * asynchronous task using its task number. */ - static void startApplicationTask(thread_function_t routine, int priority = DEFAULT_PRIORITY); + void startAsynchronousTask(uint8_t task_number); + +#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + private: - static const struct device* timer6; static const int DEFAULT_PRIORITY; - static k_tid_t communicationThreadTid; - static k_tid_t applicationThreadTid; - - static k_thread communicationThreadData; - static k_thread applicationThreadData; }; diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1156b155810fbd19166ee80c6cca8da88eb02b03 --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + +#ifdef CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + +#include "asynchronous_tasks.hpp" +#include "scheduling_common.hpp" + + +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 uint8_t task_count = 0; + +static const int ASYNCHRONOUS_THREADS_PRIORITY = 14; + + +void _scheduling_user_asynchronous_task_entry_point(void* thread_function_p, void*, void*) +{ + while(1) + { + ((task_function_t)thread_function_p)(); + k_yield(); + } +} + +int8_t scheduling_define_asynchronous_task(task_function_t routine) +{ + if (task_count < CONFIG_OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS) + { + 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]); + + return task_number; + } + else + { + return -1; + } +} + +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); + } +} + + +#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0deca6573253ab323d6c1c4b851b27c59981f334 --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/asynchronous_tasks.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + + +#ifndef ASYNCHRONOUSTASKS_HPP_ +#define ASYNCHRONOUSTASKS_HPP_ + +#ifdef CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + + +// OwnTech Power API +#include "Scheduling.h" + + +int8_t scheduling_define_asynchronous_task(task_function_t routine); +void scheduling_start_asynchronous_task(uint8_t task_number); + + +#endif // CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS + +#endif // ASYNCHRONOUSTASKS_HPP_ diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6630aac9c0ac1b5187aa14ac2da710c8d1f97c6d --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + + +// OwnTech Power API +#include "scheduling_common.hpp" + +void scheduling_common_start_task(task_information_t& task_info, k_thread_entry_t entry_point) +{ + k_tid_t tid = k_thread_create(&task_info.thread_data, + task_info.stack, + task_info.stack_size, + entry_point, + (void*)task_info.routine, NULL, NULL, + task_info.priority, + K_FP_REGS, + K_NO_WAIT); + + task_info.thread_id = tid; +} diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e4c23f82c1c92340af83379b25a5097c80d8d5fc --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/scheduling_common.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + + +#ifndef SCHEDULING_COMMON_HPP_ +#define SCHEDULING_COMMON_HPP_ + +// OwnTech Power API +#include "Scheduling.h" + +typedef struct +{ + task_function_t routine; + int priority; + uint8_t task_number; + k_thread_stack_t* stack; + size_t stack_size; + k_tid_t thread_id; + k_thread thread_data; +} task_information_t; + +void scheduling_common_start_task(task_information_t& task_info, k_thread_entry_t entry_point); + +#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 new file mode 100644 index 0000000000000000000000000000000000000000..e2c1199e669e56205921152547f9dc7ca1bc0cdb --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + + +// OwnTech Power API +#include "timer.h" + +static const struct device* timer6 = DEVICE_DT_GET(TIMER6_DEVICE); +static bool uninterruptibleTaskDefined = false; + +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) ) + { + // 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; + + timer_config(timer6, &timer_cfg); + + uninterruptibleTaskDefined = true; + + return 0; + } + else + { + return -1; + } +} + +void scheduling_start_uninterruptible_synchronous_task() +{ + if ( (device_is_ready(timer6) == true) && (uninterruptibleTaskDefined == true ) ) + { + timer_start(timer6); + } +} diff --git a/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp new file mode 100644 index 0000000000000000000000000000000000000000..55a4cf41085dfe3af2b76c9a745dfd5ceb8b586d --- /dev/null +++ b/zephyr/modules/owntech_scheduling/zephyr/src/uninterruptible_synchronous_task.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 LAAS-CNRS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGLPV2.1 + */ + +/** + * @date 2022 + * @author Clément Foucher <clement.foucher@laas.fr> + */ + + +#ifndef UNINTERRUPTIBLESYNCHRONOUSTASK_HPP_ +#define UNINTERRUPTIBLESYNCHRONOUSTASK_HPP_ + +// 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(); + +#endif // UNINTERRUPTIBLESYNCHRONOUSTASK_HPP_ diff --git a/zephyr/prj.conf b/zephyr/prj.conf index 233e66da9a5fddc196e46f8613d02477cdfe3745..3e3d507ab4b842036107feb14bcdd18b6fa5093b 100644 --- a/zephyr/prj.conf +++ b/zephyr/prj.conf @@ -56,6 +56,13 @@ CONFIG_ASSERT=y # as an external dependecy in the owntech.ini file. #CONFIG_OWNTECH_COMMUNICATION=y +# Modules configuration: uncomment a line to change its value. +# Value provided on a line is the default value of the parameter. + +#CONFIG_OWNTECH_SCHEDULING_ENABLE_ASYNCHRONOUS_TASKS=y +#CONFIG_OWNTECH_SCHEDULING_MAX_ASYNCHRONOUS_TASKS=3 +#CONFIG_OWNTECH_SCHEDULING_ASYNCHRONOUS_TASKS_STACK_SIZE=512 + ##### # OwnTech driver modules: uncomment a line to exclude a module