diff --git a/LocoNet.cpp b/LocoNet.cpp index 13c6989..d1f732b 100644 --- a/LocoNet.cpp +++ b/LocoNet.cpp @@ -83,11 +83,13 @@ uint8_t eeprom_read_byte(const uint8_t* offset) { void eeprom_write_byte(const uint8_t* offset, uint8_t value) { EEPROM.write((int)offset, value); } -#elif defined(STM32F1) +#elif defined(STM32F1) # include # include # include # include +#elif defined(ARDUINO_ARCH_STM32) +# include #else # include # include @@ -154,7 +156,7 @@ void LocoNetClass::setTxPin(uint8_t txPin) LnPortRegisterType bitMaskTest = 0x01; LnPortRegisterType bitNum = 0; - LnPortRegisterType port = digitalPinToPort(txPin); + auto port = digitalPinToPort(txPin); LnPortAddrType out = portOutputRegister(port); while (bitMask != bitMaskTest) @@ -618,7 +620,7 @@ void LocoNetThrottleClass::updateState(TH_STATE State, uint8_t ForceNotify) void LocoNetThrottleClass::updateStatus1(uint8_t Status, uint8_t ForceNotify) { - register uint8_t Mask; // Temporary uint8_t Variable for bitwise AND to force + uint8_t Mask; // Temporary uint8_t Variable for bitwise AND to force // the compiler to only do 8 bit operations not 16 if (ForceNotify || myStatus1 != Status) @@ -1428,7 +1430,7 @@ void LocoNetFastClockClass::process66msActions(void) } } -#if defined(STM32F1) +#if defined(STM32F1) || defined(ARDUINO_ARCH_STM32) // STM31F1 has no EEPROM. #else @@ -1760,7 +1762,7 @@ SV_STATUS LocoNetSystemVariableClass::doDeferredProcessing(void) return SV_OK; } -#endif // STM32F1 +#endif // STM32F1 || ARDUINO_ARCH_STM32 /***************************************************************************** diff --git a/LocoNet.h b/LocoNet.h index e0c2fb6..8ea28d0 100644 --- a/LocoNet.h +++ b/LocoNet.h @@ -335,7 +335,7 @@ class LocoNetFastClockClass /************************************************************************************ SV (System Variable Handling ************************************************************************************/ -#if defined(STM32F1) +#if defined(STM32F1) || defined(ARDUINO_ARCH_STM32) // STM31F1 has no flash. #else @@ -490,7 +490,7 @@ class LocoNetSystemVariableClass SV_STATUS doDeferredProcessing(void); }; -#endif // STM32F1 +#endif // STM32F1 || ARDUINO_ARCH_STM32 class LocoNetCVClass { diff --git a/README.md b/README.md index 847437f..79b9171 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ It's known to work with: - MEGA (ATmega2560) - Leonardo, LeoStick, Arduino Pro Micro (ATmega32U4) - Various AVRTiny Boards (ATTiny84, ATTiny84A, ATTiny841) -- Blue Pill (STM32F1 w/ libopencm3 and Arduino Stubs) +- Blue Pill (STM32F1 w/ libopencm3 and Arduino Stubs, or STM32F3 with stm32duino core) - NodeMCU v1.0 (ESP8266 core for Arduino) As of 2020-03-28 - Hans Tanner added the capability to change the polarity diff --git a/utility/ln_config.h b/utility/ln_config.h index 58222be..68ebcb1 100644 --- a/utility/ln_config.h +++ b/utility/ln_config.h @@ -55,7 +55,7 @@ // figure out what board we are building // Common defines -#if !defined(STM32F1) && !defined(ESP8266) +#if !defined(STM32F1) && !defined(ARDUINO_ARCH_STM32) && !defined(ESP8266) # ifdef PINL // For the Mega 2560 (should work with 1280, etc) # define _LNET_USE_MEGA # else // For the UNO: @@ -72,7 +72,7 @@ # endif #endif -#if defined(STM32F1) +#if defined(STM32F1) || defined(ARDUINO_ARCH_STM32) typedef uint32_t LnPortRegisterType; typedef uint32_t LnCompareTargetType; #else @@ -97,6 +97,9 @@ typedef volatile LnPortRegisterType* LnPortAddrType; #else # if defined(STM32F1) # define LN_BIT_PERIOD (rcc_apb1_frequency * 2 / 16666) +# elif defined(ARDUINO_ARCH_STM32) + // TMR2 runs at half the CPU clock on the STM32F3. +# define LN_BIT_PERIOD (36000000 / 16666) # else # define LN_BIT_PERIOD (F_CPU / 16666) # endif @@ -209,6 +212,23 @@ defined(__AVR_ATmega1284P__) #define LN_TMR_CONTROL_REG TCCR1B // the code. #define LN_INIT_COMPARATOR() { TCCR1A = 0; TCCR1B = 0x01; } // no prescaler, normal mode +#elif defined(ARDUINO_ARCH_STM32) +// This architecture is used for the stm32 core in Arduino (aka stm32duino, +// also present in the boards manager under 'stm32'. The default settings +// are for an STM32F303RE (nucleo). + +#define LN_RX_PIN_NAME PB14 +#define LN_RX_PORT (*portInputRegister(GPIOB)) +#define LN_RX_BIT (14) +#define LN_RX_BITCFG LL_SYSCFG_EXTI_LINE14 +#define LN_RX_GPIOSEL EXTI_GPIOB +#define LN_RX_GPIOCFG LL_SYSCFG_EXTI_PORTB +#define LN_SB_SIGNAL EXTI15_10_IRQHandler +#define LN_SB_IRQn EXTI15_10_IRQn +#define LN_TMR_SIGNAL TIM2_IRQHandler + +#define ISR(name) extern "C" void name(void) + #elif defined(STM32F1) #define LN_RX_PIN_NAME PB14 diff --git a/utility/ln_sw_uart.cpp b/utility/ln_sw_uart.cpp index 920830f..b205a87 100755 --- a/utility/ln_sw_uart.cpp +++ b/utility/ln_sw_uart.cpp @@ -51,6 +51,12 @@ extern "C" { # include # include # include +#elif defined(ARDUINO_ARCH_STM32) +#include +#include +#include +#include +/// @todo #else # include # include @@ -84,7 +90,7 @@ volatile uint8_t lnTxSuccess; // this boolean flag as a message from timer in volatile uint8_t lnLastTxBit; #endif -#ifndef ESP8266 +#if !defined(ESP8266) && !defined(ARDUINO_ARCH_STM32) volatile uint8_t* txPort; #else LnPortAddrType txPort; @@ -131,7 +137,7 @@ bool ICACHE_RAM_ATTR isLocoNetCollision() } #endif -#if defined(STM32F1) +#if defined(STM32F1) || defined(ARDUINO_ARCH_STM32) # define bit_is_set(PORT, PIN) (((PORT >> PIN) & 0x01) != 0) # define bit_is_clear(PORT, PIN) (((PORT >> PIN) & 0x01) == 0) #endif @@ -160,6 +166,12 @@ ISR(LN_SB_SIGNAL) // Ignore any interrupt that is not EXTI14. return; } +#elif defined(ARDUINO_ARCH_STM32) + // Check if it really was EXTI14 that triggered this interrupt. + if (!LL_EXTI_IsActiveFlag_0_31(1u<DIER = 0; + + // Sets up level change interrupt on RX pin. + LL_SYSCFG_SetEXTISource(LN_RX_GPIOCFG, LN_RX_BITCFG); +# ifdef LN_SW_UART_RX_INVERTED + LL_EXTI_EnableRisingTrig_0_31(LN_EXTI_FLAG); +# else + LL_EXTI_EnableFallingTrig_0_31(LN_EXTI_FLAG); +# endif + + lnState = LN_ST_IDLE; + + LN_CLEAR_START_BIT_FLAG(); + LN_ENABLE_START_BIT_INTERRUPT(); + NVIC_SetPriority(LN_SB_IRQn, 0); + NVIC_EnableIRQ(LN_SB_IRQn); + #else # ifdef LN_INIT_COMPARATOR LN_INIT_COMPARATOR(); @@ -525,6 +591,8 @@ void initLocoNetHardware(LnBuf * RxBuffer) # else attachInterrupt(digitalPinToInterrupt(LN_RX_PORT), ln_esp8266_pin_isr, FALLING); # endif +#elif defined(ARDUINO_ARCH_STM32) + // all of these already done above #else //Clear StartBit Interrupt flag LN_CLEAR_START_BIT_FLAG(); @@ -538,7 +606,7 @@ void initLocoNetHardware(LnBuf * RxBuffer) // Set Timer Clock Source LN_TMR_CONTROL_REG = (LN_TMR_CONTROL_REG & 0xF8) | LN_TMR_PRESCALER; -#endif // STM32F1 +#endif // STM32F1 || ARDUINO_ARCH_STM32 } @@ -609,8 +677,10 @@ LN_STATUS sendLocoNetPacketTry(lnMsg * TxData, unsigned char ucPrioDelay) #else // Before we do anything else - Disable StartBit Interrupt LN_DISABLE_START_BIT_INTERRUPT(); -# if defined(STM32F1) +# if defined(STM32F1) if (exti_get_flag_status(EXTI14)) { +# elif defined(ARDUINO_ARCH_STM32) + if (LL_EXTI_IsActiveFlag_0_31(1u< -#elif !defined(STM32F1) +#elif !defined(STM32F1) && !defined(ARDUINO_ARCH_STM32) # include # include #endif @@ -100,7 +100,28 @@ # define LN_ENABLE_TIMER_INTERRUPT() (timer_enable_irq(TIM2, TIM_DIER_CC1IE)) // Disable Timer Compare Interrupt # define LN_DISABLE_TIMER_INTERRUPT() (timer_disable_irq(TIM2, TIM_DIER_CC1IE)) -#elif !defined(ESP8266) + +#elif defined(ARDUINO_ARCH_STM32) + +# define LN_EXTI_FLAG (1u << LN_RX_BIT) +//Clear StartBit Interrupt flag +# define LN_CLEAR_START_BIT_FLAG() (LL_EXTI_ClearFlag_0_31(LN_EXTI_FLAG)) +//Enable StartBit Interrupt +# define LN_ENABLE_START_BIT_INTERRUPT() (LL_EXTI_EnableIT_0_31(LN_EXTI_FLAG)) +//Disable StartBit Interrupt +# define LN_DISABLE_START_BIT_INTERRUPT() (LL_EXTI_DisableIT_0_31(LN_EXTI_FLAG)) + +// Clear Timer Interrupt Flag +# define LN_CLEAR_TIMER_FLAG() (LL_TIM_ClearFlag_CC1(TIM2)) + +// Enable Timer Compare Interrupt +# define LN_ENABLE_TIMER_INTERRUPT() (LL_TIM_EnableIT_CC1(TIM2)) +// Disable Timer Compare Interrupt +# define LN_DISABLE_TIMER_INTERRUPT() (LL_TIM_DisableIT_CC1(TIM2)) + +#elif defined(ESP8266) +// No common definitions needed for the ESP. +#else // AVR //Clear StartBit Interrupt flag # define LN_CLEAR_START_BIT_FLAG() (sbi( LN_SB_INT_STATUS_REG, LN_SB_INT_STATUS_BIT )) //Enable StartBit Interrupt @@ -117,6 +138,7 @@ # define LN_DISABLE_TIMER_INTERRUPT() (cbi( LN_TMR_INT_ENABLE_REG, LN_TMR_INT_ENABLE_BIT )) #endif + // For now we will simply check that TX and RX ARE NOT THE SAME as our circuit // requires the TX signal to be INVERTED. If they are THE SAME then we have a // Collision.