diff --git a/df_datalink_ge/src/config/app_config.h b/df_datalink_ge/src/config/app_config.h index 252159a..1588fad 100644 --- a/df_datalink_ge/src/config/app_config.h +++ b/df_datalink_ge/src/config/app_config.h @@ -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 diff --git a/df_datalink_ge/src/dev_profile/timer_profile.c b/df_datalink_ge/src/dev_profile/timer_profile.c index 53aac51..343806e 100644 --- a/df_datalink_ge/src/dev_profile/timer_profile.c +++ b/df_datalink_ge/src/dev_profile/timer_profile.c @@ -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 }; diff --git a/df_datalink_ge/src/main.c b/df_datalink_ge/src/main.c index caf49e3..33b35e1 100644 --- a/df_datalink_ge/src/main.c +++ b/df_datalink_ge/src/main.c @@ -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 diff --git a/df_datalink_ge/src/mpc/mpc.c b/df_datalink_ge/src/mpc/mpc.c new file mode 100644 index 0000000..2aacd40 --- /dev/null +++ b/df_datalink_ge/src/mpc/mpc.c @@ -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 +#include +#include +#include +#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; +} diff --git a/df_datalink_ge/src/mpc/mpc.h b/df_datalink_ge/src/mpc/mpc.h new file mode 100644 index 0000000..71d165b --- /dev/null +++ b/df_datalink_ge/src/mpc/mpc.h @@ -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 +#include +#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_ diff --git a/df_datalink_ge/src/mpc/mpc_hw.c b/df_datalink_ge/src/mpc/mpc_hw.c new file mode 100644 index 0000000..459bbe5 --- /dev/null +++ b/df_datalink_ge/src/mpc/mpc_hw.c @@ -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 +#include +#include +#include +#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; +} + diff --git a/df_datalink_ge/src/mpc/mpc_hw.h b/df_datalink_ge/src/mpc/mpc_hw.h new file mode 100644 index 0000000..8a8e26d --- /dev/null +++ b/df_datalink_ge/src/mpc/mpc_hw.h @@ -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 +#include +#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