Yes.
Whiles I am not doing what you are trying to do, I hope this serves as an example:
Code: Select all
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#define evtAnalogVoltReadTask_LIDAR ( 1 << 6 ) //1000000
#define evtfLIDAR_Power_On ( 1 << 7 ) //10000000
#define evtfLIDAR_Power_Off ( 1 << 8 ) //100000000
#define TimerDivider 80
#define TaskCore1 1
#define OneK 1000
#define TaskStack10K 10000
#define LIDAR_PowerControl 14
TickType_t xTicksToWait0 = 0;
TickType_t QueueReceiveDelayTime = 20;
TickType_t xTicksToWait20 = 20;
TickType_t xSemaphoreTicksToWait = 30;
TickType_t xSemaphoreTicksToWait10 = 10;
SemaphoreHandle_t sema_iLIDAR_Power_Reset;
/* create event group */
EventGroupHandle_t eg;
volatile int iTicCount = 0; //counts milliseconds
volatile int iLIDAR_Power_Reset = 0;
void IRAM_ATTR onTimer()
{
BaseType_t xHigherPriorityTaskWoken;
iTicCount++;
xEventGroupSetBitsFromISR(eg, OneMilliSecondGroupBits, &xHigherPriorityTaskWoken);
if ( (iTicCount % 2) == 0 )
{
if ( (xSemaphoreTakeFromISR(sema_ReceiveSerial_LIDAR, &xHigherPriorityTaskWoken)) == pdTRUE ) // grab semaphore, no wait
{
xEventGroupSetBitsFromISR(eg, evtReceiveSerial_LIDAR, &xHigherPriorityTaskWoken); // trigger every 2mS, if not already processing
}
}
if ( iTicCount == OneK )
{
xEventGroupSetBitsFromISR(eg, OneSecondGroupBits, &xHigherPriorityTaskWoken); // trigger every 1X a second
// reset counter to start again
iTicCount = 0;
}
if ( !bLIDAR_OK )
{
xSemaphoreTakeFromISR ( sema_iLIDAR_Power_Reset, &xHigherPriorityTaskWoken );
++iLIDAR_Power_Reset;
xSemaphoreGiveFromISR ( sema_iLIDAR_Power_Reset, &xHigherPriorityTaskWoken);
if ( iLIDAR_Power_Reset >= 4000 )
{
xEventGroupSetBitsFromISR(eg, evtfLIDAR_Power_On, &xHigherPriorityTaskWoken);
}
}
} // void IRAM_ATTR onTimer()
void fLIDAR_Power_On ( void *pvParameters )
{
for ( ;; )
{
xEventGroupWaitBits (eg, evtfLIDAR_Power_On, pdTRUE, pdTRUE, portMAX_DELAY );
fClearSpiffFile();
vTaskDelay( pdMS_TO_TICKS( 1 ) );
xSemaphoreTake ( sema_SPIFF_Buffer, xSemaphoreTicksToWait );
SPIFF_Buffer.concat ("Power up LIDAR" );
xEventGroupSetBits( eg, evtOpenAppendSPIFF_FILE );
digitalWrite ( LIDAR_PowerControl, LOW );
xSemaphoreTake ( sema_iLIDAR_Power_Reset, xSemaphoreTicksToWait );
iLIDAR_Power_Reset = 0;
xSemaphoreGive ( sema_iLIDAR_Power_Reset );
}
vTaskDelete( NULL );
} //void fLIDAR_Power_On ) void *pvParameters )
void setup()
{
eg = xEventGroupCreate();
pinMode( LIDAR_PowerControl, OUTPUT );
digitalWrite ( LIDAR_PowerControl, HIGH );
/* Use 4th timer of 4.
1 tick 1/(80MHZ/80) = 1us set divider 80 and count up.
Attach onTimer function to timer
Set alarm to call timer ISR, every 10000uS and repeat / reset ISR (true) after each alarm
Start an timer alarm
*/
timer = timerBegin( TIMER_FOUR, TimerDivider, true );
timerAttachInterrupt( timer, &onTimer, true );
timerAlarmWrite(timer, OneK, true);
timerAlarmEnable(timer);
sema_iLIDAR_Power_Reset = xSemaphoreCreateMutex();
xSemaphoreGive ( sema_iLIDAR_Power_Reset );
xTaskCreatePinnedToCore ( fLIDAR_Power_On, "fLIDAR_Power_On", TaskStack10K, NULL, Priority5, NULL, TaskCore0 ); // assigned to core 0
} //void setup() // runs on core 1
///////////////////////////
void loop() {} // runs on core 1
I posted other code but I wanted to show how I do a LIDAR power on, so I tried to include all the code for a LIDAR power on.
As you can see the void IRAM_ATTR onTimer() function uses ISR based routines to run various taskings. Instead of functions calls, where the timer has to go to those functions and follow those functions through, the functions are just triggered to run as CPU cycles allow
https://www.freertos.org/a00106.html
Code: Select all
if (dcA) // ON cycle
{
digitalWrite(PIN_A, LOW);
dcA = false;
timerAlarmWrite(timerA, durationON, true);
}
else // OFF cycle
{
digitalWrite(PIN_A, HIGH);
dcA = true;
timerAlarmWrite(timerA, durationOFF, true);
}
You'd replace the above code with a task triggered by an event in the ISR, the task would be wrapped in a semaphore to stop the task from being re-triggered in case the task is already in process when the next interrupt arrives.