@@ -48,6 +48,7 @@ void dma_tx_callback(dmac_callback_args_t *args);
48
48
void dma_rx_callback (dmac_callback_args_t *args);
49
49
50
50
extern int attachIrq2Link (uint32_t pin, PinStatus mode);
51
+ extern int getIrqIndexFromPint (uint32_t pin);
51
52
typedef void (*fsp_dma_callback_t ) (dmac_callback_args_t *args);
52
53
53
54
static 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):
192
193
assert (rx_pin < NUM_DIGITAL_PINS);
193
194
_tx_pin = tx_pin;
194
195
_rx_pin = rx_pin;
196
+ initialized = false ;
195
197
}
196
198
197
199
SoftwareSerial::~SoftwareSerial ()
@@ -228,17 +230,26 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
228
230
IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_HIGH);
229
231
#endif
230
232
233
+ /* TX pin configuration */
234
+
231
235
R_IOPORT_PinCfg (&g_ioport_ctrl, tx_descr.pin , IOPORT_CFG_PORT_DIRECTION_OUTPUT
232
236
| IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_PORT_OUTPUT_HIGH);
233
237
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 = getIrqIndexFromPint (_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);
240
247
}
241
248
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
+
242
253
// Set serial configuration.
243
254
config.bitshift = (rx_descr.pin & 0xFF );
244
255
config.polarity = (inverted) ? 1 : 0 ;
@@ -279,34 +290,36 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
279
290
// be calculated, and the start/stop samples can be prepopulated in the DMA TX buffer.
280
291
config.nsamples = (1 + config.databits + (!!config.parity ) + config.stopbits );
281
292
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
+ }
287
299
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
+ }
293
305
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
+ }
299
311
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
+ }
305
317
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
+ }
310
323
}
311
324
312
325
// Configure and enable the ELC.
@@ -324,9 +337,29 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
324
337
tx_descr.pin , rx_descr.pin , config.bitshift , (config.polarity ) ? " Inverted" : " Normal" ,
325
338
config.nsamples , config.baudrate , config.databits , parity_tostr[config.parity ], config.stopbits );
326
339
#endif
340
+
341
+ initialized = true ;
327
342
return 1 ;
328
343
}
329
344
345
+ int SoftwareSerial::end () {
346
+ int irq_index = getIrqIndexFromPint (_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
+ }
361
+ }
362
+
330
363
int SoftwareSerial::read ()
331
364
{
332
365
int chr = -1 ;
0 commit comments