From 23109988c29447067b15f1943f72c0b486819c6c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 14 Aug 2020 15:21:23 +1000 Subject: [PATCH] stm32/uart: Allow static IRQ handler registration. This will allow the HCI UART to use a non-heap mp_irq_obj_t, which avoids needing to make a root pointer for it. --- lib/utils/mpirq.h | 2 +- ports/stm32/machine_uart.c | 78 ++------------------------------------ ports/stm32/uart.c | 62 ++++++++++++++++++++++++++++++ ports/stm32/uart.h | 12 +++++- 4 files changed, 77 insertions(+), 77 deletions(-) diff --git a/lib/utils/mpirq.h b/lib/utils/mpirq.h index 186c9e1b0b..dd423c0101 100644 --- a/lib/utils/mpirq.h +++ b/lib/utils/mpirq.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H #define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H -#include "py/obj.h" +#include "py/runtime.h" /****************************************************************************** DEFINE CONSTANTS diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 631f46e81f..2862f4c0e7 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -73,76 +73,6 @@ /// /// uart.any() # returns True if any characters waiting -typedef struct _pyb_uart_irq_map_t { - uint16_t irq_en; - uint16_t flag; -} pyb_uart_irq_map_t; - -STATIC const pyb_uart_irq_map_t mp_irq_map[] = { - { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle - { USART_CR1_PEIE, UART_FLAG_PE}, // parity error - { USART_CR1_TXEIE, UART_FLAG_TXE}, // TX register empty - { USART_CR1_TCIE, UART_FLAG_TC}, // TX complete - { USART_CR1_RXNEIE, UART_FLAG_RXNE}, // RX register not empty - #if 0 - // For now only IRQs selected by CR1 are supported - #if defined(STM32F4) - { USART_CR2_LBDIE, UART_FLAG_LBD}, // LIN break detection - #else - { USART_CR2_LBDIE, UART_FLAG_LBDF}, // LIN break detection - #endif - { USART_CR3_CTSIE, UART_FLAG_CTS}, // CTS - #endif -}; - -// OR-ed IRQ flags which should not be touched by the user -STATIC const uint32_t mp_irq_reserved = UART_FLAG_RXNE; - -// OR-ed IRQ flags which are allowed to be used by the user -STATIC const uint32_t mp_irq_allowed = UART_FLAG_IDLE; - -STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - -STATIC void pyb_uart_irq_config(pyb_uart_obj_t *self, bool enable) { - if (self->mp_irq_trigger) { - for (size_t entry = 0; entry < MP_ARRAY_SIZE(mp_irq_map); ++entry) { - if (mp_irq_map[entry].flag & mp_irq_reserved) { - continue; - } - if (mp_irq_map[entry].flag & self->mp_irq_trigger) { - if (enable) { - self->uartx->CR1 |= mp_irq_map[entry].irq_en; - } else { - self->uartx->CR1 &= ~mp_irq_map[entry].irq_en; - } - } - } - } -} - -STATIC mp_uint_t pyb_uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - pyb_uart_irq_config(self, false); - self->mp_irq_trigger = new_trigger; - pyb_uart_irq_config(self, true); - return 0; -} - -STATIC mp_uint_t pyb_uart_irq_info(mp_obj_t self_in, mp_uint_t info_type) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (info_type == MP_IRQ_INFO_FLAGS) { - return self->mp_irq_flags; - } else if (info_type == MP_IRQ_INFO_TRIGGERS) { - return self->mp_irq_trigger; - } - return 0; -} - -STATIC const mp_irq_methods_t pyb_uart_irq_methods = { - .trigger = pyb_uart_irq_trigger, - .info = pyb_uart_irq_info, -}; - STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { @@ -518,7 +448,7 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t * if (self->mp_irq_obj == NULL) { self->mp_irq_trigger = 0; - self->mp_irq_obj = mp_irq_new(&pyb_uart_irq_methods, MP_OBJ_FROM_PTR(self)); + self->mp_irq_obj = mp_irq_new(&uart_irq_methods, MP_OBJ_FROM_PTR(self)); } if (n_args > 1 || kw_args->used != 0) { @@ -530,17 +460,17 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // Check the trigger mp_uint_t trigger = args[MP_IRQ_ARG_INIT_trigger].u_int; - mp_uint_t not_supported = trigger & ~mp_irq_allowed; + mp_uint_t not_supported = trigger & ~MP_UART_ALLOWED_FLAGS; if (trigger != 0 && not_supported) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("trigger 0x%08x unsupported"), not_supported); } // Reconfigure user IRQs - pyb_uart_irq_config(self, false); + uart_irq_config(self, false); self->mp_irq_obj->handler = handler; self->mp_irq_obj->ishard = args[MP_IRQ_ARG_INIT_hard].u_bool; self->mp_irq_trigger = trigger; - pyb_uart_irq_config(self, true); + uart_irq_config(self, true); } return MP_OBJ_FROM_PTR(self->mp_irq_obj); diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 8693813fa4..b14a18c6dd 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -93,6 +93,28 @@ extern void NORETURN __fatal_error(const char *msg); +typedef struct _pyb_uart_irq_map_t { + uint16_t irq_en; + uint16_t flag; +} pyb_uart_irq_map_t; + +STATIC const pyb_uart_irq_map_t mp_uart_irq_map[] = { + { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle + { USART_CR1_PEIE, UART_FLAG_PE}, // parity error + { USART_CR1_TXEIE, UART_FLAG_TXE}, // TX register empty + { USART_CR1_TCIE, UART_FLAG_TC}, // TX complete + { USART_CR1_RXNEIE, UART_FLAG_RXNE}, // RX register not empty + #if 0 + // For now only IRQs selected by CR1 are supported + #if defined(STM32F4) + { USART_CR2_LBDIE, UART_FLAG_LBD}, // LIN break detection + #else + { USART_CR2_LBDIE, UART_FLAG_LBDF}, // LIN break detection + #endif + { USART_CR3_CTSIE, UART_FLAG_CTS}, // CTS + #endif +}; + void uart_init0(void) { #if defined(STM32H7) RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; @@ -444,6 +466,23 @@ bool uart_init(pyb_uart_obj_t *uart_obj, return true; } +void uart_irq_config(pyb_uart_obj_t *self, bool enable) { + if (self->mp_irq_trigger) { + for (size_t entry = 0; entry < MP_ARRAY_SIZE(mp_uart_irq_map); ++entry) { + if (mp_uart_irq_map[entry].flag & MP_UART_RESERVED_FLAGS) { + continue; + } + if (mp_uart_irq_map[entry].flag & self->mp_irq_trigger) { + if (enable) { + self->uartx->CR1 |= mp_uart_irq_map[entry].irq_en; + } else { + self->uartx->CR1 &= ~mp_uart_irq_map[entry].irq_en; + } + } + } + } +} + void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) { self->read_buf_head = 0; self->read_buf_tail = 0; @@ -864,3 +903,26 @@ void uart_irq_handler(mp_uint_t uart_id) { mp_irq_handler(self->mp_irq_obj); } } + +STATIC mp_uint_t uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + uart_irq_config(self, false); + self->mp_irq_trigger = new_trigger; + uart_irq_config(self, true); + return 0; +} + +STATIC mp_uint_t uart_irq_info(mp_obj_t self_in, mp_uint_t info_type) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (info_type == MP_IRQ_INFO_FLAGS) { + return self->mp_irq_flags; + } else if (info_type == MP_IRQ_INFO_TRIGGERS) { + return self->mp_irq_trigger; + } + return 0; +} + +const mp_irq_methods_t uart_irq_methods = { + .trigger = uart_irq_trigger, + .info = uart_irq_info, +}; diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 62676fb91b..9a38db593d 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_STM32_UART_H #define MICROPY_INCLUDED_STM32_UART_H -struct _mp_irq_obj_t; +#include "lib/utils/mpirq.h" typedef enum { PYB_UART_NONE = 0, @@ -45,6 +45,12 @@ typedef enum { #define CHAR_WIDTH_8BIT (0) #define CHAR_WIDTH_9BIT (1) +// OR-ed IRQ flags which are allowed to be used by the user +#define MP_UART_ALLOWED_FLAGS UART_FLAG_IDLE + +// OR-ed IRQ flags which should not be touched by the user +#define MP_UART_RESERVED_FLAGS UART_FLAG_RXNE + typedef struct _pyb_uart_obj_t { mp_obj_base_t base; USART_TypeDef *uartx; @@ -62,16 +68,18 @@ typedef struct _pyb_uart_obj_t { byte *read_buf; // byte or uint16_t, depending on char size uint16_t mp_irq_trigger; // user IRQ trigger mask uint16_t mp_irq_flags; // user IRQ active IRQ flags - struct _mp_irq_obj_t *mp_irq_obj; // user IRQ object + mp_irq_obj_t *mp_irq_obj; // user IRQ object } pyb_uart_obj_t; extern const mp_obj_type_t pyb_uart_type; +extern const mp_irq_methods_t uart_irq_methods; void uart_init0(void); void uart_deinit_all(void); bool uart_exists(int uart_id); bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow); +void uart_irq_config(pyb_uart_obj_t *self, bool enable); void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf); void uart_deinit(pyb_uart_obj_t *uart_obj); void uart_irq_handler(mp_uint_t uart_id);