Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cores/arduino/FspLinkIrq.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum {

extern int attachIrq2Link(uint32_t pin, PinStatus mode);
extern int detachIrq2Link(pin_size_t pinNumber);
extern int getIrqIndexFromPint(uint32_t pin);
Copy link

Copilot AI Apr 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name 'getIrqIndexFromPint' appears to contain a typo; it may be intended to be 'getIrqIndexFromPin'.

Suggested change
extern int getIrqIndexFromPint(uint32_t pin);
extern int getIrqIndexFromPin(uint32_t pin);

Copilot uses AI. Check for mistakes.

/* Wrapper class for FSP ELC
at the present only support the link of an external Irq to a peripheral */
Expand Down
15 changes: 15 additions & 0 deletions cores/arduino/Interrupts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr func, PinStatus mode) {
attachInterruptParam(pinNumber, (voidFuncPtrParam)func, mode, NULL);
}


int getIrqIndexFromPint(uint32_t pinNumber) {
CIrq *irq_context = nullptr;
int rv = -1;
int ch = pin2IrqChannel(pinNumber);
if(ch >= 0 && ch < MAX_IRQ_CHANNEL) {
irq_context = IrqChannel.get(ch,false);
if(irq_context != nullptr) {
rv = irq_context->cfg.irq;
}
}
return rv;
}


int attachIrq2Link(uint32_t pinNumber, PinStatus mode) {
CIrq *irq_context = nullptr;
int ch = pin2IrqChannel(pinNumber);
Expand Down
93 changes: 63 additions & 30 deletions libraries/SoftwareSerial/src/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void dma_tx_callback(dmac_callback_args_t *args);
void dma_rx_callback(dmac_callback_args_t *args);

extern int attachIrq2Link(uint32_t pin, PinStatus mode);
extern int getIrqIndexFromPint(uint32_t pin);
typedef void (*fsp_dma_callback_t) (dmac_callback_args_t *args);

static uint32_t tx_get_sample(bsp_io_port_pin_t tx, ioport_size_t value)
Expand Down Expand Up @@ -192,6 +193,7 @@ SoftwareSerial::SoftwareSerial(uint8_t rx_pin, uint8_t tx_pin, size_t bufsize):
assert(rx_pin < NUM_DIGITAL_PINS);
_tx_pin = tx_pin;
_rx_pin = rx_pin;
initialized = false;
}

SoftwareSerial::~SoftwareSerial()
Expand Down Expand Up @@ -228,17 +230,26 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_HIGH);
#endif

/* TX pin configuration */

R_IOPORT_PinCfg(&g_ioport_ctrl, tx_descr.pin, IOPORT_CFG_PORT_DIRECTION_OUTPUT
| IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_PORT_OUTPUT_HIGH);

// Enable RX pin IRQ.
rx_descr.irq_chan = attachIrq2Link(_rx_pin, CHANGE);
if (rx_descr.irq_chan != -1) {
// TODO: workaround for the core not setting pull-ups.
R_IOPORT_PinCfg(&g_ioport_ctrl, rx_descr.pin, IOPORT_CFG_PORT_DIRECTION_INPUT
| IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_IRQ_ENABLE);
/* RX pin configuration */

/* avoid to call attachIrq2Link if already used because it "consumes" irq
indexes in the NVIC */
int irq_index = getIrqIndexFromPint(_rx_pin);
if(irq_index == -1) {
rx_descr.irq_chan = attachIrq2Link(_rx_pin, CHANGE); // Enable RX pin IRQ.
} else {
R_BSP_IrqEnable ((IRQn_Type)irq_index);
}

R_IOPORT_PinCfg(&g_ioport_ctrl, rx_descr.pin, IOPORT_CFG_PORT_DIRECTION_INPUT
| IOPORT_CFG_PULLUP_ENABLE | IOPORT_CFG_IRQ_ENABLE);


// Set serial configuration.
config.bitshift = (rx_descr.pin & 0xFF);
config.polarity = (inverted) ? 1 : 0;
Expand Down Expand Up @@ -279,34 +290,36 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
// be calculated, and the start/stop samples can be prepopulated in the DMA TX buffer.
config.nsamples = (1 + config.databits + (!!config.parity) + config.stopbits);

// Prepopulate start and stop bits samples.
tx_descr.dmabuf[0][0] = tx_get_sample(tx_descr.pin, 0);
for (size_t i=0; i<config.stopbits; i++) {
tx_descr.dmabuf[0][config.nsamples-1-i] = tx_get_sample(tx_descr.pin, 1);
}
if(!initialized) {
// Prepopulate start and stop bits samples.
tx_descr.dmabuf[0][0] = tx_get_sample(tx_descr.pin, 0);
for (size_t i=0; i<config.stopbits; i++) {
tx_descr.dmabuf[0][config.nsamples-1-i] = tx_get_sample(tx_descr.pin, 1);
}

// Configure the TX DMA and its tigger timer.
R_PORT0_Type *tx_port = SS_PORT_ADDR(((tx_descr.pin >> 8) & 0xFF));
if (fsp_tim_config(&tx_descr.tim, config.baudrate, false) != 0) {
return 0;
}
// Configure the TX DMA and its tigger timer.
R_PORT0_Type *tx_port = SS_PORT_ADDR(((tx_descr.pin >> 8) & 0xFF));
if (fsp_tim_config(&tx_descr.tim, config.baudrate, false) != 0) {
return 0;
}

if (fsp_dma_config(&tx_descr.dma, SS_DMA_CHANNEL_TX,
fsp_tim_to_elc_event(tx_descr.tim.get_channel()), tx_descr.dmabuf[0],
(void *) &tx_port->PCNTR3, config.nsamples, dma_tx_callback, this) != 0) {
return 0;
}
if (fsp_dma_config(&tx_descr.dma, SS_DMA_CHANNEL_TX,
fsp_tim_to_elc_event(tx_descr.tim.get_channel()), tx_descr.dmabuf[0],
(void *) &tx_port->PCNTR3, config.nsamples, dma_tx_callback, this) != 0) {
return 0;
}

// Configure the RX DMA and its trigger timer.
R_PORT0_Type *rx_port = SS_PORT_ADDR(((rx_descr.pin >> 8) & 0xFF));
if (fsp_tim_config(&rx_descr.tim, config.baudrate, true) != 0) {
return 0;
}
// Configure the RX DMA and its trigger timer.
R_PORT0_Type *rx_port = SS_PORT_ADDR(((rx_descr.pin >> 8) & 0xFF));
if (fsp_tim_config(&rx_descr.tim, config.baudrate, true) != 0) {
return 0;
}

if (fsp_dma_config(&rx_descr.dma, SS_DMA_CHANNEL_RX,
fsp_tim_to_elc_event(rx_descr.tim.get_channel()), rx_descr.dmabuf[0],
(void *) &rx_port->PCNTR2, config.nsamples, dma_rx_callback, this) != 0) {
return 0;
if (fsp_dma_config(&rx_descr.dma, SS_DMA_CHANNEL_RX,
fsp_tim_to_elc_event(rx_descr.tim.get_channel()), rx_descr.dmabuf[0],
(void *) &rx_port->PCNTR2, config.nsamples, dma_rx_callback, this) != 0) {
return 0;
}
}

// Configure and enable the ELC.
Expand All @@ -324,9 +337,29 @@ int SoftwareSerial::begin(uint32_t baudrate, uint32_t sconfig, bool inverted)
tx_descr.pin, rx_descr.pin, config.bitshift, (config.polarity) ? "Inverted" : "Normal",
config.nsamples, config.baudrate, config.databits, parity_tostr[config.parity], config.stopbits);
#endif

initialized = true;
return 1;
}

int SoftwareSerial::end() {
int irq_index = getIrqIndexFromPint(_rx_pin);

if(irq_index != -1) {
R_BSP_IrqDisable((IRQn_Type)irq_index);
R_BSP_IrqStatusClear((IRQn_Type)irq_index);
}

if(initialized) {
// put rx and tx pin as input
R_IOPORT_PinCfg(&g_ioport_ctrl, tx_descr.pin, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinCfg(&g_ioport_ctrl, rx_descr.pin, IOPORT_CFG_PORT_DIRECTION_INPUT);

R_ELC_Disable(&elc_ctrl);
R_ELC_Close(&elc_ctrl);
}
}

int SoftwareSerial::read()
{
int chr = -1;
Expand Down
2 changes: 2 additions & 0 deletions libraries/SoftwareSerial/src/SoftwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class SoftwareSerial : public Stream, public arduino::Printable {
ss_descr_t<2> rx_descr;
uint8_t _tx_pin, _rx_pin;
void rx_process();
bool initialized;

public:
using Print::write;
Expand All @@ -83,6 +84,7 @@ class SoftwareSerial : public Stream, public arduino::Printable {
int peek();
virtual size_t write(uint8_t byte);
virtual int available();
virtual int end();
};

#endif //__SOFTWARE_SERIAL_H__
Loading