stm32/uart: Remove HAL's UART_HandleTypeDef from UART object struct.

This UART_HandleTypeDef is quite large (around 70 bytes in RAM needed for
each UART object) and is not needed: instead the state of the peripheral
held in its registers provides all the required information.
pull/4343/head
Damien George 2018-12-10 10:44:52 +11:00
rodzic 7d7f59d78b
commit bc3f0dddac
3 zmienionych plików z 105 dodań i 65 usunięć

Wyświetl plik

@ -78,37 +78,48 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
mp_printf(print, "UART(%u)", self->uart_id);
} else {
mp_int_t bits;
switch (self->uart.Init.WordLength) {
#ifdef UART_WORDLENGTH_7B
case UART_WORDLENGTH_7B: bits = 7; break;
#endif
case UART_WORDLENGTH_8B: bits = 8; break;
case UART_WORDLENGTH_9B: default: bits = 9; break;
uint32_t cr1 = self->uartx->CR1;
#if defined(UART_CR1_M1)
if (cr1 & UART_CR1_M1) {
bits = 7;
} else if (cr1 & UART_CR1_M0) {
bits = 9;
} else {
bits = 8;
}
if (self->uart.Init.Parity != UART_PARITY_NONE) {
#else
if (cr1 & USART_CR1_M) {
bits = 9;
} else {
bits = 8;
}
#endif
if (cr1 & USART_CR1_PCE) {
bits -= 1;
}
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=",
self->uart_id, self->uart.Init.BaudRate, bits);
if (self->uart.Init.Parity == UART_PARITY_NONE) {
self->uart_id, uart_get_baudrate(self), bits);
if (!(cr1 & USART_CR1_PCE)) {
mp_print_str(print, "None");
} else if (self->uart.Init.Parity == UART_PARITY_EVEN) {
} else if (!(cr1 & USART_CR1_PS)) {
mp_print_str(print, "0");
} else {
mp_print_str(print, "1");
}
uint32_t cr2 = self->uartx->CR2;
mp_printf(print, ", stop=%u, flow=",
self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2);
if (self->uart.Init.HwFlowCtl == UART_HWCONTROL_NONE) {
((cr2 >> USART_CR2_STOP_Pos) & 3) == 0 ? 1 : 2);
uint32_t cr3 = self->uartx->CR3;
if (!(cr3 & (USART_CR3_CTSE | USART_CR3_RTSE))) {
mp_print_str(print, "0");
} else {
if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
if (cr3 & USART_CR3_RTSE) {
mp_print_str(print, "RTS");
if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (cr3 & USART_CR3_CTSE) {
mp_print_str(print, "|");
}
}
if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (cr3 & USART_CR3_CTSE) {
mp_print_str(print, "CTS");
}
}
@ -151,8 +162,9 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
// set the UART configuration values
memset(&self->uart, 0, sizeof(self->uart));
UART_InitTypeDef *init = &self->uart.Init;
UART_InitTypeDef init_struct;
memset(&init_struct, 0, sizeof(init_struct));
UART_InitTypeDef *init = &init_struct;
// baudrate
init->BaudRate = args.baudrate.u_int;
@ -194,7 +206,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const
init->OverSampling = UART_OVERSAMPLING_16;
// init UART (if it fails, it's because the port doesn't exist)
if (!uart_init2(self)) {
if (!uart_init2(self, init)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) doesn't exist", self->uart_id));
}
@ -247,8 +259,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const
} else {
baudrate_diff = init->BaudRate - actual_baudrate;
}
init->BaudRate = actual_baudrate; // remember actual baudrate for printing
if (20 * baudrate_diff > init->BaudRate) {
if (20 * baudrate_diff > actual_baudrate) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "set baudrate %d is not within 5%% of desired value", actual_baudrate));
}
@ -408,9 +419,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7)
self->uart.Instance->RQR = USART_RQR_SBKRQ; // write-only register
self->uartx->RQR = USART_RQR_SBKRQ; // write-only register
#else
self->uart.Instance->CR1 |= USART_CR1_SBK;
self->uartx->CR1 |= USART_CR1_SBK;
#endif
return mp_const_none;
}
@ -521,7 +532,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t a
if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self)) {
ret |= MP_STREAM_POLL_RD;
}
if ((flags & MP_STREAM_POLL_WR) && __HAL_UART_GET_FLAG(&self->uart, UART_FLAG_TXE)) {
if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) {
ret |= MP_STREAM_POLL_WR;
}
} else {

Wyświetl plik

@ -37,6 +37,14 @@
#include "irq.h"
#include "pendsv.h"
#if defined(STM32F4)
#define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE)
#else
#define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE)
#endif
#define UART_RXNE_IT_EN(uart) do { (uart)->CR1 |= USART_CR1_RXNEIE; } while (0)
#define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE; } while (0)
extern void NORETURN __fatal_error(const char *msg);
void uart_init0(void) {
@ -115,7 +123,7 @@ bool uart_exists(int uart_id) {
}
// assumes Init parameters have been set up correctly
bool uart_init2(pyb_uart_obj_t *uart_obj) {
bool uart_init2(pyb_uart_obj_t *uart_obj, UART_InitTypeDef *init) {
USART_TypeDef *UARTx;
IRQn_Type irqn;
int uart_unit;
@ -142,12 +150,12 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
pins[0] = MICROPY_HW_UART2_TX;
pins[1] = MICROPY_HW_UART2_RX;
#if defined(MICROPY_HW_UART2_RTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
if (init->HwFlowCtl & UART_HWCONTROL_RTS) {
pins[2] = MICROPY_HW_UART2_RTS;
}
#endif
#if defined(MICROPY_HW_UART2_CTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (init->HwFlowCtl & UART_HWCONTROL_CTS) {
pins[3] = MICROPY_HW_UART2_CTS;
}
#endif
@ -167,12 +175,12 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
pins[0] = MICROPY_HW_UART3_TX;
pins[1] = MICROPY_HW_UART3_RX;
#if defined(MICROPY_HW_UART3_RTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
if (init->HwFlowCtl & UART_HWCONTROL_RTS) {
pins[2] = MICROPY_HW_UART3_RTS;
}
#endif
#if defined(MICROPY_HW_UART3_CTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (init->HwFlowCtl & UART_HWCONTROL_CTS) {
pins[3] = MICROPY_HW_UART3_CTS;
}
#endif
@ -226,12 +234,12 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
pins[0] = MICROPY_HW_UART6_TX;
pins[1] = MICROPY_HW_UART6_RX;
#if defined(MICROPY_HW_UART6_RTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
if (init->HwFlowCtl & UART_HWCONTROL_RTS) {
pins[2] = MICROPY_HW_UART6_RTS;
}
#endif
#if defined(MICROPY_HW_UART6_CTS)
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (init->HwFlowCtl & UART_HWCONTROL_CTS) {
pins[3] = MICROPY_HW_UART6_CTS;
}
#endif
@ -291,10 +299,14 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
}
uart_obj->irqn = irqn;
uart_obj->uart.Instance = UARTx;
uart_obj->uartx = UARTx;
// init UARTx
HAL_UART_Init(&uart_obj->uart);
UART_HandleTypeDef huart;
memset(&huart, 0, sizeof(huart));
huart.Instance = UARTx;
huart.Init = *init;
HAL_UART_Init(&huart);
uart_obj->is_enabled = true;
uart_obj->attached_to_repl = false;
@ -309,9 +321,9 @@ void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) {
self->read_buf = buf;
if (len == 0) {
HAL_NVIC_DisableIRQ(self->irqn);
__HAL_UART_DISABLE_IT(&self->uart, UART_IT_RXNE);
UART_RXNE_IT_DIS(self->uartx);
} else {
__HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE);
UART_RXNE_IT_EN(self->uartx);
NVIC_SetPriority(IRQn_NONNEG(self->irqn), IRQ_PRI_UART);
HAL_NVIC_EnableIRQ(self->irqn);
}
@ -319,20 +331,23 @@ void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) {
void uart_deinit(pyb_uart_obj_t *self) {
self->is_enabled = false;
UART_HandleTypeDef *uart = &self->uart;
HAL_UART_DeInit(uart);
if (uart->Instance == USART1) {
UART_HandleTypeDef huart;
huart.Instance = self->uartx;
HAL_UART_DeInit(&huart);
if (self->uart_id == 1) {
HAL_NVIC_DisableIRQ(USART1_IRQn);
__HAL_RCC_USART1_FORCE_RESET();
__HAL_RCC_USART1_RELEASE_RESET();
__HAL_RCC_USART1_CLK_DISABLE();
} else if (uart->Instance == USART2) {
} else if (self->uart_id == 2) {
HAL_NVIC_DisableIRQ(USART2_IRQn);
__HAL_RCC_USART2_FORCE_RESET();
__HAL_RCC_USART2_RELEASE_RESET();
__HAL_RCC_USART2_CLK_DISABLE();
#if defined(USART3)
} else if (uart->Instance == USART3) {
} else if (self->uart_id == 3) {
#if !defined(STM32F0)
HAL_NVIC_DisableIRQ(USART3_IRQn);
#endif
@ -341,60 +356,60 @@ void uart_deinit(pyb_uart_obj_t *self) {
__HAL_RCC_USART3_CLK_DISABLE();
#endif
#if defined(UART4)
} else if (uart->Instance == UART4) {
} else if (self->uart_id == 4) {
HAL_NVIC_DisableIRQ(UART4_IRQn);
__HAL_RCC_UART4_FORCE_RESET();
__HAL_RCC_UART4_RELEASE_RESET();
__HAL_RCC_UART4_CLK_DISABLE();
#endif
#if defined(USART4)
} else if (uart->Instance == USART4) {
} else if (self->uart_id == 4) {
__HAL_RCC_USART4_FORCE_RESET();
__HAL_RCC_USART4_RELEASE_RESET();
__HAL_RCC_USART4_CLK_DISABLE();
#endif
#if defined(UART5)
} else if (uart->Instance == UART5) {
} else if (self->uart_id == 5) {
HAL_NVIC_DisableIRQ(UART5_IRQn);
__HAL_RCC_UART5_FORCE_RESET();
__HAL_RCC_UART5_RELEASE_RESET();
__HAL_RCC_UART5_CLK_DISABLE();
#endif
#if defined(USART5)
} else if (uart->Instance == USART5) {
} else if (self->uart_id == 5) {
__HAL_RCC_USART5_FORCE_RESET();
__HAL_RCC_USART5_RELEASE_RESET();
__HAL_RCC_USART5_CLK_DISABLE();
#endif
#if defined(UART6)
} else if (uart->Instance == USART6) {
} else if (self->uart_id == 6) {
HAL_NVIC_DisableIRQ(USART6_IRQn);
__HAL_RCC_USART6_FORCE_RESET();
__HAL_RCC_USART6_RELEASE_RESET();
__HAL_RCC_USART6_CLK_DISABLE();
#endif
#if defined(UART7)
} else if (uart->Instance == UART7) {
} else if (self->uart_id == 7) {
HAL_NVIC_DisableIRQ(UART7_IRQn);
__HAL_RCC_UART7_FORCE_RESET();
__HAL_RCC_UART7_RELEASE_RESET();
__HAL_RCC_UART7_CLK_DISABLE();
#endif
#if defined(USART7)
} else if (uart->Instance == USART7) {
} else if (self->uart_id == 7) {
__HAL_RCC_USART7_FORCE_RESET();
__HAL_RCC_USART7_RELEASE_RESET();
__HAL_RCC_USART7_CLK_DISABLE();
#endif
#if defined(UART8)
} else if (uart->Instance == UART8) {
} else if (self->uart_id == 8) {
HAL_NVIC_DisableIRQ(UART8_IRQn);
__HAL_RCC_UART8_FORCE_RESET();
__HAL_RCC_UART8_RELEASE_RESET();
__HAL_RCC_UART8_CLK_DISABLE();
#endif
#if defined(USART8)
} else if (uart->Instance == USART8) {
} else if (self->uart_id == 8) {
__HAL_RCC_USART8_FORCE_RESET();
__HAL_RCC_USART8_RELEASE_RESET();
__HAL_RCC_USART8_CLK_DISABLE();
@ -485,7 +500,7 @@ uint32_t uart_get_baudrate(pyb_uart_obj_t *self) {
#endif
// This formula assumes UART_OVERSAMPLING_16
uint32_t baudrate = uart_clk / self->uart.Instance->BRR;
uint32_t baudrate = uart_clk / self->uartx->BRR;
return baudrate;
}
@ -497,7 +512,7 @@ mp_uint_t uart_rx_any(pyb_uart_obj_t *self) {
} else if (buffer_bytes > 0) {
return buffer_bytes;
} else {
return __HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET;
return UART_RXNE_IS_SET(self->uartx);
}
}
@ -507,7 +522,7 @@ mp_uint_t uart_rx_any(pyb_uart_obj_t *self) {
bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout) {
uint32_t start = HAL_GetTick();
for (;;) {
if (self->read_buf_tail != self->read_buf_head || __HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
if (self->read_buf_tail != self->read_buf_head || UART_RXNE_IS_SET(self->uartx)) {
return true; // have at least 1 char ready for reading
}
if (HAL_GetTick() - start >= timeout) {
@ -528,17 +543,17 @@ int uart_rx_char(pyb_uart_obj_t *self) {
data = self->read_buf[self->read_buf_tail];
}
self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len;
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
if (UART_RXNE_IS_SET(self->uartx)) {
// UART was stalled by flow ctrl: re-enable IRQ now we have room in buffer
__HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE);
UART_RXNE_IT_EN(self->uartx);
}
return data;
} else {
// no buffering
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7)
return self->uart.Instance->RDR & self->char_mask;
return self->uartx->RDR & self->char_mask;
#else
return self->uart.Instance->DR & self->char_mask;
return self->uartx->DR & self->char_mask;
#endif
}
}
@ -548,7 +563,7 @@ int uart_rx_char(pyb_uart_obj_t *self) {
bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) {
uint32_t start = HAL_GetTick();
for (;;) {
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_TXE)) {
if (uart_tx_avail(self)) {
return true; // tx register is empty
}
if (HAL_GetTick() - start >= timeout) {
@ -565,9 +580,15 @@ STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t tim
// an interrupt and the flag can be set quickly if the baudrate is large.
uint32_t start = HAL_GetTick();
for (;;) {
if (__HAL_UART_GET_FLAG(&self->uart, flag)) {
#if defined(STM32F4)
if (self->uartx->SR & flag) {
return true;
}
#else
if (self->uartx->ISR & flag) {
return true;
}
#endif
if (timeout == 0 || HAL_GetTick() - start >= timeout) {
return false; // timeout
}
@ -585,7 +606,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
}
uint32_t timeout;
if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
if (self->uartx->CR3 & USART_CR3_CTSE) {
// CTS can hold off transmission for an arbitrarily long time. Apply
// the overall timeout rather than the character timeout.
timeout = self->timeout;
@ -600,7 +621,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
const uint8_t *src = (const uint8_t*)src_in;
size_t num_tx = 0;
USART_TypeDef *uart = self->uart.Instance;
USART_TypeDef *uart = self->uartx;
while (num_tx < num_chars) {
if (!uart_wait_flag_set(self, UART_FLAG_TXE, timeout)) {
@ -648,15 +669,15 @@ void uart_irq_handler(mp_uint_t uart_id) {
return;
}
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
if (UART_RXNE_IS_SET(self->uartx)) {
if (self->read_buf_len != 0) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
if (next_head != self->read_buf_tail) {
// only read data if room in buf
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7)
int data = self->uart.Instance->RDR; // clears UART_FLAG_RXNE
int data = self->uartx->RDR; // clears UART_FLAG_RXNE
#else
int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
int data = self->uartx->DR; // clears UART_FLAG_RXNE
#endif
data &= self->char_mask;
// Handle interrupt coming in on a UART REPL
@ -671,7 +692,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
}
self->read_buf_head = next_head;
} else { // No room: leave char in buf, disable interrupt
__HAL_UART_DISABLE_IT(&self->uart, UART_IT_RXNE);
UART_RXNE_IT_DIS(self->uartx);
}
}
}

Wyświetl plik

@ -43,7 +43,7 @@ typedef enum {
typedef struct _pyb_uart_obj_t {
mp_obj_base_t base;
UART_HandleTypeDef uart; // this is 17 words big
USART_TypeDef *uartx;
IRQn_Type irqn;
pyb_uart_t uart_id : 8;
bool is_enabled : 1;
@ -63,7 +63,7 @@ extern const mp_obj_type_t pyb_uart_type;
void uart_init0(void);
void uart_deinit_all(void);
bool uart_exists(int uart_id);
bool uart_init2(pyb_uart_obj_t *uart_obj);
bool uart_init2(pyb_uart_obj_t *uart_obj, UART_InitTypeDef *init);
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);
@ -77,4 +77,12 @@ bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout);
size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode);
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
static inline bool uart_tx_avail(pyb_uart_obj_t *self) {
#if defined(STM32F4)
return self->uartx->SR & USART_SR_TXE;
#else
return self->uartx->ISR & USART_ISR_TXE;
#endif
}
#endif // MICROPY_INCLUDED_STM32_UART_H