diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 89dbff873f..7ebc77b791 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -107,6 +107,20 @@ void timer1_attachInterrupt(void (*userFunc)(void)); void timer1_detachInterrupt(void); void timer1_write(uint32_t ticks); //maximum ticks 8388607 +// timer0 is a special CPU timer that has very high resolution but with +// limited control. +// it uses CCOUNT (ESP.GetCycleCount()) as the non-resetable timer counter +// it does not support divide, type, or reload flags +// it is auto-disabled when the compare value matches CCOUNT +// it is auto-enabled when the compare value changes +#define timer0_interrupted() (ETS_INTR_PENDING() & (_BV(ETS_COMPARE0_INUM))) +#define timer0_read() (ESP.getCycleCompare0()) +#define timer0_write(ticks) (ESP.setCycleCompare0(ticks)) + +void timer0_isr_init(void); +void timer0_attachInterrupt(void(*userFunc)(void)); +void timer0_detachInterrupt(void); + // undefine stdlib's abs if encountered #ifdef abs #undef abs @@ -126,13 +140,13 @@ void ets_intr_unlock(); // level 15 will disable ALL interrupts, // level 0 will disable most software interrupts // -#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) "; esync; isync; dsync" : "=a" (state)) +#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)) #define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; esync" :: "a" (state) : "memory") extern uint32_t interruptsState; #define interrupts() xt_enable_interrupts(interruptsState) -#define noInterrupts() __asm__ __volatile__("rsil %0,15; esync; isync; dsync" : "=a" (interruptsState)) +#define noInterrupts() __asm__ __volatile__("rsil %0,15" : "=a" (interruptsState)) #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 5e356459e1..c887c89e92 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -99,15 +99,31 @@ class EspClass { uint32_t getFlashChipSizeByChipId(void); inline uint32_t getCycleCount(void); + inline uint32_t getCycleCompare0(void); + inline void setCycleCompare0(uint32_t count); }; uint32_t EspClass::getCycleCount(void) { uint32_t ccount; - __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); + __asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount)); return ccount; } +// this returns a value in the range of (0 - 2^32) +uint32_t EspClass::getCycleCompare0(void) +{ + uint32_t count; + __asm__ __volatile__("esync; rsr %0,ccompare0":"=a" (count)); + return count; +} + +// this takes a value in the range of (0 - 2^32) +void EspClass::setCycleCompare0(uint32_t count) +{ + __asm__ __volatile__("wsr %0,ccompare0; esync"::"a" (count) : "memory"); +} + extern EspClass ESP; #endif //ESP_H diff --git a/cores/esp8266/core_esp8266_timer.c b/cores/esp8266/core_esp8266_timer.c index bfdd3692cf..979ab0bfc1 100644 --- a/cores/esp8266/core_esp8266_timer.c +++ b/cores/esp8266/core_esp8266_timer.c @@ -59,3 +59,25 @@ void timer1_disable(){ T1C = 0; T1I = 0; } + +void(*timer0_user_cb)(void); + +void timer0_isr_handler(void *para){ + if (timer0_user_cb) { + timer0_user_cb(); + } +} + +void timer0_isr_init(){ + ETS_CCOMPARE0_INTR_ATTACH(timer0_isr_handler, NULL); +} + +void timer0_attachInterrupt(void(*userFunc)(void)) { + timer1_user_cb = userFunc; + ETS_CCOMPARE0_ENABLE(); +} + +void timer0_detachInterrupt() { + timer1_user_cb = NULL; + ETS_CCOMPARE0_DISABLE(); +} \ No newline at end of file diff --git a/tools/sdk/include/ets_sys.h b/tools/sdk/include/ets_sys.h index 7908699bb5..3cdb51d2af 100644 --- a/tools/sdk/include/ets_sys.h +++ b/tools/sdk/include/ets_sys.h @@ -43,6 +43,7 @@ typedef void (*int_handler_t)(void*); #define ETS_GPIO_INUM 4 #define ETS_UART_INUM 5 #define ETS_UART1_INUM 5 +#define ETS_CCOMPARE0_INUM 6 #define ETS_FRC_TIMER1_INUM 9 /* use edge*/ #define ETS_INTR_LOCK() \ @@ -51,6 +52,9 @@ typedef void (*int_handler_t)(void*); #define ETS_INTR_UNLOCK() \ ets_intr_unlock() +#define ETS_CCOMPARE0_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_CCOMPARE0_INUM, (int_handler_t)(func), (void *)(arg)) + #define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ ets_isr_attach(ETS_FRC_TIMER1_INUM, (int_handler_t)(func), (void *)(arg)) @@ -69,6 +73,18 @@ typedef void (*int_handler_t)(void*); #define ETS_INTR_DISABLE(inum) \ ets_isr_mask((1<