How To Use ¶
Use the Sequencer as follows:
1. Selecting Files ¶
Add the following source and header files to the project:
Core (mandatory):
sequencer.candsequencer.hConfiguration (optional):
seq_user_conf.h(ifSEQ_USER_CONFIGis defined)
Required files with default configuration:
/Required files
├─ Core/
│ ├─ sequencer.c
└─ └─ sequencer.h
Required files with user configuration:
/Required files
├─ Core/
│ ├─ sequencer.c
│ └─ sequencer.h
├─ Config/
└─ └─ seq_user_conf.h (if ``SEQ_USER_CONFIG`` is defined, copy this file from template and adapt it)
2. Configuration ¶
2.1. Optional Configuration ¶
Enable the custom configuration header by defining
SEQ_USER_CONFIG
in the preprocessor options. Copy the template header and adapt it as needed.
The following table summarizes the configurable items in the optional user configuration header
seq_user_conf.h:
|
Config Item |
Description |
Default Value |
Max Value |
Min Value |
|---|---|---|---|---|
|
|
Number of task bits |
32 |
32 |
1 |
|
|
Priority levels (index 0 is highest) |
2 |
32 |
1 |
|
|
Macro to enter the critical section |
uint32_t primask_bit = __get_PRIMASK( ); __disable_irq( ) |
N/A |
N/A |
|
|
Macro to exit the critical section |
__set_PRIMASK( primask_bit ) |
N/A |
N/A |
|
|
Macro to enter the critical section in idle |
uint32_t primask_bit = __get_PRIMASK( ); __disable_irq( ) |
N/A |
N/A |
|
|
Macro to exit the critical section in idle |
__set_PRIMASK( primask_bit ) |
N/A |
N/A |
|
|
Macro to fill memory with an 8-bit value |
Standard C implementation: memset((dest),(value),(size)) |
N/A |
N/A |
Example minimal custom header:
/* Reduce task count to 8 for small app */
#define SEQ_CONF_TASK_NBR (8U)
/* Two priority levels (0 high / 1 low) */
#define SEQ_CONF_PRIO_NBR (2U)
/* Simple critical section (disable global IRQ) */
#define SEQ_ENTER_CRITICAL_SECTION() uint32_t primask_bit = __get_PRIMASK(); __disable_irq()
#define SEQ_EXIT_CRITICAL_SECTION() __set_PRIMASK(primask_bit)
#define SEQ_ENTER_CRITICAL_SECTION_IDLE() SEQ_ENTER_CRITICAL_SECTION()
#define SEQ_EXIT_CRITICAL_SECTION_IDLE() SEQ_EXIT_CRITICAL_SECTION()
3. Sequencer Initialization ¶
Call
SEQ_Init()
once after the basic hardware initialization and before scheduling tasks.
SEQ_Init(); /* Initialize the Sequencer */
4. Sequencer Usage ¶
After initialization, the following steps are required to use the Sequencer:
Define a task function (void (*task)(void)).
Register the task in the Sequencer with its ID.
Activate the task to make it executable.
Start task scheduling by calling SEQ_Run() in the main loop.
The Sequencer is non-preemptive: each task must return control quickly to allow other tasks to be scheduled.
Two task patterns are commonly used: single-action tasks and state-machine tasks.
Single-action task: performs a simple action and then returns.
void Task1(void)
{
/* Perform a simple action */
}
State-machine task: advances one step per invocation while maintaining internal state.
void Task2(void)
{
static uint32_t state = 0;
switch (state)
{
case 0:
/* Initial actions */
state = 1;
break;
case 1:
/* Second actions */
state = 2;
break;
case 2:
/* Final actions */
state = 0;
break;
}
/* Ready for next step */
SEQ_SetTask(SEQ_TASK2_ID, 0);
}
Register each task with an ID bit and a callback function.
SEQ_RegTask(SEQ_TASK1_ID, SEQ_RFU, Task1); /* Register Task1 in the Sequencer */
To schedule work, set the task bit with a priority index (0 = highest):
SEQ_SetTask(SEQ_TASK1_ID, 0); /* Task1 ready */
Call
SEQ_Run()
inside the infinite loop.
while (1)
{
/* Start scheduling */
SEQ_Run(~0);
}