enhance esp32 usage by hidding concurrency handle implementation using freertos task

pull/26/head
midilab 1 year ago
parent 9c08252ac3
commit 78a503a629
  1. 13
      examples/ESP32UartMasterMidiClock/ESP32UartMasterMidiClock.ino
  2. 2
      library.json
  3. 2
      library.properties
  4. 57
      src/platforms/esp32.h
  5. 4
      src/platforms/samd.h
  6. 4
      src/platforms/stm32.h
  7. 4
      src/platforms/teensy.h
  8. 6
      src/uClock.cpp
  9. 2
      src/uClock.h

@ -18,8 +18,6 @@
// the blue led // the blue led
#define LED_BUILTIN 2 #define LED_BUILTIN 2
volatile bool _midi_clk_income = false;
uint8_t bpm_blink_timer = 1; uint8_t bpm_blink_timer = 1;
void handle_bpm_led(uint32_t tick) void handle_bpm_led(uint32_t tick)
{ {
@ -38,8 +36,7 @@ void handle_bpm_led(uint32_t tick)
// Internal clock handlers // Internal clock handlers
void ClockOut96PPQN(uint32_t tick) { void ClockOut96PPQN(uint32_t tick) {
// Send MIDI_CLOCK to external gears // Send MIDI_CLOCK to external gears
//Serial.write(MIDI_CLOCK); Serial.write(MIDI_CLOCK);
_midi_clk_income = true;
handle_bpm_led(tick); handle_bpm_led(tick);
} }
@ -74,11 +71,5 @@ void setup() {
// Do it whatever to interface with Clock.stop(), Clock.start(), Clock.setTempo() and integrate your environment... // Do it whatever to interface with Clock.stop(), Clock.start(), Clock.setTempo() and integrate your environment...
void loop() { void loop() {
// watch for income signal from uClock to fire the clock over midi
if (_midi_clk_income) {
Serial.write(MIDI_CLOCK);
noInterrupts();
_midi_clk_income = false;
interrupts();
}
} }

@ -1,6 +1,6 @@
{ {
"name": "uClock", "name": "uClock",
"version": "1.4.1", "version": "1.4.2",
"description": "A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0. ESP32 and STM32)", "description": "A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0. ESP32 and STM32)",
"keywords": "bpm, clock, timing, tick, music, generator", "keywords": "bpm, clock, timing, tick, music, generator",
"repository": "repository":

@ -1,5 +1,5 @@
name=uClock name=uClock
version=1.4.1 version=1.4.2
author=Romulo Silva <contact@midilab.co> author=Romulo Silva <contact@midilab.co>
maintainer=Romulo Silva <contact@midilab.co> maintainer=Romulo Silva <contact@midilab.co>
sentence=BPM clock generator for Arduino platform. sentence=BPM clock generator for Arduino platform.

@ -1,26 +1,71 @@
#include <Arduino.h> #include <Arduino.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#define TIMER_ID 0 #define TIMER_ID 0
hw_timer_t * _uclockTimer = NULL; hw_timer_t * _uclockTimer = NULL;
portMUX_TYPE _uclockTimerMux = portMUX_INITIALIZER_UNLOCKED; // mutex control for ISR
#define ATOMIC(X) portENTER_CRITICAL_ISR(&_uclockTimerMux); X; portEXIT_CRITICAL_ISR(&_uclockTimerMux); //portMUX_TYPE _uclockTimerMux = portMUX_INITIALIZER_UNLOCKED;
//#define ATOMIC(X) portENTER_CRITICAL_ISR(&_uclockTimerMux); X; portEXIT_CRITICAL_ISR(&_uclockTimerMux);
// FreeRTOS main clock task size in bytes
#define CLOCK_STACK_SIZE 2048
// semaphore to signal the task from the ISR
SemaphoreHandle_t _semaphore;
// mutex to protect the shared resource
SemaphoreHandle_t _mutex;
// mutex control for task
#define ATOMIC(X) \
do { \
xSemaphoreTake(_mutex, portMAX_DELAY); \
X; \
xSemaphoreGive(_mutex); \
} while (0);
// forward declaration of uClockHandler
void uClockHandler();
// ISR handler
void ARDUINO_ISR_ATTR handlerISR(void)
{
// notify the clockTask using the semaphore
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(_semaphore, &xHigherPriorityTaskWoken);
// context switch is required? request it
if (xHigherPriorityTaskWoken == pdTRUE)
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// forward declaration of ISR // task for user clock process
void ARDUINO_ISR_ATTR uclockISR(); void clockTask(void *pvParameters)
{
while (1)
if (xSemaphoreTake(_semaphore, portMAX_DELAY) == pdTRUE)
uClockHandler();
}
void initTimer(uint32_t init_clock) void initTimer(uint32_t init_clock)
{ {
_uclockTimer = timerBegin(TIMER_ID, 80, true); _uclockTimer = timerBegin(TIMER_ID, 80, true);
// attach to generic uclock ISR // attach to generic uclock ISR
timerAttachInterrupt(_uclockTimer, &uclockISR, false); timerAttachInterrupt(_uclockTimer, &handlerISR, false);
// init clock tick time // init clock tick time
timerAlarmWrite(_uclockTimer, init_clock, true); timerAlarmWrite(_uclockTimer, init_clock, true);
// activate it! // activate it!
timerAlarmEnable(_uclockTimer); timerAlarmEnable(_uclockTimer);
// initialize the semaphore
_semaphore = xSemaphoreCreateBinary();
// initialize the mutex for shared resource access
_mutex = xSemaphoreCreateMutex();
// create the clockTask
xTaskCreate(clockTask, "clockTask", CLOCK_STACK_SIZE, NULL, 1, NULL);
} }
void setTimer(uint32_t us_interval) void setTimer(uint32_t us_interval)

@ -11,14 +11,14 @@
IntervalTimer _uclockTimer; IntervalTimer _uclockTimer;
// forward declaration of ISR // forward declaration of ISR
void uclockISR(); void uClockHandler();
void initTimer(uint32_t init_clock) void initTimer(uint32_t init_clock)
{ {
TimerTcc0.initialize(init_clock); TimerTcc0.initialize(init_clock);
// attach to generic uclock ISR // attach to generic uclock ISR
TimerTcc0.attachInterrupt(uclockISR); TimerTcc0.attachInterrupt(uClockHandler);
} }
void setTimer(uint32_t us_interval) void setTimer(uint32_t us_interval)

@ -16,12 +16,12 @@ HardwareTimer * _uclockTimer = new HardwareTimer(TimerInstance);
#define ATOMIC(X) noInterrupts(); X; interrupts(); #define ATOMIC(X) noInterrupts(); X; interrupts();
// forward declaration of ISR // forward declaration of ISR
void uclockISR(); void uClockHandler();
void initTimer(uint32_t us_interval) void initTimer(uint32_t us_interval)
{ {
_uclockTimer->setOverflow(us_interval, MICROSEC_FORMAT); _uclockTimer->setOverflow(us_interval, MICROSEC_FORMAT);
_uclockTimer->attachInterrupt(uclockISR); _uclockTimer->attachInterrupt(uClockHandler);
_uclockTimer->resume(); _uclockTimer->resume();
} }

@ -5,11 +5,11 @@
IntervalTimer _uclockTimer; IntervalTimer _uclockTimer;
// forward declaration of ISR // forward declaration of ISR
void uclockISR(); void uClockHandler();
void initTimer(uint32_t init_clock) void initTimer(uint32_t init_clock)
{ {
_uclockTimer.begin(uclockISR, init_clock); _uclockTimer.begin(uClockHandler, init_clock);
// Set the interrupt priority level, controlling which other interrupts // Set the interrupt priority level, controlling which other interrupts
// this timer is allowed to interrupt. Lower numbers are higher priority, // this timer is allowed to interrupt. Lower numbers are higher priority,

@ -2,7 +2,7 @@
* @file uClock.cpp * @file uClock.cpp
* Project BPM clock generator for Arduino * Project BPM clock generator for Arduino
* @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32) * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32)
* @version 1.4.1 * @version 1.4.2
* @author Romulo Silva * @author Romulo Silva
* @date 10/06/2017 * @date 10/06/2017
* @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co * @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co
@ -414,10 +414,8 @@ volatile uint32_t _timer = 0;
// //
#if defined(ARDUINO_ARCH_AVR) #if defined(ARDUINO_ARCH_AVR)
ISR(TIMER1_COMPA_vect) ISR(TIMER1_COMPA_vect)
#elif defined(ARDUINO_ARCH_ESP32) || defined(ESP32)
void ARDUINO_ISR_ATTR uclockISR()
#else #else
void uclockISR() void uClockHandler()
#endif #endif
{ {
// global timer counter // global timer counter

@ -2,7 +2,7 @@
* @file uClock.h * @file uClock.h
* Project BPM clock generator for Arduino * Project BPM clock generator for Arduino
* @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32) * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32)
* @version 1.4.1 * @version 1.4.2
* @author Romulo Silva * @author Romulo Silva
* @date 10/06/2017 * @date 10/06/2017
* @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co * @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co

Loading…
Cancel
Save