You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
7.1 KiB

#include "uart1.h"
#include "sw_timer.h"
#include "ring_buffer.h"
#define UARTn_TX_INTERRUTP_ENABLE FALSE
#define UARTn_PERIPHERAL UART1
#define UARTn_INTERRUPT_HANDLER UART1_IRQn
#define UARTn_INTERRUPT_MASK MSK_UART1
#define UARTn_INTERRUPT_PRIORITY 3
#define UARTn_TX_PORT PB
#define UARTn_TX_PIN_NUM 6
#define UARTn_RX_PORT PB
#define UARTn_RX_PIN_NUM 7
#define UARTn_TX_BUFFER_SIZE 200
#define UARTn_RX_BUFFER_SIZE 100
static uint8_t Tx_Buffer[UARTn_TX_BUFFER_SIZE];
static uint8_t Rx_Buffer[UARTn_RX_BUFFER_SIZE];
static RING_BUFFER RingBuffer_Tx;
static RING_BUFFER RingBuffer_Rx;
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
static volatile uint8_t Uartn_TxIntEnable = FALSE;
static void Uart1_Init_TransmitSet(void);
#else
static void Uart1_Transmit_Process(void);
#endif
static void Uart1_Receive_Handler(void);
void Uart1_Initialization(uint32_t Baudrate, UARTn_DATA_BIT_Type Databit, UARTn_PARITY_BIT_Type Paritybit, UARTn_STOP_BIT_Type Stopbit)
{
UARTn_CFG_Type UARTn_Config;
/*
* Initialize UART0 pin connect
*/
HAL_GPIO_ConfigOutput((Pn_Type*)UARTn_RX_PORT, UARTn_RX_PIN_NUM, ALTERN_FUNC );
HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_RX_PORT, UARTn_RX_PIN_NUM, AFSRx_AF1 );
HAL_GPIO_ConfigPullup((Pn_Type*)UARTn_RX_PORT, UARTn_RX_PIN_NUM, PUPDx_EnablePU );
HAL_GPIO_ConfigOutput((Pn_Type*)UARTn_TX_PORT, UARTn_TX_PIN_NUM, ALTERN_FUNC );
HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_TX_PORT, UARTn_TX_PIN_NUM, AFSRx_AF1 );
// default: 38400-8-N-1
HAL_UART_ConfigStructInit(&UARTn_Config);
UARTn_Config.Baudrate = Baudrate;
UARTn_Config.Databits = Databit;
UARTn_Config.Parity = Paritybit;
UARTn_Config.Stopbits = Stopbit;
HAL_UART_Init((UARTn_Type*)UARTn_PERIPHERAL, &UARTn_Config);
/* Enable UART Rx interrupt */
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_RBR, ENABLE );
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
// Reset Tx Interrupt state
Uartn_TxIntEnable = RESET;
#else
SW_Timer_Callback_Register(SW_TIMER_RUN_CONTINUE, 0, Uart1_Transmit_Process);
#endif
RingBuffer_Initialization(&RingBuffer_Rx, false, UARTn_RX_BUFFER_SIZE, &Rx_Buffer[0]);
RingBuffer_Initialization(&RingBuffer_Tx, false, UARTn_TX_BUFFER_SIZE, &Tx_Buffer[0]);
NVIC_SetPriority(UARTn_INTERRUPT_HANDLER, UARTn_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(UARTn_INTERRUPT_HANDLER );
HAL_INT_EInt_MaskDisable(UARTn_INTERRUPT_MASK);
}
void Uart1_Transmit(uint8_t TxData)
{
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
/* Temporarily lock out UART transmit interrupts during this read so the UART transmit interrupt won't cause problems with the index values */
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
RingBuffer_Enqueue(&RingBuffer_Tx, TxData);
/*
* Check if current Tx interrupt enable is reset,
* that means the Tx interrupt must be re-enabled
* due to call IntTransmit() function to trigger
* this interrupt type
*/
if(Uartn_TxIntEnable == RESET)
{
Uart1_Init_TransmitSet();
}
/*
* Otherwise, re-enables Tx Interrupt
*/
else
{
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
}
#else
RingBuffer_Enqueue(&RingBuffer_Tx, TxData);
#endif
}
void Uart1_TransmitData(uint8_t* pTxData, uint32_t TxLen)
{
uint32_t i;
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
for(i = 0 ; i < TxLen ; i++)
RingBuffer_Enqueue(&RingBuffer_Tx, pTxData[i]);
if(Uartn_TxIntEnable == RESET)
{
Uart1_Init_TransmitSet();
}
else
{
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
}
#else
for(i = 0 ; i < TxLen ; i++)
RingBuffer_Enqueue(&RingBuffer_Tx, pTxData[i]);
#endif
}
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
static void Uart1_Init_TransmitSet(void)
{
// Disable THRE interrupt
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
/* Wait until THR empty */
while( HAL_UART_CheckBusy( ( UARTn_Type* )UARTn_PERIPHERAL ) == SET );
while(RingBuffer_Get_DataSize(&RingBuffer_Tx) != 0)
{
uint8_t TxData;
RingBuffer_GetData(&RingBuffer_Tx, &TxData);
if(HAL_UART_Transmit( ( UARTn_Type* )UARTn_PERIPHERAL, &TxData, 1, NONE_BLOCKING ) )
{
/* Update transmit ring FIFO tail pointer */
RingBuffer_PopData(&RingBuffer_Tx);
break;
}
else
{
break;
}
}
/* If there is no more data to send, disable the transmit interrupt - else enable it or keep it enabled */
if(RingBuffer_Get_DataSize(&RingBuffer_Tx) == 0)
{
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
// Reset Tx Interrupt state
Uartn_TxIntEnable = RESET;
}
else
{
// Set Tx Interrupt state
Uartn_TxIntEnable = SET;
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
}
}
#else
static void Uart1_Transmit_Process(void)
{
if(RingBuffer_Get_DataSize(&RingBuffer_Tx) != 0)
{
uint8_t TxData;
RingBuffer_GetData(&RingBuffer_Tx, &TxData);
if(HAL_UART_Transmit((UARTn_Type*)UARTn_PERIPHERAL, &TxData, 1, NONE_BLOCKING))
{
/* Update transmit ring FIFO tail pointer */
RingBuffer_PopData(&RingBuffer_Tx);
}
}
}
#endif
static void Uart1_Receive_Handler(void)
{
uint8_t tmpc;
uint32_t rLen;
while(1)
{
rLen = HAL_UART_Receive((UARTn_Type*)UARTn_PERIPHERAL, &tmpc, 1, NONE_BLOCKING );
if (rLen)
{
RingBuffer_Enqueue(&RingBuffer_Rx, tmpc);
}
else
{
break;
}
}
}
/*********************************************************************//**
* @brief UART1 interrupt handler sub-routine
* @param[in] None
* @return None
**********************************************************************/
void UART1_Handler(void)
{
uint32_t intsrc, tmp;
/* Determine the interrupt source */
intsrc = UARTn_PERIPHERAL->IIR;
tmp = intsrc & UARTn_IIR_INTID_MASK;
// Receiver Line Status
if(tmp == UARTn_IIR_INTID_RLS) // error(Overrun, Parity, Framing or Break Error)
{
}
else if(tmp == UARTn_IIR_INTID_RDA) // Receiver Data Available
{
Uart1_Receive_Handler();
}
else if(tmp == UARTn_IIR_INTID_THRE) // Transmitter Holding Register Empty
{
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
Uart1_Init_TransmitSet();
#endif
}
else if(tmp == UARTn_IIR_INTID_TXE) // Transmitter Register Empty
{
}
}
uint32_t Uart1_Get_RecvDataCount(void)
{
return RingBuffer_Get_DataSize(&RingBuffer_Rx);
}
uint8_t Uart1_Get_RecvData(void)
{
uint8_t retData;
RingBuffer_Dequeue(&RingBuffer_Rx, &retData);
return retData;
}