@@ -48,6 +48,7 @@ void dma_tx_callback(dmac_callback_args_t *args);
4848void  dma_rx_callback (dmac_callback_args_t  *args);
4949
5050extern  int  attachIrq2Link (uint32_t  pin, PinStatus mode);
51+ extern  int  getIrqIndexFromPin (uint32_t  pin);
5152typedef  void  (*fsp_dma_callback_t ) (dmac_callback_args_t  *args);
5253
5354static  uint32_t  tx_get_sample (bsp_io_port_pin_t  tx, ioport_size_t  value)
@@ -192,6 +193,7 @@ SoftwareSerial::SoftwareSerial(uint8_t rx_pin, uint8_t tx_pin, size_t bufsize):
192193    assert (rx_pin < NUM_DIGITAL_PINS);
193194    _tx_pin = tx_pin;
194195    _rx_pin = rx_pin;
196+     initialized = false ;
195197}
196198
197199SoftwareSerial::~SoftwareSerial ()
@@ -228,17 +230,26 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
228230            IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_HIGH);
229231    #endif 
230232
233+     /*  TX pin configuration */ 
234+ 
231235    R_IOPORT_PinCfg (&g_ioport_ctrl, tx_descr.pin , IOPORT_CFG_PORT_DIRECTION_OUTPUT
232236            | IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_PORT_OUTPUT_HIGH);
233237
234-     //  Enable RX pin IRQ.
235-     rx_descr.irq_chan  = attachIrq2Link (_rx_pin, CHANGE);
236-     if  (rx_descr.irq_chan  != -1 ) {
237-         //  TODO: workaround for the core not setting pull-ups.
238-         R_IOPORT_PinCfg (&g_ioport_ctrl, rx_descr.pin , IOPORT_CFG_PORT_DIRECTION_INPUT
239-                 | IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_IRQ_ENABLE);
238+     /*  RX pin configuration */ 
239+ 
240+     /*  avoid to call attachIrq2Link if already used because it "consumes" irq
241+        indexes in the NVIC */  
242+     int  irq_index = getIrqIndexFromPin (_rx_pin);
243+     if (irq_index == -1 ) {
244+         rx_descr.irq_chan  = attachIrq2Link (_rx_pin, CHANGE); //  Enable RX pin IRQ.
245+     } else  {
246+         R_BSP_IrqEnable  ((IRQn_Type)irq_index);
240247    }
241248
249+     R_IOPORT_PinCfg (&g_ioport_ctrl, rx_descr.pin , IOPORT_CFG_PORT_DIRECTION_INPUT
250+                 | IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_IRQ_ENABLE);
251+ 
252+ 
242253    //  Set serial configuration.
243254    config.bitshift  = (rx_descr.pin  & 0xFF );
244255    config.polarity  = (inverted) ? 1  : 0 ;
@@ -279,34 +290,36 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
279290    //  be calculated, and the start/stop samples can be prepopulated in the DMA TX buffer.
280291    config.nsamples  = (1  + config.databits  + (!!config.parity ) + config.stopbits );
281292
282-     //  Prepopulate start and stop bits samples.
283-     tx_descr.dmabuf [0 ][0 ] = tx_get_sample (tx_descr.pin , 0 );
284-     for  (size_t  i=0 ; i<config.stopbits ; i++) {
285-         tx_descr.dmabuf [0 ][config.nsamples -1 -i] = tx_get_sample (tx_descr.pin , 1 );
286-     }
293+     if (!initialized) {
294+         //  Prepopulate start and stop bits samples.
295+         tx_descr.dmabuf [0 ][0 ] = tx_get_sample (tx_descr.pin , 0 );
296+         for  (size_t  i=0 ; i<config.stopbits ; i++) {
297+             tx_descr.dmabuf [0 ][config.nsamples -1 -i] = tx_get_sample (tx_descr.pin , 1 );
298+         }
287299
288-     //  Configure the TX DMA and its tigger timer.
289-     R_PORT0_Type *tx_port = SS_PORT_ADDR (((tx_descr.pin  >> 8 ) & 0xFF ));
290-     if  (fsp_tim_config (&tx_descr.tim , config.baudrate , false ) != 0 ) {
291-         return  0 ;
292-     }
300+          //  Configure the TX DMA and its tigger timer.
301+          R_PORT0_Type *tx_port = SS_PORT_ADDR (((tx_descr.pin  >> 8 ) & 0xFF ));
302+          if  (fsp_tim_config (&tx_descr.tim , config.baudrate , false ) != 0 ) {
303+              return  0 ;
304+          }
293305
294-     if  (fsp_dma_config (&tx_descr.dma , SS_DMA_CHANNEL_TX,
295-         fsp_tim_to_elc_event (tx_descr.tim .get_channel ()), tx_descr.dmabuf [0 ],
296-         (void  *) &tx_port->PCNTR3 , config.nsamples , dma_tx_callback, this ) != 0 ) {
297-         return  0 ;
298-     }
306+          if  (fsp_dma_config (&tx_descr.dma , SS_DMA_CHANNEL_TX,
307+              fsp_tim_to_elc_event (tx_descr.tim .get_channel ()), tx_descr.dmabuf [0 ],
308+              (void  *) &tx_port->PCNTR3 , config.nsamples , dma_tx_callback, this ) != 0 ) {
309+              return  0 ;
310+          }
299311
300-     //  Configure the RX DMA and its trigger timer.
301-     R_PORT0_Type *rx_port = SS_PORT_ADDR (((rx_descr.pin  >> 8 ) & 0xFF ));
302-     if  (fsp_tim_config (&rx_descr.tim , config.baudrate , true ) != 0 ) {
303-         return  0 ;
304-     }
312+          //  Configure the RX DMA and its trigger timer.
313+          R_PORT0_Type *rx_port = SS_PORT_ADDR (((rx_descr.pin  >> 8 ) & 0xFF ));
314+          if  (fsp_tim_config (&rx_descr.tim , config.baudrate , true ) != 0 ) {
315+              return  0 ;
316+          }
305317
306-     if  (fsp_dma_config (&rx_descr.dma , SS_DMA_CHANNEL_RX,
307-         fsp_tim_to_elc_event (rx_descr.tim .get_channel ()), rx_descr.dmabuf [0 ],
308-         (void  *) &rx_port->PCNTR2 , config.nsamples , dma_rx_callback, this ) != 0 ) {
309-         return  0 ;
318+         if  (fsp_dma_config (&rx_descr.dma , SS_DMA_CHANNEL_RX,
319+             fsp_tim_to_elc_event (rx_descr.tim .get_channel ()), rx_descr.dmabuf [0 ],
320+             (void  *) &rx_port->PCNTR2 , config.nsamples , dma_rx_callback, this ) != 0 ) {
321+             return  0 ;
322+         }
310323    }
311324
312325    //  Configure and enable the ELC.
@@ -324,6 +337,27 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
324337            tx_descr.pin , rx_descr.pin , config.bitshift , (config.polarity ) ? " Inverted" " Normal" 
325338            config.nsamples , config.baudrate , config.databits , parity_tostr[config.parity ], config.stopbits );
326339    #endif 
340+ 
341+     initialized = true ;
342+     return  1 ;
343+ }
344+ 
345+ int  SoftwareSerial::end () {
346+     int  irq_index = getIrqIndexFromPin (_rx_pin);
347+ 
348+     if (irq_index != -1 ) {
349+         R_BSP_IrqDisable ((IRQn_Type)irq_index);
350+         R_BSP_IrqStatusClear ((IRQn_Type)irq_index);
351+     }
352+ 
353+     if (initialized) {
354+         //  put rx and tx pin as input
355+         R_IOPORT_PinCfg (&g_ioport_ctrl, tx_descr.pin , IOPORT_CFG_PORT_DIRECTION_INPUT);
356+         R_IOPORT_PinCfg (&g_ioport_ctrl, rx_descr.pin , IOPORT_CFG_PORT_DIRECTION_INPUT);
357+ 
358+         R_ELC_Disable (&elc_ctrl);
359+         R_ELC_Close (&elc_ctrl);
360+     }
327361    return  1 ;
328362}
329363
0 commit comments