Skip to content

Commit 6a64ffd

Browse files
committed
Added end() function to Soft Serial
the basic trick of this commit is to allow to call the new introduced end and again begin as much as wanted, avoiding to further consume indexes in the nvic interrupt table
1 parent f032b82 commit 6a64ffd

File tree

4 files changed

+81
-30
lines changed

4 files changed

+81
-30
lines changed

cores/arduino/FspLinkIrq.h

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef enum {
1616

1717
extern int attachIrq2Link(uint32_t pin, PinStatus mode);
1818
extern int detachIrq2Link(pin_size_t pinNumber);
19+
extern int getIrqIndexFromPint(uint32_t pin);
1920

2021
/* Wrapper class for FSP ELC
2122
at the present only support the link of an external Irq to a peripheral */

cores/arduino/Interrupts.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,21 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr func, PinStatus mode) {
193193
attachInterruptParam(pinNumber, (voidFuncPtrParam)func, mode, NULL);
194194
}
195195

196+
197+
int getIrqIndexFromPint(uint32_t pinNumber) {
198+
CIrq *irq_context = nullptr;
199+
int rv = -1;
200+
int ch = pin2IrqChannel(pinNumber);
201+
if(ch >= 0 && ch < MAX_IRQ_CHANNEL) {
202+
irq_context = IrqChannel.get(ch,false);
203+
if(irq_context != nullptr) {
204+
rv = irq_context->cfg.irq;
205+
}
206+
}
207+
return rv;
208+
}
209+
210+
196211
int attachIrq2Link(uint32_t pinNumber, PinStatus mode) {
197212
CIrq *irq_context = nullptr;
198213
int ch = pin2IrqChannel(pinNumber);

libraries/SoftwareSerial/src/SoftwareSerial.cpp

+63-30
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void dma_tx_callback(dmac_callback_args_t *args);
4848
void dma_rx_callback(dmac_callback_args_t *args);
4949

5050
extern int attachIrq2Link(uint32_t pin, PinStatus mode);
51+
extern int getIrqIndexFromPint(uint32_t pin);
5152
typedef void (*fsp_dma_callback_t) (dmac_callback_args_t *args);
5253

5354
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):
192193
assert(rx_pin < NUM_DIGITAL_PINS);
193194
_tx_pin = tx_pin;
194195
_rx_pin = rx_pin;
196+
initialized = false;
195197
}
196198

197199
SoftwareSerial::~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 = 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);
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,9 +337,29 @@ 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;
327342
return 1;
328343
}
329344

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+
330363
int SoftwareSerial::read()
331364
{
332365
int chr = -1;

libraries/SoftwareSerial/src/SoftwareSerial.h

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class SoftwareSerial : public Stream, public arduino::Printable {
7070
ss_descr_t<2> rx_descr;
7171
uint8_t _tx_pin, _rx_pin;
7272
void rx_process();
73+
bool initialized;
7374

7475
public:
7576
using Print::write;
@@ -83,6 +84,7 @@ class SoftwareSerial : public Stream, public arduino::Printable {
8384
int peek();
8485
virtual size_t write(uint8_t byte);
8586
virtual int available();
87+
virtual int end();
8688
};
8789

8890
#endif //__SOFTWARE_SERIAL_H__

0 commit comments

Comments
 (0)