first commit, new repo branches from datalink_repo

This commit is contained in:
Gatsby Van
2024-01-19 17:19:32 +08:00
commit 9934a7534c
378 changed files with 103816 additions and 0 deletions
+579
View File
@@ -0,0 +1,579 @@
/*****************************************************************************/
/**
* Description: System bus protocol implementation file.
*
* Date: 2023-05-06 10:13
* Last Edit Time: [2023-05-06 21:45]
*
* Revisions: Rev 0.0
* History:
* [2023-05-06]: Initial version.
* [2023-09-13]: Update to 485 protocol-20220816
*
* Copyright(c) 2021 Beijing Institute of Technology.
* Lab of Communication and Network
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "systembus_uart.h"
#include "systembus.h"
#include "util.h"
#include "common.h"
#include "error.h"
#include "circ_queue.h"
#include "../system_monitor.h"
// Common Field
// -- Command word
#define WD_CMD 0x00
// -- Production type
#define WD_PRD 0x01
#define PRD_DL_K 0xDD
#define PRD_DL_S 0xDE
#define PRD_ALL 0xFF
// Self-Test
#define CMD_SELF_TEST 0xE1
// -- Request
// -- -- --
// -- Response
// -- -- Self-Test Result
#define ST_RSP_LEN 16
#define WD_ST_RET 0x02
#define ST_RET_OK 0xAA
#define ST_RET_ERROR 0x55
// -- -- Signal processor voltage
#define WD_SP_VOLT_L 0x03
#define WD_SP_VOLT_H 0x04
// -- -- Signal processor temperature
#define WD_SP_TEMP_L 0x05
#define WD_SP_TEMP_H 0x06
// -- -- Signal processor chip status
#define WD_SP_CS_L 0x07
#define WD_SP_CS_H 0x08
// -- -- Signal processor antenna voltage
#define WD_AS_VOLT 0x09
// -- -- Signal processor antenna temperature
#define WD_AS_TEMP 0x0A
// -- -- Signal processor antenna PLL lock status
#define WD_AS_PLL 0x0B
// -- -- Signal processor antenna MGC
#define WD_AS_MGC_L 0x0C
#define WD_AS_MGC_H 0x0D
// -- -- Signal processor antenna status
#define WD_AS_ST 0x0E.
// -- -- Dummy must be 0x00
#define WD_ST_DUMMY 0x0F
// Data Send Test Command
#define CMD_DATA_TEST_A 0xE2
// -- Request
#define DATA_TEST_REQ_A_LEN 80
// -- -- 78 byte payload
// -- Response
#define DATA_TEST_RSP_A_LEN 80
// -- -- 78 byte payload
// Data Send Test Command
#define CMD_DATA_TEST_B 0xF2
// -- Request
#define DATA_TEST_REQ_B_LEN 152
// -- -- 150 byte payload
// -- Response
#define DATA_TEST_RSP_B_LEN 152
// -- -- 150 byte payload
// Config load
#define CMD_CONFIG 0xE3
// -- Request
#define WD_EN_CMD 0x02
#define EN_CMD_ON 0x66
#define WD_MODE_CMD 0x03
#define MODE_CMD_HEAD 0x11
#define MODE_CMD_MEMBER 0x11
// -- Response
// -- -- none response
// System info update
#define CMD_SYS_INFO 0x33
#define SYS_INFO_OFFSET 2
// -- Request
// -- -- 54 byte system info
// -- Response
// -- -- none response
// Data Send Test Command
#define CMD_FLJ_SEND 0xE4
#define FLJ_DATA_OFFSET 2
// -- Request
// -- -- 78 byte payload
// -- Response
// -- -- none response
// Data Send Test Command
#define CMD_LJ_SEND 0xF4
#define LJ_DATA_OFFSET 2
// -- Request
// -- -- 156 byte payload
// -- Response
// -- -- none response
// FLJ Poll
#define CMD_FLJ_POLL 0xE5
// -- Request
#define WD_FLJ_POLL 0x02
#define FLJ_POLL_CODE 0x77
// -- Response
#define FLJ_POLL_RESP_LEN 78
// -- -- received 78 byte payload
// LJ Poll
#define CMD_LJ_POLL 0xF5
// -- Request
#define WD_LJ_POLL 0x02
#define LJ_POLL_CODE 0x77
// -- Response
#define LJ_POLL_RESP_LEN 168
// -- -- received 156 byte payload
// Remote Test FLJ
#define CMD_FLJ_RM_TEST 0xE6
// -- Request
#define WD_FLJ_RM_TEST 0x02
#define FLJ_RM_TEST_CODE 0x99
// -- Response
#define FLJ_RM_TEST_RESP_LEN 158
// Remote Test LJ
#define CMD_LJ_RM_TEST 0xF6
// -- Request
#define WD_LJ_RM_TEST 0x02
#define LJ_RM_TEST_CODE 0x99
// -- Response
#define LJ_RM_TEST_RESP_LEN 158
// My Production Type
#define MY_PRD_ID PRD_DL_K
inline bool SystemBus_IsReqPendding(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
return (!isCircQueueEmpty(instPtr->rxQueue));
}
inline bool SystemBus_IsRsqPendding(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
return (!isCircQueueEmpty(instPtr->txQueue));
}
inline bool SystemBus_IsTxBusy(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
return (!instPtr->isTxDone);
}
inline bool SystemBus_IsRxBusy(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
return SysbusUart_IsRxBusy(instPtr->uartInst);
}
/*****************************************************************************/
/**
* @brief Initialize System Bus instance.
*
* @param InstPtr A double pointer to System Bus instance.
* @param config A pointer to System Bus configurations.
*
* @return None.
*
******************************************************************************/
int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config)
{
ASSERT(instPtr != NULL);
ASSERT(config != NULL);
SYSBUS_UART_CONFIG uartConfig;
int32_t Status;
(*instPtr) = malloc(sizeof(SYSBUS));
if ((*instPtr) == NULL)
{
return FAILURE;
}
(*instPtr)->rxQueue = NULL;
(*instPtr)->txQueue = NULL;
(*instPtr)->uartInst = NULL;
memcpy(&((*instPtr)->config), config, sizeof(SYSBUS_CONFIG));
uartConfig.baseAddr = config->baseAddr;
Status = SysbusUart_Init(&((*instPtr)->uartInst), &uartConfig);
if (Status != SUCCESS)
{
Status = ENOMEM;
goto sysbus_init_error;
}
if (CircQueueCreate(&((*instPtr)->txQueue), (*instPtr)->config.txQueueMax) == false)
{
Status = ENOMEM;
goto sysbus_init_error;
}
if (CircQueueCreate(&((*instPtr)->rxQueue), (*instPtr)->config.rxQueueMax) == false)
{
Status = ENOMEM;
goto sysbus_init_error;
}
(*instPtr)->isRxDone = false; // nothing received.
(*instPtr)->isTxDone = true; // nothing to be sent.
return SUCCESS;
sysbus_init_error:
free((*instPtr)->uartInst);
free((*instPtr)->txQueue);
free((*instPtr)->rxQueue);
free(*instPtr);
return Status;
}
/*****************************************************************************/
/**
* @brief A handler function. This handler evaluate the message from system
* bus receive queue, and make appropriate response.
*
* @param instPtr A pointer to System Bus instance.
*
* @return None
*
******************************************************************************/
int32_t SystemBus_HandleCmd(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
SYSBUS_UART_FRAME *sysbusReq, *sysbusRsp;
uint8_t *data;
if (CircQueuePop(instPtr->rxQueue, (void **)(&sysbusReq)) == false)
{
DBG_WARNING("SystemBus::Nothing to be handled.\n");
return EIGNORE;
}
data = sysbusReq->data;
if (data[WD_PRD] != MY_PRD_ID && data[WD_PRD] != PRD_ALL)
{
DBG_WARNING("SystemBus::Production code mismatch!\n");
return EIGNORE;
}
switch (data[WD_CMD])
{
case CMD_SELF_TEST:
{
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for SELF TEST Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp->len = ST_RSP_LEN;
memset(sysbusRsp->data, 0x00, ST_RSP_LEN);
sysbusRsp->data[WD_CMD] = CMD_SELF_TEST;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
// FIXME: run self-test and insert result
sysbusRsp->data[WD_ST_RET] = ST_RET_OK;
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false)
{
free(sysbusRsp);
DBG_ERROR("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_DATA_TEST_A:
{
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for DATA TEST A Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp->len = DATA_TEST_RSP_A_LEN;
memcpy(sysbusRsp->data, sysbusReq->data, DATA_TEST_RSP_A_LEN);
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false)
{
free(sysbusRsp);
DBG_ERROR("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_DATA_TEST_B:
{
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for DATA TEST B Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp->len = DATA_TEST_RSP_B_LEN;
memcpy(sysbusRsp->data, sysbusReq->data, DATA_TEST_RSP_B_LEN);
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false)
{
free(sysbusRsp);
DBG_ERROR("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_CONFIG:
{
// FIXME: apply configurations
// Power + Mode
// -- No response
_nop_(); // for debug
Status = SUCCESS;
break;
}
case CMD_SYS_INFO:
{
SysMonitor_UpdateSysinfoRaw(data + SYS_INFO_OFFSET);
Status = SUCCESS;
break;
}
// TODO
case CMD_FLJ_SEND:
{
SysMonitor_UpdateSendPayloadFLJRaw(data + FLJ_DATA_OFFSET); // omit control info
break;
}
case CMD_LJ_SEND:
{
SysMonitor_UpdateSendPayloadLJRaw(data + LJ_DATA_OFFSET); // omit control info
break;
}
case CMD_FLJ_POLL:
{
if (data[WD_FLJ_POLL] != FLJ_POLL_CODE)
{
DBG_ERROR("SystemBus::Invalid roll call code!\n");
Status = EIGNORE;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for FLJ POLL Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp->len = FLJ_POLL_RESP_LEN;
sysbusRsp->data[WD_CMD] = WD_FLJ_POLL;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
SysMonitor_GetRecvPayloadFLJRaw(sysbusRsp->data + FLJ_DATA_OFFSET); // omit control info
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false)
{
free(sysbusRsp);
DBG_WARNING("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_LJ_POLL:
{
if (data[WD_LJ_POLL] != LJ_POLL_CODE)
{
DBG_WARNING("SystemBus::Invalid roll call code!\n");
Status = EIGNORE;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for LJ POLL Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp->len = LJ_POLL_RESP_LEN;
sysbusRsp->data[WD_CMD] = WD_LJ_POLL;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
SysMonitor_GetRecvPayloadLJRaw(sysbusRsp->data + 2); // omit control info
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false)
{
free(sysbusRsp);
DBG_WARNING("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_FLJ_RM_TEST:
{
if (data[WD_FLJ_RM_TEST] != FLJ_RM_TEST_CODE)
{
DBG_WARNING("SystemBus::Invalid remote test code!\n");
Status = EIGNORE;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for FLJ REMOTE TEST Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
sysbusRsp->len = FLJ_RM_TEST_RESP_LEN;
memset(sysbusRsp->data, 0x00, FLJ_RM_TEST_RESP_LEN);
sysbusRsp->data[WD_CMD] = CMD_FLJ_RM_TEST;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){
free(sysbusRsp);
DBG_WARNING("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
case CMD_LJ_RM_TEST:
{
if (data[WD_LJ_RM_TEST] != LJ_RM_TEST_CODE)
{
DBG_WARNING("SystemBus::Invalid remote test code!\n");
Status = EIGNORE;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for LJ REMOTE TEST Response!\n");
Status = ENOMEM;
break;
}
sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME));
sysbusRsp->len = LJ_RM_TEST_RESP_LEN;
memset(sysbusRsp->data, 0x00, LJ_RM_TEST_RESP_LEN);
sysbusRsp->data[WD_CMD] = CMD_LJ_RM_TEST;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){
free(sysbusRsp);
DBG_WARNING("SystemBus::TX Queue overflowed!\n");
Status = EQUEUE;
break;
}
Status = SUCCESS;
break;
}
default:
{
DBG_ERROR("SystemBus::Unknown command code!\n");
break;
}
}
free(sysbusReq);
return Status;
}
int32_t SystemBus_FLJ_PeriodUpdate(SYSBUS *instPtr)
{
// TODO
return SUCCESS;
}
int32_t SystemBus_LJ_PeriodUpdate(SYSBUS *instPtr)
{
// TODO
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief This function send a repose frame from system bus tx queue.
*
* @param instPtr A pointer to System Bus instance.
*
* @return None
*
******************************************************************************/
int32_t SystemBus_MakeResp(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
SYSBUS_UART_FRAME *sysbusRsp;
if (CircQueuePop(instPtr->txQueue, (void **)(&sysbusRsp)) == false)
{
DBG_WARNING("SystemBus::Nothing to be sent.\n");
return EIGNORE;
}
instPtr->isTxDone = false; // A transmission procedure is started.
Status = SysbusUart_Send(instPtr->uartInst, sysbusRsp);
free(sysbusRsp);
return Status;
}
/*****************************************************************************/
/**
* @brief This function handles the systembus tx irq events.
*
* @param instPtr A pointer to System Bus instance.
*
* @return None
*
******************************************************************************/
int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
// nothing special...
instPtr->isTxDone = true; // A transmission procedure finished.
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief This function handles the systembus rx irq events.
*
* @param instPtr A pointer to System Bus instance.
*
* @return None
*
******************************************************************************/
int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
SYSBUS_UART_FRAME *sysbusReq;
instPtr->isRxDone = true; // whether reception successes or not, receiving procedure ended.
sysbusReq = malloc(sizeof(SYSBUS_UART_FRAME));
if (sysbusReq == NULL)
{
return ENOMEM;
}
Status = SysbusUart_Recv(instPtr->uartInst, sysbusReq);
if (Status != SUCCESS)
{
goto recv_error;
}
if (CircQueuePush(instPtr->rxQueue, (void *)sysbusReq) == false)
{
DBG_ERROR("SystemBus::RX Queue overflowed!\n");
Status = EQUEUE;
goto recv_error;
}
instPtr->isRxDone = false; // another reception is undergoing.
return SUCCESS;
recv_error:
free(sysbusReq);
return Status;
}
+65
View File
@@ -0,0 +1,65 @@
/*****************************************************************************/
/**
* Description: System bus protocol head file.
*
* Date: 2023-05-06 10:12
* Last Edit Time: [2023-05-06 10:13]
*
* Revisions: Rev 0.0
* History:
* [2023-05-06]: Initial version.
*
* Copyright(c) 2021 Beijing Institute of Technology.
*
******************************************************************************/
#ifndef __SYSTEMBUS_H_
#define __SYSTEMBUS_H_
/***************************** Include Files *********************************/
#include "systembus_uart.h" // SystemBus UART driver
#include "circ_queue.h"
#include <stdint.h>
#include <stdbool.h>
/************************** Constant Definitions *****************************/
/************************** Data Type Definitions ****************************/
// Definition of SystemBus instance.
typedef struct
{
uintptr_t baseAddr;
uint32_t txQueueMax;
uint32_t rxQueueMax;
} SYSBUS_CONFIG;
typedef struct
{
SYSBUS_CONFIG config;
SYSBUS_UART *uartInst;
CIRC_QUEUE *txQueue;
CIRC_QUEUE *rxQueue;
bool isRxDone;
bool isTxDone;
} SYSBUS;
/************************** Function Prototypes ******************************/
int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config);
int32_t SystemBus_HandleCmd(SYSBUS *instPtr);
int32_t SystemBus_FLJ_PeriodUpdate(SYSBUS *instPtr);
int32_t SystemBus_LJ_PeriodUpdate(SYSBUS *instPtr);
int32_t SystemBus_MakeResp(SYSBUS *instPtr);
int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr);
int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr);
bool SystemBus_IsReqPendding(SYSBUS *instPtr);
bool SystemBus_IsRsqPendding(SYSBUS *instPtr);
bool SystemBus_IsTxBusy(SYSBUS *instPtr);
bool SystemBus_IsRxBusy(SYSBUS *instPtr);
#endif //__SYSTEMBUS_H_
@@ -0,0 +1,248 @@
/*****************************************************************************/
/**
* Description: System bus uart driver implementation file.
*
* Date: 2023-05-06 10:59
* LastEditTime: 2023-05-06 21:56
* Revisions: Rev 0.0
* History:
* [2023-05-06]: Initial version.
*
* Copyright(c) 2022 Beijing Institute of Technology.
*
******************************************************************************/
/***************************** Include Files *******************************/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "systembus_uart.h"
#include "common.h"
// Control and status register
#define MODULE_VERSION 0
#define UART_STATUS 4
#define UART_SEND_CMD 8
#define UART_RECV_CNT 12
// Status code
#define UART_STATUS_TX_BUSY 0x00010000
#define UART_STATUS_RX_BUSY 0x01000000
// Data buffer register
#define UART_TXBUFF_LOW 1024
#define UART_TXBUFF_MAX 1024
#define UART_RXBUFF_LOW 2048
#define UART_RXBUFF_MAX 1024
// 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
/*************************** Function Definitions ****************************/
/*****************************************************************************/
/**
* @brief Instance initial
*
* @param instPtr A pointer to frame uart instance structure.
* @param config Base address of frame uart, refer to "xparameters.h"
*
* @return None.
*
******************************************************************************/
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;
}
/*****************************************************************************/
/**
* @brief Send a system bus frame.
*
* @param instPtr A pointer to SYSBUS_UART instance structure.
* @param buff A pointer to send data buffer
* @param dLen A integer indicate the send data buffer length in byte.
*
* @return
*
******************************************************************************/
int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame)
{
ASSERT(instPtr != NULL);
ASSERT(frame != NULL);
uint8_t dLen, checkSum;
uint8_t 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_LOW), sendBuff, (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;
}
/*****************************************************************************/
/**
* @brief Get last system bus frame.
*
* @param instPtr A pointer to SYSBUS_UART instance structure.
* @param buff A pointer to receive data buffer.
*
* @return
*
******************************************************************************/
int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame)
{
ASSERT(instPtr != NULL);
ASSERT(frame != NULL);
uint8_t dLen, dWLen, plLen, 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_LOW), 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;
}
/*****************************************************************************/
/**
* @brief Get rx channel status.
*
* @param instPtr A pointer to SYSBUS_UART instance structure.
*
* @return true - SYSBUS_UART rx channel is busy.
* false - SYSBUS_UART rx channel is idle.
*
******************************************************************************/
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;
}
}
/*****************************************************************************/
/**
* @brief Get tx channel status.
*
* @param instPtr A pointer to SYSBUS_UART instance structure.
*
* @return true - SYSBUS_UART tx channel is busy.
* false - SYSBUS_UART tx channel is idle.
*
******************************************************************************/
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;
}
}
@@ -0,0 +1,99 @@
/*****************************************************************************/
/**
* Description: System bus uart driver implementation file.
*
* Date: 2023-05-06 10:59
* LastEditTime: 2023-05-06 21:48
* Revisions: Rev 0.0
* History:
* [2023-05-06]: Initial version.
*
* Copyright(c) 2022 Beijing Institute of Technology.
*
******************************************************************************/
#ifndef SYSTEMBUS_UART_H
#define SYSTEMBUS_UART_H
/****************** Include Files ********************/
#include <stdint.h>
#include <stdbool.h>
#include "util.h"
/**************************** Type Definitions *****************************/
/**
*
* Write a value to a SYSTEMBUS_UART register. A 32 bit write is performed.
* If the component is implemented in a smaller width, only the least
* significant data is written.
*
* @param baseAddr is the base address of the SYSTEMBUS_UARTdevice.
* @param offset is the register offset from the base to write to.
* @param data is the data written to the register.
*
* @return None.
*
* @note
* C-style signature:
* void SYSTEMBUS_UART_mWriteReg(uint32_t BaseAddress, unsigned RegOffset, uint32_t Data)
*
*/
#define SYSTEMBUS_UART_mWriteReg(baseAddr, offset, data) \
IO_Out32((baseAddr) + (offset), (uint32_t)(data))
/**
*
* Read a value from a SYSTEMBUS_UART register. A 32 bit read is performed.
* If the component is implemented in a smaller width, only the least
* significant data is read from the register. The most significant data
* will be read as 0.
*
* @param baseAddr is the base address of the SYSTEMBUS_UART device.
* @param offset is the register offset from the base to write to.
*
* @return Data is the data from the register.
*
* @note
* C-style signature:
* uint32_t SYSTEMBUS_UART_mReadReg(uint32_t BaseAddress, unsigned RegOffset)
*
*/
#define SYSTEMBUS_UART_mReadReg(baseAddr, offset) \
IO_In32((baseAddr) + (offset))
/************************** Data Type Definitions ****************************/
typedef struct
{
uintptr_t baseAddr;
} SYSBUS_UART_CONFIG;
typedef struct
{
SYSBUS_UART_CONFIG config;
} SYSBUS_UART;
typedef struct
{
uint8_t len;
uint8_t checkSum;
uint8_t isValid;
uint8_t dummy;
uint8_t data[256];
} SYSBUS_UART_FRAME;
/************************** Function Prototypes ******************************/
// Instance initial
int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config);
// Send a system bus frame.
int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame);
// Get last system bus frame.
int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame);
// Get system bus rx channel status.
bool SysbusUart_IsRxBusy(SYSBUS_UART *instPtr);
// Get system bus tx channel status.
bool SysbusUart_IsTxBusy(SYSBUS_UART *instPtr);
#endif // SYSTEMBUS_UART_H