Skip to content
Snippets Groups Projects
Commit f9eb3e5c authored by Clément Foucher's avatar Clément Foucher
Browse files

Move to a more generic asynchronous task management.

No more default naming for these tasks, user is in charge of creating its own tasks.
Also renamed "Control task" to "Uninterruptible synchronous task".
parent 50b53ded
No related branches found
No related tags found
1 merge request!40Move to a more generic asynchronous task management.
Showing
with 391 additions and 82 deletions
......@@ -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()
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
......@@ -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
......@@ -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;
};
......
/*
* 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
/*
* 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_
/*
* 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;
}
/*
* 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_
/*
* 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);
}
}
/*
* 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_
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment