rt-thread/bsp/mm32/libraries/HAL_Drivers/drv_uart.c

433 lines
11 KiB
C

/*
* Copyright (c) 2020-2022, CQ 100ask Development Team
*
* Change Logs:
* Date Author Notes
* 2022-05-29 Alen first version
*/
#include "board.h"
#include "drv_uart.h"
#include "drv_config.h"
#ifdef RT_USING_SERIAL
//#define DRV_DEBUG
#define LOG_TAG "drv.usart"
#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \
!defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && \
!defined(BSP_USING_UART7) && !defined(BSP_USING_UART8)
#error "Please define at least one BSP_USING_UARTx"
/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
#endif
#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->CSR & (__FLAG__)) == (__FLAG__))
#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->CSR = ~(__FLAG__))
#define __HAL_UART_GET_INT_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->ISR & (__FLAG__)) == (__FLAG__))
#define __HAL_UART_CLEAR_INT_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->ICR &= (__FLAG__))
enum
{
#ifdef BSP_USING_UART1
UART1_INDEX,
#endif
#ifdef BSP_USING_UART2
UART2_INDEX,
#endif
#ifdef BSP_USING_UART3
UART3_INDEX,
#endif
#ifdef BSP_USING_UART4
UART4_INDEX,
#endif
#ifdef BSP_USING_UART5
UART5_INDEX,
#endif
#ifdef BSP_USING_UART6
UART6_INDEX,
#endif
#ifdef BSP_USING_UART7
UART7_INDEX,
#endif
#ifdef BSP_USING_UART8
UART8_INDEX,
#endif
#ifdef BSP_USING_LPUART1
LPUART1_INDEX,
#endif
};
static struct mm32_uart_config uart_config[] =
{
#ifdef BSP_USING_UART1
UART1_CONFIG,
#endif
#ifdef BSP_USING_UART2
UART2_CONFIG,
#endif
#ifdef BSP_USING_UART3
UART3_CONFIG,
#endif
#ifdef BSP_USING_UART4
UART4_CONFIG,
#endif
#ifdef BSP_USING_UART5
UART5_CONFIG,
#endif
#ifdef BSP_USING_UART6
UART6_CONFIG,
#endif
#ifdef BSP_USING_UART7
UART7_CONFIG,
#endif
#ifdef BSP_USING_UART8
UART8_CONFIG,
#endif
#ifdef BSP_USING_LPUART1
LPUART1_CONFIG,
#endif
};
static struct mm32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
static rt_err_t mm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct mm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
uart = rt_container_of(serial, struct mm32_uart, serial);
uart->handle.ClockFreqHz = HAL_Get_APB2_Clock();
uart->handle.BaudRate = cfg->baud_rate;
uart->handle.XferMode = UART_XferMode_RxTx;
switch (cfg->flowcontrol)
{
case RT_SERIAL_FLOWCONTROL_NONE:
uart->handle.HwFlowControl = UART_HwFlowControl_None;
break;
case RT_SERIAL_FLOWCONTROL_CTSRTS:
uart->handle.HwFlowControl = UART_HwFlowControl_RTS_CTS;
break;
default:
uart->handle.HwFlowControl = UART_HwFlowControl_None;
break;
}
switch (cfg->data_bits)
{
case DATA_BITS_5:
uart->handle.WordLength = UART_WordLength_5b;
break;
case DATA_BITS_6:
uart->handle.WordLength = UART_WordLength_6b;
break;
case DATA_BITS_7:
uart->handle.WordLength = UART_WordLength_7b;
break;
case DATA_BITS_8:
uart->handle.WordLength = UART_WordLength_8b;
break;
default:
uart->handle.WordLength = UART_WordLength_8b;
break;
}
switch (cfg->stop_bits)
{
case STOP_BITS_1:
uart->handle.StopBits = UART_StopBits_1;
break;
case STOP_BITS_2:
uart->handle.StopBits = UART_StopBits_2;
break;
default:
uart->handle.StopBits = UART_StopBits_1;
break;
}
switch (cfg->parity)
{
case PARITY_NONE:
uart->handle.Parity = UART_Parity_None;
break;
case PARITY_ODD:
uart->handle.Parity = UART_Parity_Odd;
break;
case PARITY_EVEN:
uart->handle.Parity = UART_Parity_Even;
break;
default:
uart->handle.Parity = UART_Parity_None;
break;
}
#ifdef RT_SERIAL_USING_DMA
if (!(serial->parent.open_flag & RT_DEVICE_OFLAG_OPEN)) {
uart->dma_rx.last_index = 0;
}
#endif
extern void UART_MspInit(UART_Type *muart);
UART_MspInit(uart->config->Instance);
UART_Init(uart->config->Instance, &uart->handle);
UART_Enable(uart->config->Instance, true);
return RT_EOK;
}
static rt_err_t mm32_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct mm32_uart *uart;
rt_uint32_t prioritygroup = 0x00U;
#ifdef RT_SERIAL_USING_DMA
rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
#endif
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct mm32_uart, serial);
switch (cmd)
{
/* disable interrupt */
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
NVIC_DisableIRQ(uart->config->irq_type);
#ifdef RT_SERIAL_USING_DMA
/* disable DMA */
if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX)
{
}
else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX)
{
}
#endif
break;
/* enable interrupt */
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
UART_EnableInterrupts(uart->config->Instance, UART_INT_RX_DONE, true);
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(prioritygroup, 1, 0));
NVIC_EnableIRQ(uart->config->irq_type);
break;
#ifdef RT_SERIAL_USING_DMA
case RT_DEVICE_CTRL_CONFIG:
break;
#endif
case RT_DEVICE_CTRL_CLOSE:
break;
}
return RT_EOK;
}
rt_uint32_t mm32_uart_get_mask(rt_uint32_t word_length, rt_uint32_t parity)
{
rt_uint32_t mask;
if (word_length == UART_WordLength_8b)
{
if (parity == UART_Parity_None)
{
mask = 0x00FFU ;
}
else
{
mask = 0x007FU ;
}
}
#ifdef UART_WORDLENGTH_7B
else if (word_length == UART_WordLength_7b)
{
if (parity == UART_Parity_None)
{
mask = 0x007FU ;
}
else
{
mask = 0x003FU ;
}
}
else
{
mask = 0x0000U;
}
#endif
return mask;
}
static int mm32_putc(struct rt_serial_device *serial, char c)
{
struct mm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct mm32_uart, serial);
uart->config->Instance->TDR = c;
while ( 0u == (UART_STATUS_TX_EMPTY & UART_GetStatus(uart->config->Instance)) )
{}
return 1;
}
static int mm32_getc(struct rt_serial_device *serial)
{
int ch;
struct mm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct mm32_uart, serial);
ch = -1;
if ((UART_STATUS_RX_DONE & UART_GetStatus(uart->config->Instance)) != 0)
{
ch = uart->config->Instance->RDR & mm32_uart_get_mask(uart->handle.WordLength, uart->handle.Parity);
}
return ch;
}
/**
* Uart common interrupt process. This need add to uart ISR.
*
* @param serial serial device
*/
static void uart_isr(struct rt_serial_device *serial)
{
struct mm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
rt_size_t recv_total_index, recv_len;
rt_base_t level;
#endif
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct mm32_uart, serial);
/* UART in mode Receiver -------------------------------------------------*/
if ( (0u != __HAL_UART_GET_INT_FLAG(uart->config->Instance, UART_INT_RX_DONE))
&& (0u != __HAL_UART_GET_FLAG(uart->config->Instance, UART_STATUS_RX_DONE)) )
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
#ifdef RT_SERIAL_USING_DMA
#endif
else
{
if (__HAL_UART_GET_FLAG(uart->config->Instance, UART_STATUS_RX_DONE) != 0)
{
__HAL_UART_CLEAR_FLAG(uart->config->Instance, UART_STATUS_RX_DONE);
}
if (__HAL_UART_GET_FLAG(uart->config->Instance, UART_STATUS_TX_DONE) != 0)
{
__HAL_UART_CLEAR_FLAG(uart->config->Instance, UART_STATUS_TX_DONE);
}
if (__HAL_UART_GET_FLAG(uart->config->Instance, UART_STATUS_TX_FULL) != 0)
{
__HAL_UART_CLEAR_FLAG(uart->config->Instance, UART_STATUS_TX_FULL);
}
if (__HAL_UART_GET_FLAG(uart->config->Instance, UART_STATUS_TX_EMPTY) != 0)
{
__HAL_UART_CLEAR_FLAG(uart->config->Instance, UART_STATUS_TX_EMPTY);
}
if (__HAL_UART_GET_INT_FLAG(uart->config->Instance, UART_INT_RX_DONE) != 0)
{
__HAL_UART_CLEAR_INT_FLAG(uart->config->Instance, UART_INT_RX_DONE);
}
if (__HAL_UART_GET_INT_FLAG(uart->config->Instance, UART_INT_TX_DONE) != 0)
{
__HAL_UART_CLEAR_INT_FLAG(uart->config->Instance, UART_INT_TX_DONE);
}
if (__HAL_UART_GET_INT_FLAG(uart->config->Instance, UART_INT_TX_EMPTY) != 0)
{
__HAL_UART_CLEAR_INT_FLAG(uart->config->Instance, UART_INT_TX_EMPTY);
}
}
}
#if defined(BSP_USING_UART1)
void UART1_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
uart_isr(&(uart_obj[UART1_INDEX].serial));
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#if defined(BSP_USING_UART2)
void UART2_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
uart_isr(&(uart_obj[UART2_INDEX].serial));
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#if defined(BSP_USING_UART3)
void UART3_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
uart_isr(&(uart_obj[UART3_INDEX].serial));
/* leave interrupt */
rt_interrupt_leave();
}
#endif
static const struct rt_uart_ops mm32_uart_ops =
{
.configure = mm32_configure,
.control = mm32_control,
.putc = mm32_putc,
.getc = mm32_getc,
.dma_transmit = RT_NULL
};
int rt_hw_uart_init(void)
{
rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct mm32_uart);
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t result = 0;
for (int i = 0; i < obj_num; i++)
{
/* init UART object */
uart_obj[i].config = &uart_config[i];
uart_obj[i].serial.ops = &mm32_uart_ops;
uart_obj[i].serial.config = config;
/* register UART device */
result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
RT_DEVICE_FLAG_RDWR
| RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX
| uart_obj[i].uart_dma_flag
, NULL);
RT_ASSERT(result == RT_EOK);
}
return result;
}
#endif /* RT_USING_SERIAL */