forked from gatsby/df_datalink
221 lines
5.1 KiB
C
221 lines
5.1 KiB
C
/*****************************************************************************/
|
|
/**
|
|
* @file systembus_uart.h
|
|
* @author FanHao ([email protected])
|
|
* @brief System bus uart driver implementation file.
|
|
* @version 0.1
|
|
* @date 2023-05-06
|
|
*
|
|
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
|
* Lab of Communication and Network
|
|
*
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* @addtogroup SystemBus
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @addtogroup SystemBus_UART
|
|
* @{
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "systembus_uart.h"
|
|
#include "common.h"
|
|
|
|
/**
|
|
* @name SystemBus_UART_Driver_Constants
|
|
* @{
|
|
*/
|
|
// Control and status register
|
|
#define MODULE_VERSION 0x00000000U
|
|
#define UART_STATUS 0x0000004U
|
|
#define UART_SEND_CMD 0x00000008U
|
|
#define UART_RECV_CNT 0x0000000CU
|
|
|
|
// Status code
|
|
#define UART_STATUS_TX_BUSY 0x00010000
|
|
#define UART_STATUS_RX_BUSY 0x01000000
|
|
// Data buffer register
|
|
#define UART_TXBUFF_OFFSET 1024
|
|
#define UART_TXBUFF_MAX 1024
|
|
#define UART_RXBUFF_OFFSET 2048
|
|
#define UART_RXBUFF_MAX 1024
|
|
|
|
#if (UART_TXBUFF_MAX < UART_FRM_MAX || UART_RXBUFF_MAX < UART_FRM_MAX)
|
|
#error "UART_FRM_MAX exceeds the maximum value."
|
|
#endif
|
|
|
|
// Frame Data offsets
|
|
#define FRAME_HEAD_LOW 0x5A
|
|
#define FRAME_HEAD_HIGH 0x54
|
|
#define FRAME_TAIL_LOW 0x5A
|
|
#define FRAME_TAIL_HIGH 0xFE
|
|
|
|
#define FRAME_HEAD_LEN 2
|
|
#define FRAME_TAIL_LEN 2
|
|
#define FRAME_DUMMY_LEN 1 // Dummy
|
|
#define FRAME_CHECK_LEN 1 // CheckSum
|
|
#define FRAME_INFO_LEN 3 // CheckSum, Dummy and DataLen
|
|
#define FRAME_OVERHEAD_LEN 7 // CheckSum, Dummy and DataLen
|
|
/** @} SystemBus_UART_Driver_Constants*/
|
|
|
|
int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config)
|
|
{
|
|
ASSERT(instPtr != NULL);
|
|
ASSERT(config != NULL);
|
|
(*instPtr) = malloc(sizeof(SYSBUS_UART));
|
|
if ((*instPtr) == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
(*instPtr)->config.baseAddr = config->baseAddr;
|
|
return SUCCESS;
|
|
}
|
|
|
|
int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame)
|
|
{
|
|
ASSERT(instPtr != NULL);
|
|
ASSERT(frame != NULL);
|
|
uint8_t checkSum;
|
|
uint16_t dLen, sendLen;
|
|
uint8_t *sendBuff;
|
|
if (frame->len > UART_TXBUFF_MAX || frame->len == 0)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
sendBuff = malloc(sizeof(uint8_t) * UART_TXBUFF_MAX);
|
|
if (sendBuff == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
sendBuff[0] = FRAME_HEAD_LOW;
|
|
sendBuff[1] = FRAME_HEAD_HIGH;
|
|
dLen = 0;
|
|
checkSum = 0;
|
|
for (int i = 0; i < frame->len - 1; i++)
|
|
{
|
|
if (frame->data[i] == FRAME_TAIL_LOW && frame->data[i + 1] == FRAME_TAIL_HIGH)
|
|
{
|
|
sendBuff[FRAME_HEAD_LEN + dLen] = 0x00;
|
|
dLen++;
|
|
}
|
|
sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[i];
|
|
checkSum += sendBuff[FRAME_HEAD_LEN + dLen];
|
|
dLen++;
|
|
}
|
|
// Last Byte
|
|
sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[frame->len - 1];
|
|
checkSum += sendBuff[FRAME_HEAD_LEN + dLen];
|
|
dLen++;
|
|
// Dummy Byte
|
|
sendBuff[FRAME_HEAD_LEN + dLen] = 0x00;
|
|
// Check Sum
|
|
sendBuff[FRAME_HEAD_LEN + dLen + 1] = checkSum;
|
|
// Data Len
|
|
sendBuff[FRAME_HEAD_LEN + dLen + 2] = dLen;
|
|
// Frame Tail
|
|
sendBuff[FRAME_HEAD_LEN + dLen + 3] = FRAME_TAIL_LOW;
|
|
sendBuff[FRAME_HEAD_LEN + dLen + 4] = FRAME_TAIL_HIGH;
|
|
sendLen = dLen + FRAME_OVERHEAD_LEN;
|
|
if (sendLen > UART_TXBUFF_MAX)
|
|
{
|
|
free(sendBuff);
|
|
return FAILURE;
|
|
}
|
|
memcpy((void *)(instPtr->config.baseAddr + UART_TXBUFF_OFFSET), sendBuff,
|
|
NORMALIZE_SIZE((sendLen + sizeof(uint32_t) - 1) / sizeof(uint32_t) * sizeof(uint32_t)));
|
|
free(sendBuff);
|
|
// Start Sending
|
|
SYSTEMBUS_UART_mWriteReg(instPtr->config.baseAddr, UART_SEND_CMD, sendLen);
|
|
return SUCCESS;
|
|
}
|
|
|
|
int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame)
|
|
{
|
|
ASSERT(instPtr != NULL);
|
|
ASSERT(frame != NULL);
|
|
|
|
uint16_t dLen, dWLen, plLen;
|
|
uint8_t checkSum, checkSumCal;
|
|
uint8_t *plBuff, *dBuff;
|
|
dLen = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_RECV_CNT);
|
|
if (dLen == 0 || dLen > UART_TXBUFF_MAX)
|
|
{
|
|
return EPARAM;
|
|
}
|
|
dWLen = (dLen + FRAME_HEAD_LEN + FRAME_INFO_LEN - 1) / 4 + 1;
|
|
|
|
dBuff = malloc(sizeof(uint32_t) * dWLen);
|
|
if (dBuff == NULL)
|
|
{
|
|
return ENOMEM;
|
|
}
|
|
memcpy(dBuff, (void *)(instPtr->config.baseAddr + UART_RXBUFF_OFFSET),
|
|
NORMALIZE_SIZE(sizeof(uint32_t) * dWLen));
|
|
plBuff = dBuff + FRAME_HEAD_LEN;
|
|
checkSumCal = 0;
|
|
checkSum = plBuff[dLen + FRAME_DUMMY_LEN];
|
|
plLen = 0;
|
|
for (int i = 0; i < dLen; i++)
|
|
{
|
|
if (plBuff[i + 1] == FRAME_TAIL_LOW && plBuff[i + 2] == FRAME_TAIL_HIGH)
|
|
{
|
|
continue;
|
|
}
|
|
checkSumCal += plBuff[i];
|
|
frame->data[plLen] = plBuff[i];
|
|
plLen++;
|
|
}
|
|
free(dBuff);
|
|
frame->len = plLen;
|
|
frame->checkSum = checkSumCal;
|
|
if (checkSumCal != checkSum)
|
|
{
|
|
frame->isValid = false;
|
|
return FAILURE;
|
|
}
|
|
frame->isValid = true;
|
|
return SUCCESS;
|
|
}
|
|
|
|
bool SysbusUart_IsRxBusy(SYSBUS_UART *instPtr)
|
|
{
|
|
ASSERT(instPtr != NULL);
|
|
uint32_t Status;
|
|
Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS);
|
|
|
|
if (Status & UART_STATUS_RX_BUSY)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool SysbusUart_IsTxBusy(SYSBUS_UART *instPtr)
|
|
{
|
|
ASSERT(instPtr != NULL);
|
|
uint32_t Status;
|
|
Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS);
|
|
if (Status & UART_STATUS_TX_BUSY)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** @} SystemBus_UART*/
|
|
|
|
/** @} SystemBus*/
|