326 lines
9.3 KiB
C
326 lines
9.3 KiB
C
|
/*
|
|||
|
******************************************************************************
|
|||
|
* @file driver_uart.c
|
|||
|
* @author FreqChip Firmware Team
|
|||
|
* @version V1.0.0
|
|||
|
* @date 2021
|
|||
|
* @brief UART module driver.
|
|||
|
* This file provides firmware functions to manage the
|
|||
|
* Universal Asynchronous Receiver/Transmitter (UART) peripheral
|
|||
|
******************************************************************************
|
|||
|
* @attention
|
|||
|
*
|
|||
|
* Copyright (c) 2021 FreqChip.
|
|||
|
* All rights reserved.
|
|||
|
******************************************************************************
|
|||
|
*/
|
|||
|
#include "fr30xx.h"
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_IRQHandler
|
|||
|
*
|
|||
|
* @brief Handle UART interrupt request.
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
*/
|
|||
|
__WEAK void uart_IRQHandler(UART_HandleTypeDef *huart)
|
|||
|
{
|
|||
|
switch (__UART_INT_GET_ID(huart->UARTx))
|
|||
|
{
|
|||
|
case INT_INDEX_TXE:
|
|||
|
{
|
|||
|
/* Data transit end */
|
|||
|
if (huart->u32_TxCount >= huart->u32_TxSize)
|
|||
|
{
|
|||
|
__UART_INT_TXE_DISABLE(huart->UARTx);
|
|||
|
|
|||
|
huart->b_TxBusy = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* UART_FIFO_ENABLE */
|
|||
|
if (__UART_IS_FIFO_Enable(huart))
|
|||
|
{
|
|||
|
/* Until TxFIFO full */
|
|||
|
while(!__UART_IS_TxFIFO_FULL(huart->UARTx))
|
|||
|
{
|
|||
|
huart->UARTx->DATA_DLL.DATA = huart->p_TxData[huart->u32_TxCount++];
|
|||
|
|
|||
|
/* Data transit end */
|
|||
|
if (huart->u32_TxCount >= huart->u32_TxSize)
|
|||
|
{
|
|||
|
__UART_INT_TXE_DISABLE(huart->UARTx);
|
|||
|
|
|||
|
huart->b_TxBusy = false;
|
|||
|
|
|||
|
if (huart->TxCpltCallback != NULL)
|
|||
|
{
|
|||
|
huart->TxCpltCallback(huart);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
huart->UARTx->DATA_DLL.DATA = huart->p_TxData[huart->u32_TxCount++];
|
|||
|
}
|
|||
|
}
|
|||
|
}break;
|
|||
|
|
|||
|
|
|||
|
case INT_INDEX_RX:
|
|||
|
case INT_INDEX_RX_TOUT:
|
|||
|
{
|
|||
|
/* Rx ready */
|
|||
|
while (huart->UARTx->LSR.LSR_BIT.DR)
|
|||
|
{
|
|||
|
huart->p_RxData[huart->u32_RxCount++] = huart->UARTx->DATA_DLL.DATA;
|
|||
|
|
|||
|
/* Data receive end */
|
|||
|
if (huart->u32_RxCount >= huart->u32_RxSize)
|
|||
|
{
|
|||
|
__UART_INT_RX_DISABLE(huart->UARTx);
|
|||
|
|
|||
|
huart->b_RxBusy = false;
|
|||
|
|
|||
|
if (huart->RxCpltCallback != NULL)
|
|||
|
{
|
|||
|
huart->RxCpltCallback(huart);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}break;
|
|||
|
|
|||
|
default: break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_init
|
|||
|
*
|
|||
|
* @brief Initialize the UART according to the specified parameters in the struct_UARTInit_t
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
*/
|
|||
|
void uart_init(UART_HandleTypeDef *huart)
|
|||
|
{
|
|||
|
/* Config Data Length */
|
|||
|
huart->UARTx->LCR.Bits.DLS = huart->Init.DataLength;
|
|||
|
/* Config Stop Bits*/
|
|||
|
huart->UARTx->LCR.Bits.STOP = huart->Init.StopBits;
|
|||
|
/* Config Auto Flow */
|
|||
|
if(huart->Init.AUTO_FLOW)
|
|||
|
{
|
|||
|
__UART_AUTO_FLOW_CONTROL_ENABLE( huart->UARTx);
|
|||
|
}
|
|||
|
/* Config Parity */
|
|||
|
if (huart->Init.Parity != UART_PARITY_NONE)
|
|||
|
{
|
|||
|
huart->UARTx->LCR.Bits.PEN = 1;
|
|||
|
|
|||
|
switch (huart->Init.Parity)
|
|||
|
{
|
|||
|
case UART_PARITY_ODD: huart->UARTx->LCR.Bits.SP = 0; huart->UARTx->LCR.Bits.EPS = 0; break;
|
|||
|
case UART_PARITY_EVEN: huart->UARTx->LCR.Bits.SP = 0; huart->UARTx->LCR.Bits.EPS = 1; break;
|
|||
|
case UART_PARITY_0: huart->UARTx->LCR.Bits.SP = 1; huart->UARTx->LCR.Bits.EPS = 1; break;
|
|||
|
case UART_PARITY_1: huart->UARTx->LCR.Bits.SP = 1; huart->UARTx->LCR.Bits.EPS = 0; break;
|
|||
|
|
|||
|
default: break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
huart->UARTx->LCR.Bits.PEN = 0;
|
|||
|
}
|
|||
|
|
|||
|
/* Config FIFO<46><4F>DMA<4D><41>RxFIF/TxFIFO threshold */
|
|||
|
huart->FCR_Shadow = huart->Init.FIFO_Mode | (huart->Init.FIFO_Mode << FCR_DMAM);
|
|||
|
|
|||
|
huart->UARTx->FCR_IID.FCR = huart->FCR_Shadow;
|
|||
|
|
|||
|
/* Config BaudRate */
|
|||
|
uart_config_baudRate(huart);
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_transmit
|
|||
|
*
|
|||
|
* @brief Send an amount of data in blocking mode.
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
* @param fp_Data: Pointer to data buffer.
|
|||
|
* @param fu32_Size: Amount of data to be sent.
|
|||
|
*/
|
|||
|
void uart_transmit(UART_HandleTypeDef *huart, uint8_t *fp_Data, uint32_t fu32_Size)
|
|||
|
{
|
|||
|
/* UART_FIFO_ENABLE */
|
|||
|
if (__UART_IS_FIFO_Enable(huart))
|
|||
|
{
|
|||
|
while (fu32_Size--)
|
|||
|
{
|
|||
|
/* TxFIFO FULL */
|
|||
|
while(!(huart->UARTx->USR.TFNF));
|
|||
|
/* Send data */
|
|||
|
huart->UARTx->DATA_DLL.DATA = *fp_Data++;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
while (fu32_Size--)
|
|||
|
{
|
|||
|
/* Tx not empty */
|
|||
|
while(!(huart->UARTx->LSR.LSR_BIT.THRE));
|
|||
|
/* Send data */
|
|||
|
huart->UARTx->DATA_DLL.DATA = *fp_Data++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_receive
|
|||
|
*
|
|||
|
* @brief Receive an amount of data in blocking mode.
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
* @param fp_Data: Pointer to data buffer.
|
|||
|
* @param fu32_Size: Amount of data to be receive.
|
|||
|
*/
|
|||
|
void uart_receive(UART_HandleTypeDef *huart, uint8_t *fp_Data, uint32_t fu32_Size)
|
|||
|
{
|
|||
|
while (fu32_Size--)
|
|||
|
{
|
|||
|
/* Rx ready */
|
|||
|
while (!(huart->UARTx->LSR.LSR_BIT.DR));
|
|||
|
/* receive data */
|
|||
|
*fp_Data++ = huart->UARTx->DATA_DLL.DATA;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_transmit_IT
|
|||
|
*
|
|||
|
* @brief Send an amount of data in interrupt mode.
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
* @param fp_Data: Pointer to data buffer.
|
|||
|
* @param fu32_Size: Amount of data to be sent.
|
|||
|
*/
|
|||
|
void uart_transmit_IT(UART_HandleTypeDef *huart, uint8_t *fp_Data, uint32_t fu32_Size)
|
|||
|
{
|
|||
|
if (huart->b_TxBusy)
|
|||
|
return;
|
|||
|
|
|||
|
huart->p_TxData = fp_Data;
|
|||
|
huart->u32_TxCount = 0;
|
|||
|
huart->u32_TxSize = fu32_Size;
|
|||
|
huart->b_TxBusy = true;
|
|||
|
|
|||
|
/* UART_FIFO_ENABLE */
|
|||
|
if (__UART_IS_FIFO_Enable(huart))
|
|||
|
{
|
|||
|
// /* Tx FIFO reset */
|
|||
|
// __UART_TxFIFO_Reset(huart);
|
|||
|
|
|||
|
/* Tx empty interrupt and fifo enable */
|
|||
|
__UART_INT_TXE_ENABLE_FE(huart->UARTx);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* Tx empty interrupt and fifo disable */
|
|||
|
__UART_INT_TXE_ENABLE_FD(huart->UARTx);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_transmit_IT
|
|||
|
*
|
|||
|
* @brief Receive an amount of data in interrupt mode.
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
* @param fp_Data: Pointer to data buffer.
|
|||
|
* @param fu32_Size: Amount of data to be receive.
|
|||
|
*/
|
|||
|
void uart_receive_IT(UART_HandleTypeDef *huart, uint8_t *fp_Data, uint32_t fu32_Size)
|
|||
|
{
|
|||
|
if (huart->b_RxBusy)
|
|||
|
return;
|
|||
|
|
|||
|
huart->p_RxData = fp_Data;
|
|||
|
huart->u32_RxCount = 0;
|
|||
|
huart->u32_RxSize = fu32_Size;
|
|||
|
huart->b_RxBusy = true;
|
|||
|
|
|||
|
// /* Rx FIFO reset */
|
|||
|
// __UART_RxFIFO_Reset(huart);
|
|||
|
|
|||
|
/* data ready<64><79>character timeout interrupt enable */
|
|||
|
__UART_INT_RX_ENABLE(huart->UARTx);
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn uart_config_baudRate
|
|||
|
*
|
|||
|
* @brief Config BaudRate
|
|||
|
*
|
|||
|
* @param huart: UART handle.
|
|||
|
*/
|
|||
|
void uart_config_baudRate(UART_HandleTypeDef *huart)
|
|||
|
{
|
|||
|
uint32_t i;
|
|||
|
uint32_t lu32_UartClock;
|
|||
|
uint32_t lu32_Integer;
|
|||
|
uint64_t lu64_Fractional;
|
|||
|
uint16_t lu32_TempValue[2];
|
|||
|
|
|||
|
lu32_UartClock = system_get_peripheral_clock(PER_CLK_UARTx);
|
|||
|
|
|||
|
/* Calculate the integer part */
|
|||
|
lu32_Integer = lu32_UartClock / (16 * huart->Init.BaudRate);
|
|||
|
|
|||
|
/* Calculate the fractional part */
|
|||
|
lu64_Fractional = lu32_UartClock % (16 * huart->Init.BaudRate);
|
|||
|
lu64_Fractional = (lu64_Fractional * 10000) / (16 * huart->Init.BaudRate);
|
|||
|
|
|||
|
for (i = 0; i < 0x3F; i++)
|
|||
|
{
|
|||
|
lu32_TempValue[0] = (i * 10000) / 64;
|
|||
|
lu32_TempValue[1] = ((i + 1) * 10000) / 64;
|
|||
|
|
|||
|
if (lu64_Fractional >= lu32_TempValue[0] && lu64_Fractional <= lu32_TempValue[1])
|
|||
|
{
|
|||
|
if (lu64_Fractional - lu32_TempValue[0] < lu32_TempValue[1] - lu64_Fractional)
|
|||
|
{
|
|||
|
lu64_Fractional = i;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
lu64_Fractional = i + 1;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
else if (i == 0x3E)
|
|||
|
{
|
|||
|
lu64_Fractional = 0x3F;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* DLL<4C><4C>DLH register access enable */
|
|||
|
__UART_DLL_DLH_ACCESS_ENABLE(huart->UARTx);
|
|||
|
|
|||
|
huart->UARTx->DATA_DLL.DLL = lu32_Integer & 0xFF;
|
|||
|
huart->UARTx->IER_DLH.DLH = (lu32_Integer >> 8) & 0xFF;
|
|||
|
huart->UARTx->DLF.DLF = lu64_Fractional;
|
|||
|
|
|||
|
/* DLL<4C><4C>DLH register access disable */
|
|||
|
__UART_DLL_DLH_ACCESS_DISABLE(huart->UARTx);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|