11 #if !defined(__AVR__) && !defined(__SAM3X8E__)
12 #error board not supported, error
22 #define TASKS_MEASURE_PIN 0
23 #if (TASKS_MEASURE_PIN)
24 #define SET_PIN (PORTB |= B00000010)
25 #define CLEAR_PIN (PORTB &= ~B00000010)
26 #define TOGGLE_PIN (PORTB ^= B00000010)
33 #define PAUSE_INTERRUPTS { oldISR = SREG; noInterrupts(); }
34 #define RESUME_INTERRUPTS { SREG = oldISR; interrupts(); }
35 #elif defined(__SAM3X8E__)
36 #define PAUSE_INTERRUPTS { oldISR = ((__get_PRIMASK() & 0x1) == 0 && (__get_FAULTMASK() & 0x1) == 0); noInterrupts(); }
37 #define RESUME_INTERRUPTS { if (oldISR != 0) { interrupts(); } }
42 typedef struct SchedulingStruct
54 bool SchedulingActive;
60 #if defined(__SAM3X8E__)
74 void startTasksTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency)
76 pmc_set_writeprotect(
false);
77 pmc_enable_periph_clk((uint32_t)irq);
78 TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
79 uint32_t rc = (SystemCoreClock >> 1)/frequency;
81 TC_SetRC(tc, channel, rc);
82 TC_Start(tc, channel);
83 tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
84 tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
85 NVIC_SetPriority(SysTick_IRQn, 8);
86 NVIC_SetPriority(irq, 15);
92 void Scheduler_update_nexttime(
void)
98 _nexttime = _timebase + INT16_MAX;
99 for (uint8_t i = 0; i < _lasttask; i++) {
100 if ((SchedulingTable[i].active ==
true) && (SchedulingTable[i].func != NULL)) {
108 if ((int16_t)(SchedulingTable[i].time - _nexttime) < 0) {
109 _nexttime = SchedulingTable[i].time;
148 SchedulingActive =
false;
155 SchedulingTable[i].func = NULL;
156 SchedulingTable[i].active =
false;
157 SchedulingTable[i].running =
false;
158 SchedulingTable[i].period = 0;
159 SchedulingTable[i].time = 0;
175 if ((period < 0) || (delay < 0))
180 delay = (uint16_t)(((((int32_t)delay) * 250) + 128) >> 8);
181 period = (uint16_t)(((((int32_t)period) * 250) + 128) >> 8);
185 for(uint8_t i = 0; i < _lasttask; i++)
191 if (SchedulingTable[i].func == func)
193 SchedulingTable[i].active =
true;
194 SchedulingTable[i].running =
false;
195 SchedulingTable[i].period = period;
196 SchedulingTable[i].time = _timebase + delay;
202 Scheduler_update_nexttime();
220 if (SchedulingTable[i].func == NULL)
223 SchedulingTable[i].func = func;
224 SchedulingTable[i].active =
true;
225 SchedulingTable[i].running =
false;
226 SchedulingTable[i].period = period;
227 SchedulingTable[i].time = _timebase + delay;
237 Scheduler_update_nexttime();
263 for (uint8_t i = 0; i < _lasttask; i++)
269 if (SchedulingTable[i].func == func)
272 SchedulingTable[i].func = NULL;
273 SchedulingTable[i].active =
false;
274 SchedulingTable[i].running =
false;
275 SchedulingTable[i].period = 0;
276 SchedulingTable[i].time = 0;
279 if (i == (_lasttask - 1))
282 while(_lasttask != 0)
284 if(SchedulingTable[_lasttask - 1].func != NULL)
296 Scheduler_update_nexttime();
327 delay = (uint16_t)(((((int32_t)delay) * 250) + 128) >> 8);
331 for (uint8_t i = 0; i < _lasttask; i++)
337 if (SchedulingTable[i].func == func)
340 if (SchedulingTable[i].running ==
true)
341 SchedulingTable[i].time = SchedulingTable[i].time - SchedulingTable[i].period;
344 SchedulingTable[i].time = _timebase + delay;
350 Scheduler_update_nexttime();
376 for (uint8_t i = 0; i < _lasttask; i++)
382 if(SchedulingTable[i].func == func)
385 SchedulingTable[i].active = state;
386 SchedulingTable[i].time = _timebase + SchedulingTable[i].period;
392 Scheduler_update_nexttime();
414 #if (TASKS_MEASURE_PIN)
419 SchedulingActive =
true;
422 _nexttime = _timebase;
426 TIMSK0 |= (1<<OCIE0A);
427 #elif defined(__SAM3X8E__)
428 startTasksTimer(TC1, 0, TC3_IRQn, 1000);
432 Scheduler_update_nexttime();
441 SchedulingActive =
false;
446 TIMSK0 &= ~(1<<OCIE0A);
447 #elif defined(__SAM3X8E__)
448 NVIC_DisableIRQ(TC3_IRQn);
461 ISR(TIMER0_COMPA_vect)
462 #elif defined(__SAM3X8E__)
463 void TC3_Handler(
void)
465 void Scheduler_dummy_handler(
void)
471 #if (TASKS_MEASURE_PIN)
475 #if defined(__SAM3X8E__)
476 TC_GetStatus(TC1, 0);
480 if (SchedulingActive ==
false) {
481 #if (TASKS_MEASURE_PIN) // measure speed via GPIO
491 if ((int16_t)(_nexttime - _timebase) > 0) {
492 #if (TASKS_MEASURE_PIN) // measure speed via GPIO
499 for(i = 0; i < _lasttask; i++)
505 if ((SchedulingTable[i].active ==
true) && (SchedulingTable[i].running ==
false) && (SchedulingTable[i].func != NULL))
508 if((int16_t)(SchedulingTable[i].time - _timebase) <= 0)
511 SchedulingTable[i].running =
true;
512 SchedulingTable[i].time = _timebase + SchedulingTable[i].period;
518 SchedulingTable[i].func();
524 SchedulingTable[i].running =
false;
527 if(SchedulingTable[i].period == 0)
529 SchedulingTable[i].func = NULL;
543 Scheduler_update_nexttime();
546 #if (TASKS_MEASURE_PIN)
void(* Task)(void)
Example prototype for a function than can be executed as a task.
void Tasks_Pause(void)
Pause the task scheduler.
void Tasks_Start(void)
Start the task scheduler.
bool Tasks_SetState(Task func, bool state)
Enable or disable the execution of a task.
bool Tasks_Add(Task func, int16_t period, int16_t delay)
Add a task to the task scheduler.
#define MAX_TASK_CNT
Maximum number of parallel tasks.
void Tasks_Init(void)
Initialize and reset the tasks library.
bool Tasks_Delay(Task func, int16_t delay)
Delay execution of a task.
Library providing a simple task scheduler for multitasking.
bool Tasks_Remove(Task func)
Remove a task from the task scheduler.