132 lines
2.8 KiB
C
132 lines
2.8 KiB
C
/**
|
|
* @file bsp_uart.c
|
|
* @brief UART1 DMA + IDLE interrupt driver
|
|
*/
|
|
|
|
#include "bsp_uart.h"
|
|
#include "bsp_cmd.h"
|
|
#include "usart.h"
|
|
#include <string.h>
|
|
|
|
/* External DMA handle */
|
|
extern DMA_HandleTypeDef hdma_usart1_rx;
|
|
|
|
/* DMA receive buffer */
|
|
uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE];
|
|
|
|
/* IDLE interrupt sets this flag, main loop checks and processes */
|
|
static volatile uint16_t idle_rx_len = 0;
|
|
|
|
/**
|
|
* @brief Init UART1 for MQTT module with DMA
|
|
*/
|
|
void BSP_UART1_Init(void)
|
|
{
|
|
/* Start DMA reception */
|
|
HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE);
|
|
|
|
/* Enable IDLE line detection interrupt */
|
|
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
|
|
}
|
|
|
|
/**
|
|
* @brief Send data via UART1 (blocking)
|
|
*/
|
|
uint16_t BSP_UART1_Send(uint8_t *data, uint16_t len)
|
|
{
|
|
return HAL_UART_Transmit(&huart1, data, len, 1000);
|
|
}
|
|
|
|
/**
|
|
* @brief Send string via UART1
|
|
*/
|
|
uint16_t BSP_UART1_SendString(const char *str)
|
|
{
|
|
return BSP_UART1_Send((uint8_t*)str, strlen(str));
|
|
}
|
|
|
|
/**
|
|
* @brief Get received data length in DMA buffer
|
|
*/
|
|
uint16_t BSP_UART1_GetRxLen(void)
|
|
{
|
|
return UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
|
|
}
|
|
|
|
/**
|
|
* @brief Read data from DMA rx buffer (non-destructive copy)
|
|
*/
|
|
uint16_t BSP_UART1_Read(uint8_t *buf, uint16_t len)
|
|
{
|
|
uint16_t head = UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
|
|
|
|
uint16_t cnt = 0;
|
|
while (cnt < len && cnt < head)
|
|
{
|
|
buf[cnt] = uart1_rx_buf[cnt];
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear rx buffer (restart DMA)
|
|
*/
|
|
void BSP_UART1_ClearRxBuf(void)
|
|
{
|
|
HAL_UART_AbortReceive(&huart1);
|
|
HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE);
|
|
}
|
|
|
|
/**
|
|
* @brief Check if data received
|
|
*/
|
|
bool BSP_UART1_IsDataReceived(void)
|
|
{
|
|
return (idle_rx_len > 0);
|
|
}
|
|
|
|
/**
|
|
* @brief Process received data (call in main loop)
|
|
* Copies data, parses JSON command, sends JSON response via UART1
|
|
*/
|
|
void BSP_UART1_Process(void)
|
|
{
|
|
if (idle_rx_len == 0)
|
|
return;
|
|
|
|
/* Copy length and clear flag */
|
|
uint16_t rx_len = idle_rx_len;
|
|
idle_rx_len = 0;
|
|
|
|
/* Copy data to local buffer so DMA restart won't overwrite */
|
|
uint8_t local_buf[UART1_RX_BUF_SIZE];
|
|
if (rx_len > sizeof(local_buf))
|
|
rx_len = sizeof(local_buf);
|
|
memcpy(local_buf, uart1_rx_buf, rx_len);
|
|
|
|
/* Process JSON command */
|
|
BSP_Cmd_ProcessJSON(local_buf, rx_len);
|
|
|
|
/* Restart DMA for next frame */
|
|
BSP_UART1_ClearRxBuf();
|
|
}
|
|
|
|
/**
|
|
* @brief Called from USART1 IDLE interrupt - saves length and restarts DMA
|
|
*/
|
|
void BSP_UART1_IDLE_IRQHandler(void)
|
|
{
|
|
uint16_t rx_len = UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
|
|
|
|
if (rx_len > 0)
|
|
{
|
|
idle_rx_len = rx_len;
|
|
}
|
|
|
|
/* Restart DMA immediately */
|
|
HAL_UART_AbortReceive(&huart1);
|
|
HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE);
|
|
}
|