add MPC module to GE project

This commit is contained in:
Gatsby Van
2024-03-12 20:43:15 +08:00
parent 31dcb5aa69
commit 2898bdfa15
7 changed files with 1024 additions and 110 deletions
+4 -3
View File
@@ -71,9 +71,10 @@
#define TIME_CONTROLLER_BASEADDR XPAR_TMC_BASEADDR
// System Bus Configs
//#define SYSBUS_BASE_ADDR XPAR_SYSTEMBUS_BASEADDR
//#define SYSBUS_TX_INTR_ID XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR
//#define SYSBUS_RX_INTR_ID XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR
#define MPC_BRAM_ID XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID
#define MPC_GPIO_ID XPAR_MPC_GPIO_DEVICE_ID
#define MPC_TX_INTR_ID XPAR_FABRIC_MPC_TX_IRQ_INTR
#define MPC_RX_INTR_ID XPAR_FABRIC_MPC_RX_IRQ_INTR
// Global Timer config
#define GLOBAL_TIMER_DEVICE_ID XPAR_GLOBAL_TMR_DEVICE_ID
@@ -11,7 +11,7 @@ struct xil_timer_init_param xil_scutimer_init_param = {
struct timer_init_param scutimer_init_param = {
.id = SCUTIMER_DEVICE_ID,
.freq_hz = SCU_TIMER_CLK_HZ,
.ticks_count = (SCU_TIMER_CLK_HZ/10), //update log every 100ms
.ticks_count = (SCU_TIMER_CLK_HZ/2), //update log every 500ms
.platform_ops = &xil_timer_ops,
.extra = &xil_scutimer_init_param
};
+110 -106
View File
@@ -36,7 +36,7 @@
#include "timer.h"
#include "config/app_config.h"
#include "dev_profile/dev_profile.h"
#include "systembus/systembus.h"
#include "mpc/mpc.h"
#include "networking/phy_layer/phy_layer.h"
#include "networking/link_layer/link_layer.h"
// RF-Driver
@@ -48,8 +48,8 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr);
void Phy_IntrHandler(void *context);
void PeriodicPull_Handler(void *callBackRef);
void ScuTimer_IntrHandler(void *context);
void Systembus_RxIntrHandler(void *context);
void Systembus_TxIntrHandler(void *context);
void Mpc_RxIntrHandler(void *context);
void Mpc_TxIntrHandler(void *context);
/************************** Constant Definitions *****************************/
struct callback_desc phy_callback_desc =
{
@@ -64,15 +64,15 @@ struct callback_desc periodicpull_callback_desc =
};
struct callback_desc sysbus_rx_callback_desc =
struct callback_desc mpc_rx_callback_desc =
{
.callback = Systembus_RxIntrHandler,
.callback = Mpc_RxIntrHandler,
.ctx = NULL
};
struct callback_desc sysbus_tx_callback_desc =
struct callback_desc mpc_tx_callback_desc =
{
.callback = Systembus_TxIntrHandler,
.callback = Mpc_TxIntrHandler,
.ctx = NULL
};
@@ -126,15 +126,16 @@ TMC_CONFIG tmcConfig =
.reset = 10
};
//static SYSBUS_CONFIG sysbusConfig = {
// .baseAddr = SYSBUS_BASE_ADDR,
// .txQueueMax = 16,
// .rxQueueMax = 16
//};
static MPC_CONFIG mpcConfig = {
.bramId = MPC_BRAM_ID,
.gpioId = MPC_GPIO_ID,
.txQueueMax = 16,
.rxQueueMax = 16
};
/************************** Function Prototypes ******************************/
static struct irq_ctrl_desc *intcDescPtr; // General interrupt controller descriptor
static struct timer_desc *logTmPtr;
static SYSBUS *sysbusDescPtr;
static MPC *mpcDescPtr;
static PHY_INST *phyInstPtr;
static TMC_INST *tmcInstPtr = NULL;
L2_INST *linkInstPtr;
@@ -213,64 +214,64 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
return Status;
}
// /* Initialize system bus interrupt. */
// Status = irq_trigger_level_set(descPtr, SYSBUS_TX_INTR_ID, IRQ_EDGE_RISING);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
// // Set interrupt priority
// Status = irq_set_priority(descPtr, SYSBUS_TX_INTR_ID, 0x10);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
//
// // Connect the interrupt service routine isr1 to the interrupt controller
// Status = irq_register_callback(descPtr, SYSBUS_TX_INTR_ID, &sysbus_tx_callback_desc);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
// Status = irq_trigger_level_set(descPtr, SYSBUS_RX_INTR_ID, IRQ_EDGE_RISING);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
// // Set interrupt priority
// Status = irq_set_priority(descPtr, SYSBUS_RX_INTR_ID, 0x18);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
//
// // Connect the interrupt service routine isr1 to the interrupt controller
// Status = irq_register_callback(descPtr, SYSBUS_RX_INTR_ID, &sysbus_rx_callback_desc);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
//
// /* Initialize Scu timer interrupt. */
// // Connect the interrupt service routine isr1 to the interrupt controller
// Status = irq_register_callback(descPtr, SCUTIMER_INTR_ID, &scutm_callback_desc);
// if (Status != SUCCESS)
// {
// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
// return Status;
// }
/* Initialize system bus interrupt. */
Status = irq_trigger_level_set(descPtr, MPC_TX_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Set interrupt priority
Status = irq_set_priority(descPtr, MPC_TX_INTR_ID, 0x10);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Connect the interrupt service routine isr1 to the interrupt controller
Status = irq_register_callback(descPtr, MPC_TX_INTR_ID, &mpc_tx_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
Status = irq_trigger_level_set(descPtr, MPC_RX_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Set interrupt priority
Status = irq_set_priority(descPtr, MPC_RX_INTR_ID, 0x18);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Connect the interrupt service routine isr1 to the interrupt controller
Status = irq_register_callback(descPtr, MPC_RX_INTR_ID, &mpc_rx_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
/* Initialize Scu timer interrupt. */
// Connect the interrupt service routine isr1 to the interrupt controller
Status = irq_register_callback(descPtr, SCUTIMER_INTR_ID, &scutm_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Enable interrupts
irq_enable(descPtr, PHY_INTR_ID);
irq_enable(descPtr, PERIODIC_5MS_INTR_ID);
// irq_enable(descPtr, SYSBUS_RX_INTR_ID);
// irq_enable(descPtr, SYSBUS_TX_INTR_ID);
irq_enable(descPtr, MPC_RX_INTR_ID);
irq_enable(descPtr, MPC_TX_INTR_ID);
irq_enable(descPtr, SCUTIMER_INTR_ID);
// Enable Exceptions
@@ -328,13 +329,13 @@ void PeriodicPull_Handler(void *callBackRef)
* @return None.
*
******************************************************************************/
void Systembus_RxIntrHandler(void *context)
void Mpc_RxIntrHandler(void *context)
{
int32_t Status;
Status = SystemBus_RxIntrHandler(sysbusDescPtr);
Status = Mpc_RxIrqHandler(mpcDescPtr);
if (Status != SUCCESS)
{
DBG_ERROR("SystemBus_RxIntrHandler exit with error code %" PRId32 ",\n", Status);
DBG_ERROR("Mpc_RxIrqHandler exit with error code %" PRId32 ",\n", Status);
}
}
@@ -347,13 +348,13 @@ void Systembus_RxIntrHandler(void *context)
* @return None.
*
******************************************************************************/
void Systembus_TxIntrHandler(void *context)
void Mpc_TxIntrHandler(void *context)
{
int32_t Status;
Status = SystemBus_TxIntrHandler(sysbusDescPtr);
Status = Mpc_TxIrqHandler(mpcDescPtr);
if (Status != SUCCESS)
{
DBG_ERROR("SystemBus_TxIntrHandler exit with error code %" PRId32 ",\n", Status);
DBG_ERROR("Mpc_TxIrqHandler exit with error code %" PRId32 ",\n", Status);
}
}
@@ -374,6 +375,15 @@ void ScuTimer_IntrHandler(void *context)
{
// Refresh log
Phy_RefreshHwSate(phyInstPtr);
if (Mpc_IsEnable(mpcDescPtr))
{
if (Mpc_PendRemoteTest(mpcDescPtr) != SUCCESS)
{
DBG_ERROR("Failed to apply remote test.\n");
}
}
XScuTimer_ClearInterruptStatus((XScuTimer *)xdesc->instance);
}
else
@@ -458,13 +468,13 @@ int main(void)
return Status;
}
// /* System Bus Initialize */
// Status = SystemBus_Init(&sysbusDescPtr, &sysbusConfig);
// if (Status != SUCCESS)
// {
// DBG_ERROR("Systembus init FAILED, with error code: %" PRId32 "\n", Status);
// return Status;
// }
/* System Bus Initialize */
Status = Mpc_Init(&mpcDescPtr, &mpcConfig);
if (Status != SUCCESS)
{
DBG_ERROR("MPC init FAILED, with error code: %" PRId32 "\n", Status);
return Status;
}
/* System Monitor log timer Initialize */
Status = timer_init(&logTmPtr, &scutimer_init_param);
@@ -492,30 +502,24 @@ int main(void)
DBG_PRINT("Physical started...\n");
Phy_Start(phyInstPtr);
Linklayer_Start(linkInstPtr);
while (true);
// while (true)
// {
// // System bus handler
// if (SystemBus_IsReqPendding(sysbusDescPtr))
// {
// Status = SystemBus_HandleCmd(sysbusDescPtr);
// if (Status != SUCCESS)
// {
// DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status);
// }
// }
// if (SystemBus_IsRsqPendding(sysbusDescPtr) && (!SystemBus_IsTxBusy(sysbusDescPtr)))
// {
// // FIXME: Required by 12 (CASC)
// udelay(200);
// Status = SystemBus_MakeResp(sysbusDescPtr);
// if (Status != SUCCESS)
// {
// DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status);
// }
// }
// }
while (true)
{
// System bus handler
if (Mpc_IsReqPending(mpcDescPtr))
{
Status = Mpc_HandleCmd(mpcDescPtr);
if (Status != SUCCESS)
{
DBG_ERROR("Mpc_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status);
}
}
if (Mpc_IsRsqPending(mpcDescPtr) && (!Mpc_IsTxBusy(mpcDescPtr)))
{
Status = Mpc_MakeResp(mpcDescPtr);
if (Status != SUCCESS)
{
DBG_ERROR("Mpc_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status);
}
}
}
} // main
+601
View File
@@ -0,0 +1,601 @@
/*****************************************************************************/
/**
* Description: MPC 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 "mpc.h"
#include "util.h"
#include "common.h"
#include "error.h"
#include "circ_queue.h"
#include "xbram.h"
#include "xgpio.h"
#include "../system_monitor.h"
/************************** Constant Definitions *****************************/
// Common Field
// -- Command word
#define WD_CMD 0x00
// -- Production type
#define WD_PRD 0x01
#define PRD_DL_K 0xDD
#define PRD_DL_S 0xEE
#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
#define ST_RET_INFO_LEN 13
// -- -- Signal processor PS voltage
#define WD_SP_FPGA_VOLT 0x03
// -- -- Signal processor PS AUX voltage
#define WD_SP_CLK_STATE 0x04
// -- -- Signal processor DDR voltage
#define WD_SP_AD_LOCK_STATE 0x05
// -- -- Signal processor PL voltage
#define WD_SP_AD_TEMP_0 0x06
// -- -- Signal processor PL AUX voltage
#define WD_SP_AD_TEMP_1 0x07
// -- -- Signal processor Bram voltage
#define WD_SP_FPGA_TEMP 0x08
// -- -- Signal processor antenna voltage status
#define WD_ANT_VOLT 0x09
// -- -- Signal processor antenna RF temperature
#define WD_ANT_RF_TEMP 0x0A
// -- -- Signal processor antenna PLL lock status
#define WD_ANT_RF_PLL 0x0B
// -- -- Signal processor antenna MGC
#define WD_ANT_MGC_0 0x0C
#define WD_ANT_MGC_1 0x0D
// -- -- Reserved
#define WD_ANT_RESERVE 0x0E
// Data Send Test Command
#define CMD_DATA_TEST_A 0xE2
// -- Request
#define DATA_TEST_REQ_A_LEN 68
// -- -- 68 byte payload
// -- Response
#define DATA_TEST_RSP_A_LEN 68
// -- -- 68 byte payload
// Data Send Test Command
#define CMD_DATA_TEST_B 0xF2
// -- Request
#define DATA_TEST_REQ_B_LEN 170
// -- -- 170 byte payload
// -- Response
#define DATA_TEST_RSP_B_LEN 170
// -- -- 170 byte payload
// Config load
#define CMD_CONFIG 0xE3
// -- Request
#define WD_EN_CMD 0x02
#define EN_CMD_ON_HIGH_POWER 0x66
#define EN_CMD_ON_LOW_POWER 0x77
#define EN_CMD_SILENT 0x88
#define WD_MODE_CMD 0x03
#define MODE_CMD_HEAD 0x11
#define MODE_CMD_MEMBER 0x00
// -- 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 170
// -- -- received 170 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 68
// -- -- received 68 byte payload
// Remote Test
#define RM_TEST_RESP_LEN 158
#define WD_RM_TEST 0x02
#define RM_TEST_CODE 0x99
// -- Response
#define WD_TIME_STAMP 0x02
#define WD_TIME_STAMP_LEN 8
#define WD_SYSBUS_LOG 0x0A
#define WD_SYSBUS_LOG_LEN 14
#define WD_LINK_LOG 0x18
#define WD_LINK_LOG_LEN 64
#define WD_PHY_LOG 0x58
#define WD_PHY_LOG_LEN 57
#define WD_HARDWARE_ST 0x91
#define WD_HARDWARE_ST_LEN 13
// Remote Test FLJ
#define CMD_FLJ_RM_TEST 0xE6
// -- Request
#define WD_FLJ_RM_TEST 0x02
#define FLJ_RM_TEST_CODE 0x99
// -- Response
#define WD_FLJ_TIME_STAMP 0x02
#define WD_FLJ_TIME_STAMP_LEN 8
#define WD_FLJ_SYSBUS_LOG 0x0A
#define WD_FLJ_SYSBUS_LOG_LEN 14
#define WD_FLJ_LINK_LOG 0x18
#define WD_FLJ_LINK_LOG_LEN 64
#define WD_FLJ_PHY_LOG 0x58
#define WD_FLJ_PHY_LOG_LEN 57
#define WD_FLJ_HARDWARE_ST 0x91
#define WD_FLJ_HARDWARE_ST_LEN 13
// Remote Test LJ
#define CMD_LJ_RM_TEST 0xF6
// -- Request
#define WD_LJ_RM_TEST 0x02
#define LJ_RM_TEST_CODE 0x99
// -- Response
#define WD_LJ_TIME_STAMP 0x02
#define WD_LJ_TIME_STAMP_LEN 8
#define WD_LJ_SYSBUS_LOG 0x0A
#define WD_LJ_SYSBUS_LOG_LEN 14
#define WD_LJ_LINK_LOG 0x18
#define WD_LJ_LINK_LOG_LEN 64
#define WD_LJ_PHY_LOG 0x58
#define WD_LJ_PHY_LOG_LEN 57
#define WD_LJ_HARDWARE_ST 0x91
#define WD_LJ_HARDWARE_ST_LEN 13
// My Production Type
#define MY_PRD_ID PRD_DL_K
/************************** Function Prototypes ******************************/
/**************************** Type Definitions *******************************/
/************************** Variable Definitions *****************************/
// TODO: better approach?
#include "../networking/link_layer/link_layer.h"
#include "../networking/phy_layer/phy_layer.h"
extern L2_INST *linkInstPtr;
extern L2_CONFIG linkConfig;
inline bool Mpc_IsEnable(MPC *instPtr)
{
ASSERT(instPtr != NULL);
return (instPtr->isEnable);
}
inline bool Mpc_IsReqPending(MPC *instPtr)
{
ASSERT(instPtr != NULL);
return (!isCircQueueEmpty(instPtr->rxQueue));
}
inline bool Mpc_IsRsqPending(MPC *instPtr)
{
ASSERT(instPtr != NULL);
return (!isCircQueueEmpty(instPtr->txQueue));
}
inline bool Mpc_IsTxBusy(MPC *instPtr)
{
ASSERT(instPtr != NULL);
return (!instPtr->isTxDone);
}
inline bool Mpc_IsRxBusy(MPC *instPtr)
{
ASSERT(instPtr != NULL);
return (!instPtr->isRxDone);
}
/**
* @brief Apply system configuration
*/
static int32_t Mpc_SystemConfig(MPC *instPtr, uint8_t *msg)
{
PHY_INST *phyRef = linkInstPtr->config.phyInstPtr;
TMC_INST *tmcRef = linkInstPtr->config.tmcInstPtr;
bool reconfig = false;
bool start = false;
if (msg[WD_MODE_CMD] == MODE_CMD_HEAD)
{
// omit unnecessary reconfiguration
if (L2_GetNodeType(linkInstPtr) != L2_NODE_HEAD)
{
// head node config
linkConfig.myType = L2_NODE_HEAD;
linkConfig.myId = 1;
reconfig = true;
}
}
else if (msg[WD_MODE_CMD] == MODE_CMD_MEMBER )
{
// omit unnecessary reconfiguration
if (L2_GetNodeType(linkInstPtr) != L2_NODE_MEMBER)
{
// member node config
linkConfig.myType = L2_NODE_MEMBER;
linkConfig.myId = 2;
reconfig = true;
}
}
else
{
// Ignore current command
DBG_ERROR("Unexpected config command 0x%02X:0x%02X",
WD_MODE_CMD, msg[WD_MODE_CMD]);
return EPARAM;
}
if(msg[WD_EN_CMD] == EN_CMD_ON_HIGH_POWER)
{
// high power config
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_FULL);
start = true;
}
else if(msg[WD_EN_CMD] == EN_CMD_ON_LOW_POWER)
{
// low power config
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_LOW);
start = true;
}
else if(msg[WD_EN_CMD] == EN_CMD_SILENT)
{
// silence config
// TODO: better approach?
start = false;
Linklayer_Halt(linkInstPtr);
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_STANDBY);
TIME_WORD pullTime = {0, 0};
pullTime.int_part = TimeCtrl_GetIntCnt(tmcRef) + 1;
if (Phy_SetTimeWord(phyRef, &pullTime, PHY_TIME_WORD_POLL) != SUCCESS)
{
DBG_ERROR("Physical set pull time failed.\n");
}
Phy_SetupNextSlot(phyRef, PHY_TOR_RX, L1_10KBPS_10MS_FRAME, NULL);
}
if (reconfig == true)
{
Linklayer_Reconfig(linkInstPtr, &linkConfig);
}
if (start == true)
{
Linklayer_Start(linkInstPtr);
}
instPtr->mpcLog.lastConfig[0] = msg[WD_MODE_CMD];
instPtr->mpcLog.lastConfig[1] = msg[WD_EN_CMD];
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Initialize MPC instance.
*
* @param InstPtr A double pointer to MPC instance.
* @param config A pointer to MPC configurations.
*
* @return None.
*
******************************************************************************/
int32_t Mpc_Init(MPC **instPtr, MPC_CONFIG *config)
{
ASSERT(instPtr != NULL);
ASSERT(config != NULL);
MPC_HW_CONFIG mpcHwConfig;
int32_t Status;
(*instPtr) = malloc(sizeof(MPC));
if ((*instPtr) == NULL)
{
return FAILURE;
}
(*instPtr)->rxQueue = NULL;
(*instPtr)->txQueue = NULL;
(*instPtr)->mpchwDesc = NULL;
memcpy(&((*instPtr)->config), config, sizeof(MPC_CONFIG));
memset(&((*instPtr)->mpcLog), 0x00, sizeof(SYSBUSLOG));
memset(&((*instPtr)->linkLog), 0x00, sizeof(LINKLOG));
memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG));
memset(&((*instPtr)->hwState), 0x00, sizeof(HWSTATE));
XBram_Config *bramConfigPtr;
XBram mpcBram;
bramConfigPtr = XBram_LookupConfig(config->bramId);
if (bramConfigPtr == NULL)
{
Status = EDCONF;
goto mpc_init_error;
}
Status = XBram_CfgInitialize(&mpcBram, bramConfigPtr,
bramConfigPtr->CtrlBaseAddress);
if (Status != SUCCESS)
{
goto mpc_init_error;
}
/*
* Execute the BRAM driver selftest.
*/
Status = XBram_SelfTest(&mpcBram, 0);
if (Status != SUCCESS)
{
goto mpc_init_error;
}
mpcHwConfig.txBuffAddr = mpcBram.Config.MemBaseAddress;
mpcHwConfig.rxBuffAddr = mpcBram.Config.MemBaseAddress;
mpcHwConfig.gpioId = config->gpioId;
Status = MpcHw_Init(&((*instPtr)->mpchwDesc), &mpcHwConfig);
if (Status != SUCCESS)
{
Status = ENOMEM;
goto mpc_init_error;
}
if (CircQueueCreate(&((*instPtr)->txQueue), (*instPtr)->config.txQueueMax) == false)
{
Status = ENOMEM;
goto mpc_init_error;
}
if (CircQueueCreate(&((*instPtr)->rxQueue), (*instPtr)->config.rxQueueMax) == false)
{
Status = ENOMEM;
goto mpc_init_error;
}
(*instPtr)->isEnable = false; // nothing received.
(*instPtr)->isRxDone = false; // nothing received.
(*instPtr)->isTxDone = true; // nothing to be sent.
return SUCCESS;
mpc_init_error:
free((*instPtr)->mpchwDesc);
free((*instPtr)->txQueue);
free((*instPtr)->rxQueue);
free(*instPtr);
return Status;
}
/*****************************************************************************/
/**
* @brief Generate a remote test response message.
*
* @param instPtr A pointer to MPC instance.
*
* @return SUCCESS
* error code
*
******************************************************************************/
int32_t Mpc_PendRemoteTest(MPC *instPtr)
{
MPC_HW_FRAME *sysbusRsp;
uint8_t *msg;
if (instPtr->isEnable == false)
{
DBG_ERROR("System is not enabled!\n");
return EIGNORE;
}
sysbusRsp = malloc(sizeof(MPC_HW_FRAME));
if (sysbusRsp == NULL) {
DBG_ERROR("Failed to allocate memory for LJ REMOTE TEST Response!\n");
return ENOMEM;
}
sysbusRsp = malloc(sizeof(MPC_HW_FRAME));
msg = sysbusRsp->data + FRAME_PAYLOAD_POFFSET;
sysbusRsp->len = RM_TEST_RESP_LEN;
if (L2_GetNodeType(linkInstPtr) == L2_NODE_HEAD)
{
// head node config
msg[WD_CMD] = CMD_FLJ_RM_TEST;
}
else
{
msg[WD_CMD] = CMD_LJ_RM_TEST;
}
msg[WD_PRD] = MY_PRD_ID;
TIME_WORD tmWord;
uint64_t time;
TimeCtrl_GetCurrentTime(linkInstPtr->config.tmcInstPtr, &tmWord);
time = (uint64_t)tmWord.int_part * TIME_FRAC_MAX + tmWord.frac_part;
memcpy(msg + WD_TIME_STAMP, &time, WD_TIME_STAMP_LEN);
SysMonitor_GetLinklayerLog(&(instPtr->linkLog));
SysMonitor_GetPhysicalLayerLog(&(instPtr->phyLog));
SysMonitor_GetHardwareStatus(&(instPtr->hwState));
memcpy(msg + WD_SYSBUS_LOG, &(instPtr->mpcLog), WD_SYSBUS_LOG_LEN);
memcpy(msg + WD_LINK_LOG, &(instPtr->linkLog), WD_LINK_LOG_LEN);
memcpy(msg + WD_PHY_LOG, &(instPtr->phyLog), WD_PHY_LOG_LEN);
memcpy(msg + WD_HARDWARE_ST, &(instPtr->hwState.spFpgaVolt), WD_HARDWARE_ST_LEN);
if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){
free(sysbusRsp);
DBG_WARNING("SystemBus::TX Queue overflowed!\n");
return EQUEUE;
}
instPtr->mpcLog.remoteCnt++;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief A handler function. This handler evaluate the message from system
* bus receive queue, and make appropriate response.
*
* @param instPtr A pointer to MPC instance.
*
* @return None
*
******************************************************************************/
int32_t Mpc_HandleCmd(MPC *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
MPC_HW_FRAME *mpcReq;
uint8_t *reqMsg;
if (CircQueuePop(instPtr->rxQueue, (void **)(&mpcReq)) == false)
{
DBG_WARNING("SystemBus::Nothing to be handled.\n");
return EIGNORE;
}
reqMsg = mpcReq->data + FRAME_PAYLOAD_POFFSET;
if (reqMsg[WD_PRD] != MY_PRD_ID && reqMsg[WD_PRD] != PRD_ALL)
{
DBG_WARNING("SystemBus::Production code mismatch!\n");
return EIGNORE;
}
switch (reqMsg[WD_CMD])
{
case CMD_CONFIG:
{
Status = Mpc_SystemConfig(instPtr, reqMsg);
break;
}
default:
{
DBG_ERROR("SystemBus::Unknown command code!\n");
Status = FAILURE;
break;
}
}
free(mpcReq);
return Status;
}
/*****************************************************************************/
/**
* @brief This function send a repose frame from MPC tx queue.
*
* @param instPtr A pointer to MPC instance.
*
* @return None
*
******************************************************************************/
int32_t Mpc_MakeResp(MPC *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
MPC_HW_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 = MpcHw_Send(instPtr->mpchwDesc, sysbusRsp);
free(sysbusRsp);
return Status;
}
/*****************************************************************************/
/**
* @brief This function handles the mpc tx irq events.
*
* @param instPtr A pointer to MPC instance.
*
* @return None
*
******************************************************************************/
int32_t Mpc_TxIrqHandler(MPC *instPtr)
{
ASSERT(instPtr != NULL);
// nothing special...
instPtr->isTxDone = true; // A transmission procedure finished.
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief This function handles the mpc rx irq events.
*
* @param instPtr A pointer to MPC instance.
*
* @return None
*
******************************************************************************/
int32_t Mpc_RxIrqHandler(MPC *instPtr)
{
ASSERT(instPtr != NULL);
int32_t Status;
MPC_HW_FRAME *mpcReq;
instPtr->isRxDone = true; // whether reception successes or not, receiving procedure ended.
mpcReq = malloc(sizeof(MPC_HW_FRAME));
if (mpcReq == NULL)
{
return ENOMEM;
}
Status = MpcHw_Recv(instPtr->mpchwDesc, mpcReq);
if (Status != SUCCESS)
{
goto recv_error;
}
if (CircQueuePush(instPtr->rxQueue, (void *)mpcReq) == 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(mpcReq);
return Status;
}
+71
View File
@@ -0,0 +1,71 @@
/*****************************************************************************/
/**
* Description: MPC 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 __MPC_H_
#define __MPC_H_
/***************************** Include Files *********************************/
#include <stdint.h>
#include <stdbool.h>
#include "mpc_hw.h" // MPC driver
#include "circ_queue.h"
#include "../system_monitor.h"
/************************** Constant Definitions *****************************/
/************************** Data Type Definitions ****************************/
// Definition of MPC instance.
typedef struct
{
uint32_t bramId;
uint32_t gpioId;
uint32_t txQueueMax;
uint32_t rxQueueMax;
} MPC_CONFIG;
typedef struct
{
MPC_CONFIG config;
SYSBUSLOG mpcLog; // mpc log
LINKLOG linkLog; // Link layer log
PHYLOG phyLog; // Physical layer log
HWSTATE hwState; // Hardware status
MPC_HW *mpchwDesc;
CIRC_QUEUE *txQueue;
CIRC_QUEUE *rxQueue;
bool isEnable;
bool isRxDone;
bool isTxDone;
} MPC;
/************************** Function Prototypes ******************************/
int32_t Mpc_Init(MPC **instPtr, MPC_CONFIG *config);
int32_t Mpc_HandleCmd(MPC *instPtr);
int32_t Mpc_PendRemoteTest(MPC *instPtr);
int32_t Mpc_MakeResp(MPC *instPtr);
int32_t Mpc_TxIrqHandler(MPC *instPtr);
int32_t Mpc_RxIrqHandler(MPC *instPtr);
bool Mpc_IsEnable(MPC *instPtr);
bool Mpc_IsReqPending(MPC *instPtr);
bool Mpc_IsRsqPending(MPC *instPtr);
bool Mpc_IsTxBusy(MPC *instPtr);
bool Mpc_IsRxBusy(MPC *instPtr);
#endif //__MPC_H_
+139
View File
@@ -0,0 +1,139 @@
/*****************************************************************************/
/**
* Description: MPC 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 "mpc_hw.h"
#include "common.h"
// Control and status register
#define MODULE_VERSION 0
#define MPC_STATUS 4
#define MPC_SEND_CMD 8
#define MPC_RECV_CNT 12
// Status code
#define MPC_STATUS_TX_BUSY 0x00010000
#define MPC_STATUS_RX_BUSY 0x01000000
// Data buffer register
#define MPC_TXBUFF_MAX 512
#define MPC_RXBUFF_MAX 512
// Frame Data offsets
#define FRAME_HEAD_LOW 0x02
#define FRAME_HEAD_HIGH 0x53
#define FRAME_TAIL_LOW 0x32
#define FRAME_TAIL_HIGH 0x20
#define FRAME_HEAD_LEN 2
#define FRAME_TAIL_LEN 2
#define FRAME_DUMMY_LEN 1 // Dummy
#define FRAME_OVERHEAD_LEN 2 // CheckSum, Dummy and
#define MPC_STATUS_CH 1
#define MPC_CONFIG_CH 2
#define MPC_CONFIG_SEND_TRIG 0x00000002
/*************************** 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 MpcHw_Init(MPC_HW **instPtr, MPC_HW_CONFIG *config)
{
ASSERT(instPtr != NULL);
ASSERT(config != NULL);
uint32_t Status;
(*instPtr) = malloc(sizeof(MPC_HW));
if ((*instPtr) == NULL)
{
return FAILURE;
}
(*instPtr)->config.txBuffAddr = config->txBuffAddr;
(*instPtr)->config.rxBuffAddr = config->rxBuffAddr;
Status = XGpio_Initialize(&((*instPtr)->gpioDesc), config->gpioId);
if (Status != SUCCESS) {
DBG_ERROR("MPC gpio Initialization Failed.\n");
free(*instPtr);
return FAILURE;
}
XGpio_SetDataDirection(&((*instPtr)->gpioDesc), MPC_CONFIG_CH, 0x00000000);
XGpio_SetDataDirection(&((*instPtr)->gpioDesc), MPC_STATUS_CH, 0xFFFFFFFF);
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Send a MPC frame.
*
* @param instPtr A pointer to MPC_HW instance structure.
* @param buff A pointer to send data buffer
* @param dLen A integer indicate the send data buffer length in byte.
*
* @return
*
******************************************************************************/
int MpcHw_Send(MPC_HW *instPtr, MPC_HW_FRAME *frame)
{
ASSERT(instPtr != NULL);
ASSERT(frame != NULL);
uint8_t sendLen;
uint8_t *sendBuff = (uint8_t*) instPtr->config.txBuffAddr;
sendLen = frame->len + FRAME_OVERHEAD_LEN;
if (sendLen > MPC_TXBUFF_MAX || frame->len == 0)
{
return FAILURE;
}
frame->data[0] = FRAME_HEAD_LOW;
frame->data[1] = FRAME_HEAD_HIGH;
memcpy(sendBuff, frame->data, sendLen);
// Start Sending
uint32_t gpioVal = XGpio_DiscreteRead(&(instPtr->gpioDesc), MPC_CONFIG_CH);
gpioVal ^= MPC_CONFIG_SEND_TRIG;
XGpio_DiscreteWrite(&(instPtr->gpioDesc), MPC_CONFIG_CH, gpioVal);
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Get last MPC frame.
*
* @param instPtr A pointer to MPC_HW instance structure.
* @param buff A pointer to receive data buffer.
*
* @return
*
******************************************************************************/
int MpcHw_Recv(MPC_HW *instPtr, MPC_HW_FRAME *frame)
{
ASSERT(instPtr != NULL);
ASSERT(frame != NULL);
uint8_t *recvBuff = (uint8_t *)(instPtr->config.rxBuffAddr);
memcpy(frame->data, recvBuff, MPC_FRAME_MAX);
frame->len = MPC_FRAME_MAX;
frame->isValid = true;
return SUCCESS;
}
+98
View File
@@ -0,0 +1,98 @@
/*****************************************************************************/
/**
* Description: MPC 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 __MPC_HW_H
#define __MPC_HW_H
/**************************** Include Files *****************************/
#include <stdint.h>
#include <stdbool.h>
#include "util.h"
#include "xgpio.h"
#define MPC_FRAME_MAX 256
#define FRAME_PAYLOAD_POFFSET 2 // CheckSum, Dummy and DataLen
/**************************** 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 MPC_HW_mWriteReg(uint32_t BaseAddress, unsigned RegOffset, uint32_t Data)
*
*/
#define MPC_HW_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 MPC_HW_mReadReg(uint32_t BaseAddress, unsigned RegOffset)
*
*/
#define MPC_HW_mReadReg(baseAddr, offset) \
IO_In32((baseAddr) + (offset))
typedef struct
{
uintptr_t txBuffAddr;
uintptr_t rxBuffAddr;
uint32_t gpioId;
} MPC_HW_CONFIG;
typedef struct
{
MPC_HW_CONFIG config;
XGpio gpioDesc;
} MPC_HW;
typedef struct
{
uint16_t len;
uint8_t checkSum;
uint8_t isValid;
uint8_t data[MPC_FRAME_MAX];
} MPC_HW_FRAME;
/************************** Function Prototypes ******************************/
// Instance initial
int MpcHw_Init(MPC_HW **instPtr, MPC_HW_CONFIG *config);
// Send a MPC frame.
int MpcHw_Send(MPC_HW *instPtr, MPC_HW_FRAME *frame);
// Get last MPC frame.
int MpcHw_Recv(MPC_HW *instPtr, MPC_HW_FRAME *frame);
#endif // __MPC_HW_H