@ -1,46 +1,83 @@
# include <Arduino.h>
# include <Arduino.h>
# include "FreeRTOS.h"
# include <task.h>
# include <semphr.h>
# include "pico/sync.h"
# include "pico/sync.h"
// RPi-specific timer
# define MULTICORE
struct repeating_timer timer ;
// FreeRTOS main clock task size in bytes
# ifdef MULTICORE
# define CLOCK_STACK_SIZE 5*1024 // adjust for your needs, a sequencer with heavy serial handling should be large in size
// use interrupt version -- works for 2 cores ie can run loop1() and loop() simultaneously as well as the clock callback?
TaskHandle_t taskHandle ;
// mutex to protect the shared resource
SemaphoreHandle_t _mutex ;
// mutex control for task
# define ATOMIC(X) xSemaphoreTake(_mutex, portMAX_DELAY); X; xSemaphoreGive(_mutex);
// forward declaration of uClockHandl er
// RPi-specific timer
void uClockHandler ( ) ;
struct repeating_timer timer ;
// ISR handler -- called when tick happens
# define ATOMIC(X) { uint32_t __interrupt_mask = save_and_disable_interrupts(); X; restore_interrupts(__interrupt_mask); }
bool handlerISR ( repeating_timer * timer )
{
// forward declaration of uClockHandler
void uClockHandler ( ) ;
// ISR handler -- called when tick happens
bool handlerISR ( repeating_timer * timer )
{
uClockHandler ( ) ;
return true ;
}
void initTimer ( uint32_t init_clock )
{
// set up RPi interrupt timer
// todo: actually should be -init_clock so that timer is set to start init_clock us after last tick, instead of init_clock us after finished processing last tick!
add_repeating_timer_us ( init_clock , & handlerISR , NULL , & timer ) ;
}
void setTimer ( uint32_t us_interval ) {
cancel_repeating_timer ( & timer ) ;
// todo: actually should be -init_clock so that timer is set to start init_clock us after last tick, instead of init_clock us after finished processing last tick!
add_repeating_timer_us ( us_interval , & handlerISR , NULL , & timer ) ;
}
# else
// use FreeRTOS scheduling/mutex version -- doesn't work (task starts but does not run) if using loop1() ie core 2
# include "FreeRTOS.h"
# include <task.h>
# include <semphr.h>
// RPi-specific timer
struct repeating_timer timer ;
// FreeRTOS main clock task size in bytes
# define CLOCK_STACK_SIZE 5*1024 // adjust for your needs, a sequencer with heavy serial handling should be large in size
TaskHandle_t taskHandle ;
// mutex to protect the shared resource
SemaphoreHandle_t _mutex ;
// mutex control for task
# define ATOMIC(X) xSemaphoreTake(_mutex, portMAX_DELAY); X; xSemaphoreGive(_mutex);
// forward declaration of uClockHandler
void uClockHandler ( ) ;
// ISR handler -- called when tick happens
bool handlerISR ( repeating_timer * timer )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE ;
BaseType_t xHigherPriorityTaskWoken = pdFALSE ;
// Send a notification to task1
// Send a notification to task1
vTaskNotifyGiveFromISR ( taskHandle , & xHigherPriorityTaskWoken ) ;
vTaskNotifyGiveFromISR ( taskHandle , & xHigherPriorityTaskWoken ) ;
portYIELD_FROM_ISR ( xHigherPriorityTaskWoken ) ;
portYIELD_FROM_ISR ( xHigherPriorityTaskWoken ) ;
return true ;
return true ;
}
}
// task for user clock process
// task for user clock process
void clockTask ( void * pvParameters )
void clockTask ( void * pvParameters )
{
{
while ( 1 ) {
while ( 1 ) {
// wait for a notification from ISR
// wait for a notification from ISR
ulTaskNotifyTake ( pdTRUE , portMAX_DELAY ) ;
ulTaskNotifyTake ( pdTRUE , portMAX_DELAY ) ;
uClockHandler ( ) ;
uClockHandler ( ) ;
}
}
}
}
void initTimer ( uint32_t init_clock )
void initTimer ( uint32_t init_clock )
{
{
// initialize the mutex for shared resource access
// initialize the mutex for shared resource access
_mutex = xSemaphoreCreateMutex ( ) ;
_mutex = xSemaphoreCreateMutex ( ) ;
@ -48,10 +85,14 @@ void initTimer(uint32_t init_clock)
xTaskCreate ( clockTask , " clockTask " , CLOCK_STACK_SIZE , NULL , 1 , & taskHandle ) ;
xTaskCreate ( clockTask , " clockTask " , CLOCK_STACK_SIZE , NULL , 1 , & taskHandle ) ;
// set up RPi interrupt timer
// set up RPi interrupt timer
// todo: actually should be -init_clock so that timer is set to start init_clock us after last tick, instead of init_clock us after finished processing last tick!
add_repeating_timer_us ( init_clock , & handlerISR , NULL , & timer ) ;
add_repeating_timer_us ( init_clock , & handlerISR , NULL , & timer ) ;
}
}
void setTimer ( uint32_t us_interval ) {
void setTimer ( uint32_t us_interval ) {
cancel_repeating_timer ( & timer ) ;
cancel_repeating_timer ( & timer ) ;
// todo: actually should be -init_clock so that timer is set to start init_clock us after last tick, instead of init_clock us after finished processing last tick!
add_repeating_timer_us ( us_interval , & handlerISR , NULL , & timer ) ;
add_repeating_timer_us ( us_interval , & handlerISR , NULL , & timer ) ;
}
}
# endif