From 71bb657e3a7d80edc096094564f5d279e8a1fb69 Mon Sep 17 00:00:00 2001 From: Franz-Peter Date: Mon, 5 Aug 2019 15:14:58 +0200 Subject: [PATCH] Esp32 iram attr (#26) * changed the version to 201 in the header * added conditional compilation for ESP8266 to add ICACHE_RAM_ATTR to ExternalInterruptHandler changed storage for Micros to unsigned long * some tuning to bit recognition and nested IRQ (STM32) --- NmraDcc.cpp | 40 +++++++++++++++++++++++++--------------- NmraDcc.h | 7 ++++++- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/NmraDcc.cpp b/NmraDcc.cpp index 6adfc6e..e16d05e 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -93,7 +93,7 @@ #define MAX_ONEBITHALF 82 #define MIN_ONEBITFULL 82 #define MIN_ONEBITHALF 35 -#define MAX_BITDIFF 18 +#define MAX_BITDIFF 24 // Debug-Ports @@ -217,18 +217,12 @@ #define MODE_TP2 #define SET_TP2 #define CLR_TP2 - //#define MODE_TP2 DDRC |= (1<<2) // A2 - //#define SET_TP2 PORTC |= (1<<2) - //#define CLR_TP2 PORTC &= ~(1<<2) #define MODE_TP3 #define SET_TP3 #define CLR_TP3 #define MODE_TP4 #define SET_TP4 #define CLR_TP4 - //#define MODE_TP4 DDRC |= (1<<4) //A4 - //#define SET_TP4 PORTC |= (1<<4) - //#define CLR_TP4 PORTC &= ~(1<<4) #endif #ifdef DEBUG_PRINT @@ -310,6 +304,8 @@ DCC_PROCESSOR_STATE DccProcState ; portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; void IRAM_ATTR ExternalInterruptHandler(void) +#elif defined(ESP8266) +void ICACHE_RAM_ATTR ExternalInterruptHandler(void) #else void ExternalInterruptHandler(void) #endif @@ -340,9 +336,10 @@ void ExternalInterruptHandler(void) // Bit evaluation without Timer 0 ------------------------------ uint8_t DccBitVal; static int8_t bit1, bit2 ; - static word lastMicros; + static unsigned int lastMicros = 0; static byte halfBit, DCC_IrqRunning; unsigned int actMicros, bitMicros; + #ifdef ALLOW_NESTED_IRQ if ( DCC_IrqRunning ) { // nested DCC IRQ - obviously there are glitches // ignore this interrupt and increment glitchcounter @@ -353,6 +350,7 @@ void ExternalInterruptHandler(void) SET_TP3; return; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> abort IRQ } + #endif SET_TP3; actMicros = micros(); bitMicros = actMicros-lastMicros; @@ -364,11 +362,12 @@ void ExternalInterruptHandler(void) } DccBitVal = ( bitMicros < bitMax ); lastMicros = actMicros; - #ifdef debug - if(DccBitVal) {SET_TP2;} else {CLR_TP2;}; - #endif + + #ifdef ALLOW_NESTED_IRQ DCC_IrqRunning = true; interrupts(); // time critical is only the micros() command,so allow nested irq's + #endif + #ifdef DCC_DEBUG DccProcState.TickCount++; #endif @@ -429,13 +428,10 @@ void ExternalInterruptHandler(void) DccRx.BitCount++; if( abs(bit2-bit1) > MAX_BITDIFF ) { // the length of the 2 halfbits differ too much -> wrong protokoll - CLR_TP2; - CLR_TP3; DccRx.State = WAIT_PREAMBLE; bitMax = MAX_PRAEAMBEL; bitMin = MIN_ONEBITFULL; DccRx.BitCount = 0; - SET_TP4; #if defined ( __STM32F1__ ) detachInterrupt( DccProcState.ExtIntNum ); @@ -562,6 +558,7 @@ void ExternalInterruptHandler(void) { CLR_TP3; DccRx.State = WAIT_PREAMBLE ; + DccRx.BitCount = 0 ; bitMax = MAX_PRAEAMBEL; bitMin = MIN_ONEBITFULL; #ifdef ESP32 @@ -591,9 +588,11 @@ void ExternalInterruptHandler(void) DccRx.TempByte = 0 ; } } + #ifdef ALLOW_NESTED_IRQ + DCC_IrqRunning = false; + #endif CLR_TP1; CLR_TP3; - DCC_IrqRunning = false; } void ackCV(void) @@ -1355,6 +1354,17 @@ void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup #if defined ( __STM32F1__ ) // with STM32F1 the interuptnumber is equal the pin number DccProcState.ExtIntNum = ExtIntPinNum; + // because STM32F1 has a NVIC we must set interuptpriorities + const nvic_irq_num irqNum2nvic[] = { NVIC_EXTI0, NVIC_EXTI1, NVIC_EXTI2, NVIC_EXTI3, NVIC_EXTI4, + NVIC_EXTI_9_5, NVIC_EXTI_9_5, NVIC_EXTI_9_5, NVIC_EXTI_9_5, NVIC_EXTI_9_5, + NVIC_EXTI_15_10, NVIC_EXTI_15_10, NVIC_EXTI_15_10, NVIC_EXTI_15_10, NVIC_EXTI_15_10, NVIC_EXTI_15_10 }; + exti_num irqNum = (exti_num)(PIN_MAP[ExtIntPinNum].gpio_bit); + +// DCC-Input IRQ must be able to interrupt other long low priority ( level15 ) IRQ's + nvic_irq_set_priority ( irqNum2nvic[irqNum], PRIO_DCC_IRQ); + +// Systic must be able to interrupt DCC-IRQ to always get correct micros() values + nvic_irq_set_priority(NVIC_SYSTICK, PRIO_SYSTIC); #else DccProcState.ExtIntNum = ExtIntNum; #endif diff --git a/NmraDcc.h b/NmraDcc.h index d1834c7..38c4b4f 100644 --- a/NmraDcc.h +++ b/NmraDcc.h @@ -49,10 +49,12 @@ #ifndef NMRADCC_IS_IN #define NMRADCC_IS_IN -#define NMRADCC_VERSION 200 // Version 2.0.0 +#define NMRADCC_VERSION 201 // Version 2.0.1 #define MAX_DCC_MESSAGE_LEN 6 // including XOR-Byte +//#define ALLOW_NESTED_IRQ // uncomment to enable nested IRQ's ( only for AVR! ) + typedef struct { uint8_t Size ; @@ -105,6 +107,9 @@ typedef struct #elif defined( __STM32F1__) #define MAXCV (EEPROM_PAGE_SIZE/4 - 1) // number of storage places (CV address could be larger // because STM32 uses virtual adresses) + #undef ALLOW_NESTED_IRQ // This is done with NVIC on STM32 + #define PRIO_DCC_IRQ 9 + #define PRIO_SYSTIC 8 // MUST be higher priority than DCC Irq #else #define MAXCV E2END // the upper limit of the CV value currently defined to max memory. #endif