diff --git a/miosix/arch/common/drivers/serial_stm32.cpp b/miosix/arch/common/drivers/serial_stm32.cpp index 4ab54fd46b3ab8729f54c27f0eb4b9bf96363240..f6cb193ff031f88fb24a163f3d49b33161576fb1 100644 --- a/miosix/arch/common/drivers/serial_stm32.cpp +++ b/miosix/arch/common/drivers/serial_stm32.cpp @@ -32,7 +32,6 @@ #include "kernel/sync.h" #include "kernel/scheduler/scheduler.h" #include "interfaces/portability.h" -#include "interfaces/gpio.h" #include "filesystem/ioctl.h" #include "core/cache_cortexMx.h" @@ -45,42 +44,20 @@ static const int numPorts=3; //Supporting only USART1, USART2, USART3 //GPIOS in all families, stm32f1, f2, f4 and l1. Additionally, USART1 is //always connected to the APB2, while USART2 and USART3 are always on APB1 //Unfortunately, this does not hold with DMA. -#ifdef _BOARD_STM32H753XI_EVAL -typedef Gpio<GPIOB_BASE,14> u1tx; -typedef Gpio<GPIOB_BASE,15> u1rx; -#else typedef Gpio<GPIOA_BASE,9> u1tx; typedef Gpio<GPIOA_BASE,10> u1rx; -#endif typedef Gpio<GPIOA_BASE,11> u1cts; typedef Gpio<GPIOA_BASE,12> u1rts; -#if !defined(STM32_NO_SERIAL_2_3) typedef Gpio<GPIOA_BASE,2> u2tx; typedef Gpio<GPIOA_BASE,3> u2rx; typedef Gpio<GPIOA_BASE,0> u2cts; typedef Gpio<GPIOA_BASE,1> u2rts; -//TODO: modify the class constructor so that it takes the gpiopins as -//parameter, so as to allow each board to custom-remap usart pins, -//otherwise this common driver will end up having even more ifdefs -#ifdef _BOARD_STM3220G_EVAL -//The STM3220G_EVAL board maps usart3 to different pins. -typedef Gpio<GPIOC_BASE,10> u3tx; -typedef Gpio<GPIOC_BASE,11> u3rx; -#elif defined(_BOARD_STM32F746ZG_NUCLEO) -//The STM32F746ZG_NUCLEO board maps usart3 to different pins. -typedef Gpio<GPIOD_BASE,8> u3tx; -typedef Gpio<GPIOD_BASE,9> u3rx; -#else -//Default placement typedef Gpio<GPIOB_BASE,10> u3tx; typedef Gpio<GPIOB_BASE,11> u3rx; -#endif - typedef Gpio<GPIOB_BASE,13> u3cts; typedef Gpio<GPIOB_BASE,14> u3rts; -#endif //!defined(STM32_NO_SERIAL_2_3) /// Pointer to serial port classes to let interrupts access the classes static STM32Serial *ports[numPorts]={0}; @@ -389,8 +366,77 @@ static inline bool isInCCMarea(const void *x) { return false; } // 20ms of full data rate. In the 8N1 format one char is made of 10 bits. // So (baudrate/10)*0.02=baudrate/500 STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) - : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500), rxWaiting(0), - idle(true), flowControl(flowControl==RTSCTS), portId(id) + : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500), + flowControl(flowControl==RTSCTS), portId(id) +{ + #ifndef _ARCH_CORTEXM3_STM32 + //stm32f2, f4, l1, f7, h7 require alternate function mapping + switch(id) + { + case 1: + u1tx::alternateFunction(7); + u1rx::alternateFunction(7); + if(flowControl) + { + u1rts::alternateFunction(7); + u1cts::alternateFunction(7); + } + break; + case 2: + u2tx::alternateFunction(7); + u2rx::alternateFunction(7); + if(flowControl) + { + u2rts::alternateFunction(7); + u2cts::alternateFunction(7); + } + break; + case 3: + u3tx::alternateFunction(7); + u3rx::alternateFunction(7); + if(flowControl) + { + u3rts::alternateFunction(7); + u3cts::alternateFunction(7); + } + break; + } + #endif //_ARCH_CORTEXM3_STM32 + + switch(id) + { + case 1: + commonInit(id,baudrate,u1tx::getPin(),u1rx::getPin(), + u1rts::getPin(),u1cts::getPin()); + break; + case 2: + commonInit(id,baudrate,u2tx::getPin(),u2rx::getPin(), + u2rts::getPin(),u3cts::getPin()); + break; + case 3: + commonInit(id,baudrate,u3tx::getPin(),u2rx::getPin(), + u2rts::getPin(),u3cts::getPin()); + break; + } +} + +STM32Serial::STM32Serial(int id, int baudrate, GpioPin tx, GpioPin rx) + : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500), + flowControl(false), portId(id) +{ + commonInit(id,baudrate,tx,rx,tx,rx); //The last two args will be ignored +} + +STM32Serial::STM32Serial(int id, int baudrate, GpioPin tx, GpioPin rx, + miosix::GpioPin rts, miosix::GpioPin cts) + : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500), + flowControl(true), portId(id) +{ + commonInit(id,baudrate,tx,rx,rts,cts); +} + +void STM32Serial::commonInit(int id, int baudrate, GpioPin tx, GpioPin rx, + GpioPin rts, GpioPin cts) { #ifdef SERIAL_DMA dmaTx=0; @@ -402,13 +448,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) if(id<1|| id>numPorts || ports[id-1]!=0) errorHandler(UNEXPECTED); ports[id-1]=this; unsigned int freq=SystemCoreClock; - //Quirk: stm32f1 rx pin has to be in input mode, while stm32f2 and up want - //it in ALTERNATE mode. Go figure... - #ifdef _ARCH_CORTEXM3_STM32 - Mode::Mode_ rxPinMode=Mode::INPUT; - #else //_ARCH_CORTEXM3_STM32 - Mode::Mode_ rxPinMode=Mode::ALTERNATE; - #endif //_ARCH_CORTEXM3_STM32 //Quirk the position of the PPRE1 and PPRE2 bitfields in RCC->CFGR changes #if defined(_ARCH_CORTEXM3_STM32) || defined(_ARCH_CORTEXM3_STM32L1) const unsigned int ppre1=8; @@ -449,28 +488,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) #endif port->CR3=USART_CR3_DMAT | USART_CR3_DMAR; #endif //SERIAL_1_DMA - #ifndef _ARCH_CORTEXM3_STM32 - //Only stm32f2, f4 and l1 have the new alternate function mapping - #ifdef _BOARD_STM32H753XI_EVAL - u1tx::alternateFunction(4); - u1rx::alternateFunction(4); - #else - u1tx::alternateFunction(7); - u1rx::alternateFunction(7); - #endif - if(flowControl) - { - u1rts::alternateFunction(7); - u1cts::alternateFunction(7); - } - #endif //_ARCH_CORTEXM3_STM32 - u1tx::mode(Mode::ALTERNATE); - u1rx::mode(rxPinMode); - if(flowControl) - { - u1rts::mode(Mode::ALTERNATE); - u1cts::mode(rxPinMode); - } NVIC_SetPriority(USART1_IRQn,15);//Lowest priority for serial NVIC_EnableIRQ(USART1_IRQn); #ifndef _ARCH_CORTEXM7_STM32H7 @@ -522,23 +539,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) #endif port->CR3=USART_CR3_DMAT | USART_CR3_DMAR; #endif //SERIAL_2_DMA - #ifndef _ARCH_CORTEXM3_STM32 - //Only stm32f2, f4 and l1 have the new alternate function mapping - u2tx::alternateFunction(7); - u2rx::alternateFunction(7); - if(flowControl) - { - u2rts::alternateFunction(7); - u2cts::alternateFunction(7); - } - #endif //_ARCH_CORTEXM3_STM32 - u2tx::mode(Mode::ALTERNATE); - u2rx::mode(rxPinMode); - if(flowControl) - { - u2rts::mode(Mode::ALTERNATE); - u2cts::mode(rxPinMode); - } NVIC_SetPriority(USART2_IRQn,15);//Lowest priority for serial NVIC_EnableIRQ(USART2_IRQn); #ifndef _ARCH_CORTEXM7_STM32H7 @@ -589,23 +589,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) #endif port->CR3=USART_CR3_DMAT | USART_CR3_DMAR; #endif //SERIAL_3_DMA - #ifndef _ARCH_CORTEXM3_STM32 - //Only stm32f2, f4 and l1 have the new alternate function mapping - u3tx::alternateFunction(7); - u3rx::alternateFunction(7); - if(flowControl) - { - u3rts::alternateFunction(7); - u3cts::alternateFunction(7); - } - #endif //_ARCH_CORTEXM3_STM32 - u3tx::mode(Mode::ALTERNATE); - u3rx::mode(rxPinMode); - if(flowControl) - { - u3rts::mode(Mode::ALTERNATE); - u3cts::mode(rxPinMode); - } NVIC_SetPriority(USART3_IRQn,15);//Lowest priority for serial NVIC_EnableIRQ(USART3_IRQn); #ifndef _ARCH_CORTEXM7_STM32H7 @@ -624,6 +607,20 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl) #endif //!defined(STM32F411xE) && !defined(STM32F401xE) && !defined(STM32F401xC) #endif //!defined(STM32_NO_SERIAL_2_3) } + //Quirk: stm32f1 rx pin has to be in input mode, while stm32f2 and up want + //it in ALTERNATE mode. Go figure... + #ifdef _ARCH_CORTEXM3_STM32 + Mode::Mode_ rxPinMode=Mode::INPUT; + #else //_ARCH_CORTEXM3_STM32 + Mode::Mode_ rxPinMode=Mode::ALTERNATE; + #endif //_ARCH_CORTEXM3_STM32 + tx.mode(Mode::ALTERNATE); + rx.mode(rxPinMode); + if(flowControl) + { + rts.mode(Mode::ALTERNATE); + cts.mode(rxPinMode); + } const unsigned int quot=2*freq/baudrate; //2*freq for round to nearest port->BRR=quot/2 + (quot & 1); //Round to nearest if(flowControl==false) port->CR3 |= USART_CR3_ONEBIT; diff --git a/miosix/arch/common/drivers/serial_stm32.h b/miosix/arch/common/drivers/serial_stm32.h index 19249b8436b850c44388ed34082a7940cddf105c..12d55d0f410e66be5a5fbf2ce2329ac918a8d156 100644 --- a/miosix/arch/common/drivers/serial_stm32.h +++ b/miosix/arch/common/drivers/serial_stm32.h @@ -31,6 +31,7 @@ #include "filesystem/console/console_device.h" #include "kernel/sync.h" #include "kernel/queue.h" +#include "interfaces/gpio.h" #include "board_settings.h" #if defined(_ARCH_CORTEXM3_STM32) && defined(__ENABLE_XRAM) @@ -67,7 +68,13 @@ public: }; /** - * Constructor, initializes the serial port. + * Constructor, initializes the serial port using the default pins, which + * are: + * USART1: tx=PA9 rx=PA10 cts=PA11 rts=PA12 + * USART2: tx=PA2 rx=PA3 cts=PA0 rts=PA1 + * USART3: tx=PB10 rx=PB11 cts=PB13 rts=PB14 + * If you board has a different mapping, use one of the other constructors. + * * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when * attempting to construct multiple objects with the same id. That is, * it is possible to instantiate only one instance of this class for each @@ -78,6 +85,46 @@ public: */ STM32Serial(int id, int baudrate, FlowCtrl flowControl=NOFLOWCTRL); + /** + * Constructor, initializes the serial port using remapped pins and disables + * flow control. + * + * NOTE: for stm32f2, f4, f7 and h7 you have to set the correct alternate + * function to the pins in order to connect then to the USART peripheral + * before passing them to this class. + * + * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when + * attempting to construct multiple objects with the same id. That is, + * it is possible to instantiate only one instance of this class for each + * hardware USART. + * \param id a number 1 to 3 to select which USART + * \param baudrate serial port baudrate + * \param tx tx pin + * \param rx rx pin + */ + STM32Serial(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx); + + /** + * Constructor, initializes the serial port using remapped pins and enables + * flow control. + * + * NOTE: for stm32f2, f4, f7 and h7 you have to set the correct alternate + * function to the pins in order to connect then to the USART peripheral + * before passing them to this class. + * + * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when + * attempting to construct multiple objects with the same id. That is, + * it is possible to instantiate only one instance of this class for each + * hardware USART. + * \param id a number 1 to 3 to select which USART + * \param tx tx pin + * \param rx rx pin + * \param rts rts pin + * \param cts cts pin + */ + STM32Serial(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx, + miosix::GpioPin rts, miosix::GpioPin cts); + /** * Read a block of data * \param buffer buffer where read data will be stored @@ -149,6 +196,12 @@ public: ~STM32Serial(); private: + /** + * Code common for all constructors + */ + void commonInit(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx, + miosix::GpioPin rts, miosix::GpioPin cts); + #ifdef SERIAL_DMA /** * Wait until a pending DMA TX completes, if any @@ -198,7 +251,7 @@ private: DynUnsyncQueue<char> rxQueue; ///< Receiving queue static const unsigned int rxQueueMin=16; ///< Minimum queue size - Thread *rxWaiting; ///< Thread waiting for rx, or 0 + Thread *rxWaiting=0; ///< Thread waiting for rx, or 0 USART_TypeDef *port; ///< Pointer to USART peripheral #ifdef SERIAL_DMA @@ -221,7 +274,7 @@ private: char rxBuffer[rxQueueMin]; bool dmaTxInProgress; ///< True if a DMA tx is in progress #endif //SERIAL_DMA - bool idle; ///< Receiver idle + bool idle=true; ///< Receiver idle const bool flowControl; ///< True if flow control GPIOs enabled const unsigned char portId; ///< 1 for USART1, 2 for USART2, ... }; diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp index 863907ab976c68cdb35916787640e036b9e7cb30..375b99538347ae3eaeb66225c1911e97ac5385b5 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp @@ -77,13 +77,10 @@ void IRQbspInit() ledOn(); delayMs(100); ledOff(); + auto tx=Gpio<GPIOC_BASE,10>::getPin(); tx.alternateFunction(7); + auto rx=Gpio<GPIOC_BASE,11>::getPin(); rx.alternateFunction(7); DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>( - #ifndef STDOUT_REDIRECTED_TO_DCC - new STM32Serial(defaultSerial,defaultSerialSpeed, - defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL))); - #else //STDOUT_REDIRECTED_TO_DCC - new ARMDCC)); - #endif //STDOUT_REDIRECTED_TO_DCC + new STM32Serial(3,defaultSerialSpeed,tx,rx))); } void bspInit2() diff --git a/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp b/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp index fc32a70c2a5eb220987faa2ea0ec131c9c5f985c..24bb3571ff11ec9fb8fde08c1a1604d675379e6a 100644 --- a/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp +++ b/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp @@ -72,9 +72,10 @@ void IRQbspInit() ledOn(); delayMs(100); ledOff(); + auto tx=Gpio<GPIOD_BASE,8>::getPin(); tx.alternateFunction(7); + auto rx=Gpio<GPIOD_BASE,9>::getPin(); rx.alternateFunction(7); DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>( - new STM32Serial(defaultSerial,defaultSerialSpeed, - defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL))); + new STM32Serial(3,defaultSerialSpeed,tx,rx))); } void bspInit2() diff --git a/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp index 860a9227b6e0c72e9e5724289bbbc73aa72a452f..9dbc25d762aea61e8c8a743a7ba782ee17443604 100644 --- a/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp +++ b/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp @@ -78,9 +78,10 @@ void IRQbspInit() ledOn(); delayMs(100); ledOff(); + auto tx=Gpio<GPIOB_BASE,14>::getPin(); tx.alternateFunction(4); + auto rx=Gpio<GPIOB_BASE,15>::getPin(); rx.alternateFunction(4); DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>( - new STM32Serial(defaultSerial,defaultSerialSpeed, - defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL))); + new STM32Serial(1,defaultSerialSpeed,tx,rx))); } void bspInit2() diff --git a/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h b/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h index 820ddea65eacf8e2f4165b3777efb0278169776a..4d1b7fe09b32c5be388818d924ad565ec0302493 100644 --- a/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h +++ b/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h @@ -63,9 +63,8 @@ const unsigned int AUX_TIMER_CLOCK=100000; const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits /// Serial port -const unsigned int defaultSerial=3; +//This board only exposes USART3, without flow control const unsigned int defaultSerialSpeed=19200; -const bool defaultSerialFlowctrl=false; //#define SERIAL_1_DMA //Serial 1 is not used, so not enabling DMA //#define SERIAL_2_DMA //Serial 2 is not used, so not enabling DMA #define SERIAL_3_DMA diff --git a/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h b/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h index 8ce101684d0e957d37ede39b3b1b1c1b8fb742c3..5a70bc3995bee5d5f6d83270a2f69611cd7e73af 100644 --- a/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h +++ b/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h @@ -62,9 +62,8 @@ const unsigned int AUX_TIMER_CLOCK=100000; const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits /// Serial port -const unsigned int defaultSerial=3; +//This board only exposes USART3, without flow control, connected to an UART/USB const unsigned int defaultSerialSpeed=115200; -const bool defaultSerialFlowctrl=false; // #define SERIAL_1_DMA // #define SERIAL_2_DMA #define SERIAL_3_DMA diff --git a/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h b/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h index cb4af9693756182c2022d1441b2b2effe7c18459..7466ebafb3cb7b7d0601d9b7dece5f0bd4f763de 100644 --- a/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h +++ b/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h @@ -62,9 +62,8 @@ const unsigned int AUX_TIMER_CLOCK=100000; const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits /// Serial port -const unsigned int defaultSerial=1; +//This board only exposes USART1, without flow control const unsigned int defaultSerialSpeed=115200; -const bool defaultSerialFlowctrl=false; // #define SERIAL_1_DMA //TODO: serial port DMA // #define SERIAL_2_DMA // #define SERIAL_3_DMA