Skip to content

Commit 293e8db

Browse files
committed
alif/mpuart: Enhance UART to support bits/parity/stop and more IRQs.
Signed-off-by: Damien George <[email protected]>
1 parent 19a4689 commit 293e8db

File tree

3 files changed

+92
-17
lines changed

3 files changed

+92
-17
lines changed

ports/alif/mpbthciport.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,20 @@ static ringbuf_t hci_rx_ringbuf = {
8989
.iput = 0,
9090
};
9191

92+
static void mp_bluetooth_hci_uart_irq_callback(unsigned int uart_id, unsigned int trigger) {
93+
if (trigger == MP_UART_IRQ_RXIDLE) {
94+
mp_bluetooth_hci_poll_now();
95+
}
96+
}
97+
9298
int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) {
9399
hci_uart_id = port;
94100
hci_uart_first_char = true;
95101

96102
// Initialise the UART.
97-
mp_uart_init(hci_uart_id, baudrate, pin_BT_UART_TX, pin_BT_UART_RX, &hci_rx_ringbuf);
103+
mp_uart_init(hci_uart_id, baudrate, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1, pin_BT_UART_TX, pin_BT_UART_RX, &hci_rx_ringbuf);
98104
mp_uart_set_flow(hci_uart_id, pin_BT_UART_RTS, pin_BT_UART_CTS);
99-
mp_uart_set_irq_callback(hci_uart_id, mp_bluetooth_hci_poll_now);
105+
mp_uart_set_irq_callback(hci_uart_id, MP_UART_IRQ_RXIDLE, mp_bluetooth_hci_uart_irq_callback);
100106

101107
// Start the HCI polling to process any initial events/packets.
102108
mp_bluetooth_hci_start_polling();

ports/alif/mpuart.c

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,28 @@
2626

2727
#include "py/mphal.h"
2828
#include "py/runtime.h"
29+
#include "shared/runtime/softtimer.h"
2930
#include "mpuart.h"
30-
3131
#include "sys_ctrl_uart.h"
32-
#include "uart.h"
3332

34-
#define UART_MAX (8)
33+
#define mp_container_of(ptr, structure, member) (void *)((uintptr_t)(ptr) - offsetof(structure, member))
34+
35+
#define UART_LSR_TEMT_Pos (6)
3536
#define SYST_PCLK (100000000)
3637

38+
#define CALCULATE_BITS_PER_CHAR(data_bits, parity, stop_bits) \
39+
(1 + ((data_bits) + 5) + ((parity) != UART_PARITY_NONE) + ((stop_bits) + 1))
40+
3741
typedef struct _uart_state_t {
3842
UART_TRANSFER_STATUS status;
43+
uint32_t baudrate;
44+
uint32_t bits_per_char;
3945
ringbuf_t *rx_ringbuf;
4046
const uint8_t *tx_src;
4147
const uint8_t *tx_src_max;
42-
void (*irq_callback)(void);
48+
soft_timer_entry_t rx_idle_timer;
49+
unsigned int irq_trigger;
50+
void (*irq_callback)(unsigned int uart_id, unsigned int trigger);
4351
} uart_state_t;
4452

4553
static const uint8_t uart_irqn[UART_MAX] = {
@@ -66,7 +74,19 @@ static UART_Type *const uart_periph[UART_MAX] = {
6674

6775
static uart_state_t uart_state[UART_MAX];
6876

69-
void mp_uart_init(unsigned int uart_id, uint32_t baudrate, mp_hal_pin_obj_t tx, mp_hal_pin_obj_t rx, ringbuf_t *rx_ringbuf) {
77+
// This is called by soft_timer and executes at IRQ_PRI_PENDSV.
78+
static void rx_idle_timer_callback(soft_timer_entry_t *self) {
79+
uart_state_t *state = mp_container_of(self, uart_state_t, rx_idle_timer);
80+
if (state->irq_callback != NULL && state->irq_trigger & MP_UART_IRQ_RXIDLE) {
81+
unsigned int uart_id = state - &uart_state[0];
82+
state->irq_callback(uart_id, MP_UART_IRQ_RXIDLE);
83+
}
84+
}
85+
86+
void mp_uart_init(unsigned int uart_id, uint32_t baudrate,
87+
UART_DATA_BITS data_bits, UART_PARITY parity, UART_STOP_BITS stop_bits,
88+
mp_hal_pin_obj_t tx, mp_hal_pin_obj_t rx, ringbuf_t *rx_ringbuf) {
89+
7090
UART_Type *uart = uart_periph[uart_id];
7191
uart_state_t *state = &uart_state[uart_id];
7292

@@ -82,24 +102,29 @@ void mp_uart_init(unsigned int uart_id, uint32_t baudrate, mp_hal_pin_obj_t tx,
82102
uart_disable_tx_irq(uart);
83103
uart_disable_rx_irq(uart);
84104
uart_set_baudrate(uart, SYST_PCLK, baudrate);
85-
uart_set_data_parity_stop_bits(uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
105+
uart_set_data_parity_stop_bits(uart, data_bits, parity, stop_bits);
86106
uart_set_flow_control(uart, UART_FLOW_CONTROL_NONE);
87107
uart->UART_FCR |= UART_FCR_RCVR_FIFO_RESET;
88108
uart_set_tx_trigger(uart, UART_TX_FIFO_EMPTY);
89-
uart_set_rx_trigger(uart, UART_RX_ONE_CHAR_IN_FIFO);
109+
uart_set_rx_trigger(uart, UART_RX_FIFO_QUARTER_FULL);
90110

91111
// Initialise the state.
92112
state->status = UART_TRANSFER_STATUS_NONE;
113+
state->baudrate = baudrate;
114+
state->bits_per_char = CALCULATE_BITS_PER_CHAR(data_bits, parity, stop_bits);
93115
state->rx_ringbuf = rx_ringbuf;
94116
state->tx_src = NULL;
95117
state->tx_src_max = NULL;
118+
state->irq_trigger = 0;
96119
state->irq_callback = NULL;
97120

98121
// Enable interrupts.
99122
NVIC_ClearPendingIRQ(uart_irqn[uart_id]);
100123
NVIC_SetPriority(uart_irqn[uart_id], IRQ_PRI_UART_REPL);
101124
NVIC_EnableIRQ(uart_irqn[uart_id]);
102125
uart_enable_rx_irq(uart);
126+
127+
soft_timer_static_init(&state->rx_idle_timer, SOFT_TIMER_MODE_ONE_SHOT, 0, rx_idle_timer_callback);
103128
}
104129

105130
void mp_uart_deinit(unsigned int uart_id) {
@@ -109,9 +134,16 @@ void mp_uart_deinit(unsigned int uart_id) {
109134
NVIC_DisableIRQ(uart_irqn[uart_id]);
110135
}
111136

112-
void mp_uart_set_irq_callback(unsigned int uart_id, void (*callback)(void)) {
137+
void mp_uart_set_irq_callback(unsigned int uart_id, unsigned int trigger, void (*callback)(unsigned int uart_id, unsigned int trigger)) {
138+
UART_Type *uart = uart_periph[uart_id];
113139
uart_state_t *state = &uart_state[uart_id];
140+
state->irq_trigger = trigger;
114141
state->irq_callback = callback;
142+
if (trigger & MP_UART_IRQ_RX) {
143+
uart_set_rx_trigger(uart, UART_RX_ONE_CHAR_IN_FIFO);
144+
} else {
145+
uart_set_rx_trigger(uart, UART_RX_FIFO_QUARTER_FULL);
146+
}
115147
}
116148

117149
void mp_uart_set_flow(unsigned int uart_id, mp_hal_pin_obj_t rts, mp_hal_pin_obj_t cts) {
@@ -131,10 +163,20 @@ void mp_uart_set_flow(unsigned int uart_id, mp_hal_pin_obj_t rts, mp_hal_pin_obj
131163

132164
void mp_uart_set_baudrate(unsigned int uart_id, uint32_t baudrate) {
133165
UART_Type *uart = uart_periph[uart_id];
166+
uart_state_t *state = &uart_state[uart_id];
134167

168+
state->baudrate = baudrate;
135169
uart_set_baudrate(uart, SYST_PCLK, baudrate);
136170
}
137171

172+
void mp_uart_set_bits_parity_stop(unsigned int uart_id, UART_DATA_BITS data_bits, UART_PARITY parity, UART_STOP_BITS stop_bits) {
173+
UART_Type *uart = uart_periph[uart_id];
174+
uart_state_t *state = &uart_state[uart_id];
175+
176+
state->bits_per_char = CALCULATE_BITS_PER_CHAR(data_bits, parity, stop_bits);
177+
uart_set_data_parity_stop_bits(uart, data_bits, parity, stop_bits);
178+
}
179+
138180
size_t mp_uart_rx_any(unsigned int uart_id) {
139181
uart_state_t *state = &uart_state[uart_id];
140182
if (state->rx_ringbuf != NULL) {
@@ -143,6 +185,11 @@ size_t mp_uart_rx_any(unsigned int uart_id) {
143185
return 0;
144186
}
145187

188+
size_t mp_uart_tx_any(unsigned int uart_id) {
189+
UART_Type *uart = uart_periph[uart_id];
190+
return uart->UART_TFL + !((uart->UART_LSR >> UART_LSR_TEMT_Pos) & 1);
191+
}
192+
146193
int mp_uart_rx_char(unsigned int uart_id) {
147194
uart_state_t *state = &uart_state[uart_id];
148195
if (state->rx_ringbuf != NULL && ringbuf_avail(state->rx_ringbuf)) {
@@ -208,9 +255,11 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
208255
}
209256

210257
case UART_IIR_RECEIVED_DATA_AVAILABLE:
211-
case UART_IIR_CHARACTER_TIMEOUT:
258+
case UART_IIR_CHARACTER_TIMEOUT: {
259+
bool had_char = false;
212260
while (uart->UART_USR & UART_USR_RECEIVE_FIFO_NOT_EMPTY) {
213261
for (uint32_t rfl = uart->UART_RFL; rfl; --rfl) {
262+
had_char = true;
214263
int c = uart->UART_RBR;
215264
#if MICROPY_HW_ENABLE_UART_REPL && MICROPY_KBD_EXCEPTION
216265
if (uart_id == MICROPY_HW_UART_REPL) {
@@ -226,13 +275,18 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
226275
}
227276
}
228277

229-
if (iir == UART_IIR_CHARACTER_TIMEOUT) {
230-
if (state->irq_callback != NULL) {
231-
state->irq_callback();
278+
if (had_char) {
279+
if (state->irq_callback != NULL && state->irq_trigger & MP_UART_IRQ_RX) {
280+
state->irq_callback(uart_id, MP_UART_IRQ_RX);
232281
}
233282
}
234283

284+
if (state->irq_trigger & MP_UART_IRQ_RXIDLE) {
285+
// Wait for 2 characters worth of time before triggering the RXIDLE event.
286+
soft_timer_reinsert(&state->rx_idle_timer, 2000 * state->bits_per_char / state->baudrate + 1);
287+
}
235288
break;
289+
}
236290

237291
case UART_IIR_TRANSMIT_HOLDING_REG_EMPTY:
238292
while (uart->UART_USR & UART_USR_TRANSMIT_FIFO_NOT_FULL) {
@@ -241,6 +295,9 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
241295
} else {
242296
uart_disable_tx_irq(uart);
243297
state->status = UART_TRANSFER_STATUS_SEND_COMPLETE;
298+
if (state->irq_callback != NULL && state->irq_trigger & MP_UART_IRQ_TXIDLE) {
299+
state->irq_callback(uart_id, MP_UART_IRQ_TXIDLE);
300+
}
244301
break;
245302
}
246303
}
@@ -273,7 +330,9 @@ DEFINE_IRQ_HANDLER(7)
273330
#define REPL_BAUDRATE (115200)
274331

275332
void mp_uart_init_repl(void) {
276-
mp_uart_init(MICROPY_HW_UART_REPL, REPL_BAUDRATE, pin_REPL_UART_TX, pin_REPL_UART_RX, &stdin_ringbuf);
333+
mp_uart_init(MICROPY_HW_UART_REPL,
334+
REPL_BAUDRATE, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1,
335+
pin_REPL_UART_TX, pin_REPL_UART_RX, &stdin_ringbuf);
277336
}
278337

279338
void mp_uart_write_strn_repl(const char *str, size_t len) {

ports/alif/mpuart.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,25 @@
2727
#define MICROPY_INCLUDED_ALIF2_UART_H
2828

2929
#include "py/ringbuf.h"
30+
#include "uart.h"
3031

31-
void mp_uart_init(unsigned int uart_id, uint32_t baudrate, mp_hal_pin_obj_t tx, mp_hal_pin_obj_t rx, ringbuf_t *rx_ringbuf);
32+
#define UART_MAX (8)
33+
#define MP_UART_IRQ_RX (1)
34+
#define MP_UART_IRQ_RXIDLE (2)
35+
#define MP_UART_IRQ_TXIDLE (4)
36+
37+
void mp_uart_init(unsigned int uart_id, uint32_t baudrate,
38+
UART_DATA_BITS data_bits, UART_PARITY parity, UART_STOP_BITS stop_bits,
39+
mp_hal_pin_obj_t tx, mp_hal_pin_obj_t rx, ringbuf_t *rx_ringbuf);
3240
void mp_uart_deinit(unsigned int uart_id);
3341

34-
void mp_uart_set_irq_callback(unsigned int uart_id, void (*callback)(void));
42+
void mp_uart_set_irq_callback(unsigned int uart_id, unsigned int trigger, void (*callback)(unsigned int uart_id, unsigned int trigger));
3543
void mp_uart_set_flow(unsigned int uart_id, mp_hal_pin_obj_t rts, mp_hal_pin_obj_t cts);
3644
void mp_uart_set_baudrate(unsigned int uart_id, uint32_t baudrate);
45+
void mp_uart_set_bits_parity_stop(unsigned int uart_id, UART_DATA_BITS data_bits, UART_PARITY parity, UART_STOP_BITS stop_bits);
3746

3847
size_t mp_uart_rx_any(unsigned int uart_id);
48+
size_t mp_uart_tx_any(unsigned int uart_id);
3949
int mp_uart_rx_char(unsigned int uart_id);
4050
void mp_uart_tx_data(unsigned int uart_id, const uint8_t *src, size_t len);
4151

0 commit comments

Comments
 (0)