Skip to content

Commit ce04432

Browse files
Fix implementation of Tx IRQ for serial ports. BufferedSerial works now!
1 parent 3c44ef5 commit ce04432

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

hal/include/hal/serial_api.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,10 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
255255
/** The serial interrupt handler registration
256256
*
257257
* @param obj The serial object
258-
* @param handler The interrupt handler which will be invoked when the interrupt fires
259-
* @param id The SerialBase object
258+
* @param handler The interrupt handler function which will be invoked when the interrupt fires. The handler
259+
* function pointer must be common among all serial instances.
260+
* @param id The SerialBase object. This shall be passed to \c handler when it's
261+
* invoked for this serial instance.
260262
*/
261263
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id);
262264

targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ extern "C" {
5151

5252
#include "cmsis.h"
5353

54+
#include <stdbool.h>
55+
5456
#include "PortNames.h"
5557
#include "PeripheralNames.h"
5658
#include "PinNames.h"
@@ -91,6 +93,10 @@ struct serial_s {
9193
PinName pin_rts;
9294
PinName pin_cts;
9395
uint32_t baud;
96+
97+
// Current states of the IRQ enables for Tx and Rx
98+
bool txIrqEnabled;
99+
bool rxIrqEnabled;
94100
};
95101

96102
struct i2c_s {

targets/TARGET_RASPBERRYPI/TARGET_RP2040/serial_api.c

+31-10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ extern "C" {
3030
int stdio_uart_inited = 0;
3131
serial_t stdio_uart;
3232

33+
static inline void uart0_irq(void);
34+
static inline void uart1_irq(void);
35+
3336
void serial_init(serial_t *obj, PinName tx, PinName rx)
3437
{
3538
if (tx == STDIO_UART_TX && stdio_uart_inited != 0) {
@@ -62,8 +65,15 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
6265
//uart_set_translate_crlf(obj->dev, false);
6366
uart_set_fifo_enabled(obj->dev, false);
6467

68+
// Prepare interrupt. Note that we set it to enabled here, but the interrupt
69+
// won't fire yet because we haven't enabled any interrupt sources.
70+
int UART_IRQ = obj->dev == uart0 ? UART0_IRQ : UART1_IRQ;
71+
irq_set_exclusive_handler(UART_IRQ, obj->dev == uart0 ? uart0_irq : uart1_irq);
72+
irq_clear(UART_IRQ);
73+
irq_set_enabled(UART_IRQ, true);
74+
6575
if (tx == STDIO_UART_TX) {
66-
memmove(&stdio_uart, obj, sizeof(serial_t));
76+
memcpy(&stdio_uart, obj, sizeof(serial_t));
6777
stdio_uart_inited = 1;
6878
}
6979
}
@@ -102,14 +112,23 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
102112
static volatile uart_irq_handler irq_handler;
103113
static volatile uint32_t serial_irq_ids[2] = {0};
104114

105-
static inline void uart0_irq(void)
106-
{
107-
irq_handler(serial_irq_ids[0], RxIrq);
115+
static inline void uart0_irq(void) {
116+
if(uart_is_writable(uart0)) {
117+
irq_handler(serial_irq_ids[0], TxIrq);
118+
}
119+
if(uart_is_readable(uart0)) {
120+
irq_handler(serial_irq_ids[0], RxIrq);
121+
}
108122
}
109123

110124
static inline void uart1_irq(void)
111125
{
112-
irq_handler(serial_irq_ids[1], RxIrq);
126+
if(uart_is_writable(uart1)) {
127+
irq_handler(serial_irq_ids[1], TxIrq);
128+
}
129+
if(uart_is_readable(uart1)) {
130+
irq_handler(serial_irq_ids[1], RxIrq);
131+
}
113132
}
114133

115134
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
@@ -124,12 +143,14 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
124143

125144
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
126145
{
127-
int UART_IRQ = obj->dev == uart0 ? UART0_IRQ : UART1_IRQ;
128-
129-
irq_set_exclusive_handler(UART_IRQ, obj->dev == uart0 ? uart0_irq : uart1_irq);
130-
irq_set_enabled(UART_IRQ, enable);
146+
if(irq == RxIrq) {
147+
obj->rxIrqEnabled = enable;
148+
}
149+
else if(irq == TxIrq) {
150+
obj->txIrqEnabled = enable;
151+
}
131152

132-
uart_set_irq_enables(obj->dev, irq == RxIrq, irq == TxIrq);
153+
uart_set_irq_enables(obj->dev, obj->rxIrqEnabled, obj->txIrqEnabled);
133154
}
134155

135156
int serial_getc(serial_t *obj)

0 commit comments

Comments
 (0)