Skip to content

Commit e732698

Browse files
committed
Fix stop bit time.
After transferring the last stop bit the TX GPIO needs to stay high until the trigger timer cycle is complete, otherwise the receiver may fail to decode a stop bit.
1 parent fedf789 commit e732698

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

Diff for: libraries/SoftwareSerial/src/SoftwareSerial.cpp

+18-9
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
290290
if (fsp_tim_config(&tx_descr.tim, config.baudrate, false) != 0) {
291291
return 0;
292292
}
293+
293294
if (fsp_dma_config(&tx_descr.dma, SS_DMA_CHANNEL_TX,
294295
fsp_tim_to_elc_event(tx_descr.tim.get_channel()), tx_descr.dmabuf[0],
295296
(void *) &tx_port->PCNTR3, config.nsamples, dma_tx_callback, this) != 0) {
@@ -301,6 +302,7 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
301302
if (fsp_tim_config(&rx_descr.tim, config.baudrate, true) != 0) {
302303
return 0;
303304
}
305+
304306
if (fsp_dma_config(&rx_descr.dma, SS_DMA_CHANNEL_RX,
305307
fsp_tim_to_elc_event(rx_descr.tim.get_channel()), rx_descr.dmabuf[0],
306308
(void *) &rx_port->PCNTR2, config.nsamples, dma_rx_callback, this) != 0) {
@@ -359,17 +361,20 @@ size_t __attribute__((optimize("O2"))) SoftwareSerial::write(uint8_t byte)
359361
tx_descr.dmabuf[0][config.databits + 1] = parity;
360362
}
361363

362-
// Reconfigure DMA transfer.
363-
R_DMAC_Reconfigure(&tx_descr.dma.ctrl, tx_descr.dma.cfg.p_info);
364+
// Restart DMA transfer.
365+
R_DMAC_Reset(&tx_descr.dma.ctrl, tx_descr.dma.cfg.p_info->p_src,
366+
tx_descr.dma.cfg.p_info->p_dest, tx_descr.dma.cfg.p_info->length);
364367

365368
// Start the DMA transfer.
366369
tx_descr.tim.reset();
367370
tx_descr.tim.start();
368371

369-
// TODO check if transfer is running on next write.
372+
// Wait for the DMA transfer to finish.
370373
while (tx_descr.dma.ctrl.p_reg->DMCNT) {
371-
// Wait for DMA transfer to finish.
372374
}
375+
376+
// Stop the trigger timer.
377+
tx_descr.tim.stop();
373378
return 1;
374379
}
375380

@@ -382,9 +387,10 @@ void __attribute__((optimize("O2"))) SoftwareSerial::rx_process()
382387
{
383388
static uint32_t bufidx = 0;
384389

385-
// Reconfigure DMA transfer.
390+
// Restart DMA transfer.
386391
rx_descr.dma.cfg.p_info->p_dest = rx_descr.dmabuf[bufidx ^ 1];
387-
R_DMAC_Reconfigure(&rx_descr.dma.ctrl, rx_descr.dma.cfg.p_info);
392+
R_DMAC_Reset(&rx_descr.dma.ctrl, rx_descr.dma.cfg.p_info->p_src,
393+
rx_descr.dma.cfg.p_info->p_dest, rx_descr.dma.cfg.p_info->length);
388394

389395
// Process the current DMA buffer.
390396
uint8_t data = 0;
@@ -434,9 +440,12 @@ void __attribute__((optimize("O2"))) SoftwareSerial::rx_process()
434440

435441
void dma_tx_callback(dmac_callback_args_t *args)
436442
{
437-
// Disable the DMA trigger timer as soon as the transfer is complete.
438-
// Note the timer will be cleared and restarted on next write.
439-
((SoftwareSerial *) args->p_context)->tx_descr.tim.stop();
443+
// Wait for a while cycle to keep the GPIO high enough for the last stop bit.
444+
fsp_tim_t *tim = &(((SoftwareSerial *) args->p_context)->tx_descr.tim);
445+
volatile R_GPT0_Type *regs = R_GPT0 + (tim->get_channel() * (R_GPT1 - R_GPT0));
446+
regs->GTST_b.TCFPO = 0;
447+
while (!regs->GTST_b.TCFPO) {
448+
}
440449
}
441450

442451
void dma_rx_callback(dmac_callback_args_t *args)

0 commit comments

Comments
 (0)