sentry_chassis_hzz/bsp/bsp_usart.c

105 lines
4.3 KiB
C
Raw Normal View History

2022-11-01 22:32:15 +08:00
/**
* @file bsp_usart.c
* @author neozng
* @brief bsp层的实现
* @version beta
* @date 2022-11-01
2022-11-09 20:24:22 +08:00
*
2022-11-01 22:32:15 +08:00
* @copyright Copyright (c) 2022
2022-11-09 20:24:22 +08:00
*
2022-11-01 22:32:15 +08:00
*/
2022-10-20 17:13:02 +08:00
#include "bsp_usart.h"
#include "stdlib.h"
#include "memory.h"
2022-10-20 17:13:02 +08:00
2022-11-01 22:32:15 +08:00
/* usart service instance, modules' info would be recoreded here using USARTRegister() */
/* usart服务实例,所有注册了usart的模块信息会被保存在这里 */
2022-11-11 21:20:58 +08:00
static usart_instance *instance[DEVICE_USART_CNT] = {NULL};
2022-10-20 17:13:02 +08:00
/**
* @brief usart service will start automatically, after each module registered
2022-11-01 22:32:15 +08:00
*
2022-10-31 12:14:47 +08:00
*
2022-11-01 22:32:15 +08:00
* @param _instance instance owned by module,
2022-10-20 17:13:02 +08:00
*/
2022-10-31 12:14:47 +08:00
static void USARTServiceInit(usart_instance *_instance)
2022-10-20 17:13:02 +08:00
{
HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, _instance->recv_buff_size);
2022-11-01 22:32:15 +08:00
// 关闭dma half transfer中断防止两次进入HAL_UARTEx_RxEventCallback()
2022-11-11 22:23:17 +08:00
// 这是HAL库的一个设计失误,发生DMA传输完成/半完成以及串口IDLE中断都会触发HAL_UARTEx_RxEventCallback()
// 我们只希望处理因此直接关闭DMA半传输中断第一种和第三种情况
2022-10-20 17:13:02 +08:00
__HAL_DMA_DISABLE_IT(_instance->usart_handle->hdmarx, DMA_IT_HT);
}
usart_instance* USARTRegister(USART_Init_Config_s *init_config)
2022-10-20 17:13:02 +08:00
{
static uint8_t idx;
instance[idx]=(usart_instance*)malloc(sizeof(usart_instance));
memset(instance[idx],0,sizeof(usart_instance));
instance[idx]->module_callback=init_config->module_callback;
instance[idx]->recv_buff_size=init_config->recv_buff_size;
instance[idx]->usart_handle=init_config->usart_handle;
USARTServiceInit(instance[idx]);
return instance[idx++];
2022-10-20 17:13:02 +08:00
}
2022-11-01 22:32:15 +08:00
/* @todo 当前仅进行了形式上的封装,后续要进一步考虑是否将module的行为与bsp完全分离 */
2022-10-31 12:14:47 +08:00
void USARTSend(usart_instance *_instance, uint8_t *send_buf, uint16_t send_size)
2022-10-20 17:13:02 +08:00
{
2022-10-31 12:14:47 +08:00
HAL_UART_Transmit_DMA(_instance->usart_handle, send_buf, send_size);
2022-10-20 17:13:02 +08:00
}
/**
2022-11-01 22:32:15 +08:00
* @brief dma/idle中断发生时.uart实例会调用对应的回调进行进一步的处理
* ://
2022-10-20 17:13:02 +08:00
*
2022-11-11 22:23:17 +08:00
* @todo neozng给HAL库的github repo提了issue, ST在最新的一次更新中为此提供了一个HAL_UARTEx_GetRxEventType()
*
*
2022-11-01 22:32:15 +08:00
* @note because DMA half transfer iterrupt(DMA_IT_HT) would call this callback function too, so we just
2022-10-20 17:13:02 +08:00
* disable it when transfer complete using macro: __HAL_DMA_DISABLE_IT(huart->hdmarx,DMA_IT_HT)
2022-11-11 22:23:17 +08:00
* dma half transfer中断防止两次进入HAL_UARTEx_RxEventCallback()
* HAL库的一个设计失误,DMA传输完成/IDLE中断都会触发HAL_UARTEx_RxEventCallback()
* DMA半传输中断第一种和第三种情况
2022-10-20 17:13:02 +08:00
*
2022-11-01 22:32:15 +08:00
* @param huart uart handle indicate which uart is being handled
* @param Size not used temporarily,,
2022-10-20 17:13:02 +08:00
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
for (uint8_t i = 0; i < 3; i++)
{
if (huart == instance[i]->usart_handle)
{
instance[i]->module_callback();
memset(instance[i]->recv_buff,0,Size); // 接收结束后清空buffer,对于变长数据是必要的
2022-10-20 17:13:02 +08:00
HAL_UARTEx_ReceiveToIdle_DMA(instance[i]->usart_handle, instance[i]->recv_buff, instance[i]->recv_buff_size);
__HAL_DMA_DISABLE_IT(instance[i]->usart_handle->hdmarx, DMA_IT_HT);
break;
}
}
}
/**
* @brief when error occurs in the process of send/receive,this function will be called
* then just simply restart send/receive.
*
* @note most frequent error ex: parity/overrrun/frame error
*
2022-11-01 22:32:15 +08:00
* @param huart uart handle type, indicate where error comes from
2022-10-20 17:13:02 +08:00
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
for (uint8_t i = 0; i < 3; i++)
{
if (huart == instance[i]->usart_handle)
{
HAL_UARTEx_ReceiveToIdle_DMA(instance[i]->usart_handle, instance[i]->recv_buff, instance[i]->recv_buff_size);
__HAL_DMA_DISABLE_IT(instance[i]->usart_handle->hdmarx, DMA_IT_HT);
break;
}
}
}