#include "ds2480_stm32f4_hal.h" #define RX_ERRORS (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE) static int prepare(void *user) { ds2480_stm32f4_hal *p = (ds2480_stm32f4_hal *)user; GPIO_InitTypeDef gpio = {0}; /* Abort resets HAL states after timeouts and disables UART IRQ/DMA. */ if (HAL_UART_Abort(p->uart) != HAL_OK) return -1; __HAL_UART_DISABLE(p->uart); HAL_GPIO_WritePin(p->tx_port, p->tx_pin, GPIO_PIN_RESET); gpio.Pin = p->tx_pin; gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(p->tx_port, &gpio); HAL_Delay(2); HAL_GPIO_WritePin(p->tx_port, p->tx_pin, GPIO_PIN_SET); HAL_Delay(2); gpio.Mode = GPIO_MODE_AF_PP; gpio.Alternate = p->tx_alternate; HAL_GPIO_Init(p->tx_port, &gpio); p->uart->Init.BaudRate = 9600; p->uart->Init.WordLength = UART_WORDLENGTH_8B; p->uart->Init.StopBits = UART_STOPBITS_1; p->uart->Init.Parity = UART_PARITY_NONE; p->uart->Init.Mode = UART_MODE_TX_RX; p->uart->Init.HwFlowCtl = UART_HWCONTROL_NONE; p->uart->Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(p->uart) != HAL_OK) return -1; /* SR then DR: discard BREAK echo/stale RX and clear FE/NE/ORE/PE. */ __HAL_UART_CLEAR_OREFLAG(p->uart); return 0; } static int write_byte(void *user, const uint8_t *data, uint32_t size, uint32_t timeout) { ds2480_stm32f4_hal *p = (ds2480_stm32f4_hal *)user; if (!data || size != 1 || !timeout || timeout == HAL_MAX_DELAY) return -1; /* One reply fits in DR while HAL waits for TX complete. Never flush RX * here: a reply may already be present when HAL_UART_Transmit returns. */ if (p->uart->Instance->SR & RX_ERRORS) return -1; return HAL_UART_Transmit(p->uart, data, 1, timeout) == HAL_OK ? 0 : -1; } static int read_byte(void *user, uint8_t *data, uint32_t size, uint32_t timeout) { ds2480_stm32f4_hal *p = (ds2480_stm32f4_hal *)user; uint32_t start, flags; if (!data || size != 1 || !timeout || timeout == HAL_MAX_DELAY) return -1; start = HAL_GetTick(); for (;;) { flags = p->uart->Instance->SR; /* Test errors BEFORE reading DR, including when RXNE is already set. */ if (flags & RX_ERRORS) { __HAL_UART_CLEAR_OREFLAG(p->uart); return -1; } if (flags & USART_SR_RXNE) { *data = (uint8_t)p->uart->Instance->DR; return 0; } if ((uint32_t)(HAL_GetTick() - start) >= timeout) return -1; } } static void delay_ms(void *user, uint32_t ms) { (void)user; HAL_Delay(ms); } ds2480_status ds2480_stm32f4_hal_bind(ds2480_stm32f4_hal *p, ds2480_port *port) { if (!p || !port || !p->uart || !p->uart->Instance || !p->tx_port || !p->tx_pin || (p->tx_pin & (p->tx_pin - 1U)) || p->tx_alternate > 15U) return DS2480_ARGUMENT; port->user = p; port->prepare = prepare; port->write = write_byte; port->read = read_byte; port->delay_ms = delay_ms; return DS2480_OK; }