@@ -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