/*****************************************************************************/ /** * Description: main.c * * Date: 2021-11-13 13:19 * Last Editors: Fan Hao * Last Edit Time: [2022-03-28 20:32] * * Revisions: Rev 0.0 * History: * [2021-11-13]: Initial edition. * [2022-03-28]: Add bit error test mode. * * Copyright(c) 2021 Beijing Institute of Technology. * Lab of Communication and Networking * ******************************************************************************/ /***************************** Include Files *********************************/ // Standard #include #include #include // Xilinx #include "sleep.h" #include "xil_cache.h" #include "xscugic.h" #include "xscutimer.h" #include "xgpiops.h" #include "drivers/platform/xilinx_irq.h" #include "drivers/platform/xilinx_timer.h" // App #include "common.h" #include "error.h" #include "timer.h" #include "config/app_config.h" #include "dev_profile/dev_profile.h" #include "mpc/mpc.h" #include "networking/phy_layer/phy_layer.h" #include "networking/link_layer/link_layer.h" // RF-Driver #include "hardware/headless.h" #include "hardware/platform_drivers.h" /************************** Function Prototypes ******************************/ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr); void Phy_IntrHandler(void *context); void PeriodicPull_Handler(void *callBackRef); void ScuTimer_IntrHandler(void *context); void Mpc_RxIntrHandler(void *context); void Mpc_TxIntrHandler(void *context); /************************** Constant Definitions *****************************/ struct callback_desc phy_callback_desc = { .callback = Phy_IntrHandler, .ctx = NULL }; struct callback_desc periodicpull_callback_desc = { .callback = PeriodicPull_Handler, .ctx = NULL }; struct callback_desc mpc_rx_callback_desc = { .callback = Mpc_RxIntrHandler, .ctx = NULL }; struct callback_desc mpc_tx_callback_desc = { .callback = Mpc_TxIntrHandler, .ctx = NULL }; struct callback_desc scutm_callback_desc = { .callback = ScuTimer_IntrHandler, .ctx = NULL }; L2_CONFIG linkConfig = { .myType = L2_NODE_HEAD, .clustId = 1, .myId = 1, .headId = 1, .bkpHeadId = 0, .netScale = 2, .phyInstPtr = NULL, // physical layer reference .tmcInstPtr = NULL }; // L2_CONFIG linkConfig = { // .myType = L2_NODE_MEMBER, // .clustId = 1, // .myId = 2, // .headId = 1, // .bkpHeadId = 0, // .netScale = 2, // .phyInstPtr = NULL, // physical layer reference // .tmcInstPtr = NULL // }; static PHY_CONFIG phyConfig = { .devId = 0, .baseAddr = PHY_BASEADDR, .antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID, .antInfoBramId = -1, .txBramId = PHY_TXBUFF_BRAM_DEVICE_ID, .rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID, .hwXadcId = PHY_HW_XADC_DEVICE_ID, .get_clk_state = NULL, .get_ad_lock_state = NULL, .get_ad0_temp = NULL, .get_ad1_temp = NULL }; TMC_CONFIG tmcConfig = { .baseAddr = TIME_CONTROLLER_BASEADDR, .reset = 10 }; static MPC_CONFIG mpcConfig = { .bramId = MPC_BRAM_ID, .gpioId = MPC_GPIO_ID, .txQueueMax = 16, .rxQueueMax = 16 }; #ifdef APP_EMULATE_DATA uint8_t testDataLj[] = { 0xEA, 0xDF, 0x3F, 0x27, 0xCE, 0x9B, 0xE6, 0x3F, 0xB5, 0xA3, 0x38, 0x47, 0x1D, 0x1D, 0xFA, 0x3F, 0x39, 0xB4, 0xC8, 0x76, 0xBE, 0xAB, 0x8E, 0x40, 0xC9, 0xE8, 0x80, 0x24, 0xEC, 0xCB, 0x13, 0x40, 0x37, 0x38, 0x7F, 0x22, 0x72, 0x06, 0xF0, 0x01, 0x00, 0x00, 0xB8, 0xAA, 0x08, 0x47, 0x1E, 0xC6, 0xB0, 0x47, 0x54, 0xFD, 0xEB, 0x45, 0xA1, 0x8A, 0x86, 0x44, 0x43, 0xB6, 0xC8, 0x44, 0x4E, 0x19, 0xA8, 0x42 }; uint8_t testDataFlj[] = { 0xFD, 0x1E, 0xA5, 0x22, 0x72, 0x02, 0x5A, 0x02, 0x00, 0x00, 0x81, 0x97, 0x39, 0x3F, 0xF1, 0xF4, 0xC0, 0x3F, 0x27, 0xF1, 0x65, 0x44, 0x53, 0x5C, 0xD3, 0x3F, 0xB5, 0x24, 0xA6, 0x22, 0x72, 0x02, 0x83, 0x01, 0x00, 0x00, 0xFC, 0xE0, 0x44, 0x47, 0xB7, 0x83, 0x35, 0x47, 0xA4, 0xBF, 0xE5, 0xC4, 0xE8, 0xDC, 0xD1, 0x44, 0x5D, 0x5D, 0xE7, 0x44, 0x7D, 0x1B, 0xE8, 0xC1, 0x60, 0x97, 0x57, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x86, 0xA6, 0x22, 0x72, 0x02, 0xA5, 0x02, 0x00, 0x00, 0x97, 0x4E, 0xB5, 0x47, 0xC4, 0x2A, 0xB0, 0x47, 0x2D, 0x00, 0x21, 0xC5, 0x8A, 0x85, 0xD1, 0x44, 0x23, 0xFD, 0xC8, 0x44, 0xA1, 0xC4, 0xEA, 0xC1, 0x91, 0x4E, 0x71, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xAD, 0xA6, 0x22, 0x72, 0x02, 0xA5, 0x02, 0x00, 0x00, 0xCD, 0x07, 0xD6, 0x47, 0x1D, 0xA4, 0xCE, 0x47, 0x6E, 0x61, 0x33, 0xC5, 0x85, 0x55, 0xD1, 0x44, 0x9C, 0x16, 0xBD, 0x44, 0x36, 0xC0, 0xEB, 0xC1, 0xF0, 0xFF, 0x5B, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x25, 0x03, 0x00 }; #endif /************************** Function Prototypes ******************************/ static struct irq_ctrl_desc *intcDescPtr; // General interrupt controller descriptor static struct timer_desc *logTmPtr; static MPC *mpcDescPtr; static PHY_INST *phyInstPtr; static TMC_INST *tmcInstPtr = NULL; L2_INST *linkInstPtr; /****************************************************************************/ /** * This function is responsible for initializing the SCUGIC instance, looking * for the device configuration based on the unique device ID, initializing a * SCUGIC instance, and initialize the interrupt at IRQ_F2P[0:0] * * @param intcDesc A pointer to INTC descriptor * * @return SUCCESS if initialize successful. * FAILURE if initialization failed. * *****************************************************************************/ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) { int32_t Status; struct xil_irq_desc *xil_dev; Status = irq_ctrl_init(&descPtr, &intc_init_param); if (Status != SUCCESS) { DBG_ERROR("Intc Init FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } xil_dev = (struct xil_irq_desc *)(descPtr->extra); // Clear any pending interrupt flags uint32_t intrState = XScuGic_CPUReadReg((XScuGic *)(xil_dev->instance), XSCUGIC_INT_ACK_OFFSET); XScuGic_CPUWriteReg((XScuGic *)(xil_dev->instance), XSCUGIC_EOI_OFFSET, intrState); /* Initialize physical layer interrupt. */ Status = irq_trigger_level_set(descPtr, PHY_INTR_ID, IRQ_EDGE_RISING); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } // Set highest interrupt priority Status = irq_set_priority(descPtr, PHY_INTR_ID, 0x08); 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, PHY_INTR_ID, &phy_callback_desc); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } /* Initialize linklayer layer interrupt. */ Status = irq_trigger_level_set(descPtr, PERIODIC_5MS_INTR_ID, IRQ_EDGE_RISING); if (Status != SUCCESS) { DBG_ERROR("PERIODIC_5MS_INTR_ID trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } // Set highest interrupt priority Status = irq_set_priority(descPtr, PERIODIC_5MS_INTR_ID, 0x00); if (Status != SUCCESS) { DBG_ERROR("PERIODIC_5MS_INTR_ID 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, PERIODIC_5MS_INTR_ID, &periodicpull_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, MPC_RX_INTR_ID); irq_enable(descPtr, MPC_TX_INTR_ID); irq_enable(descPtr, SCUTIMER_INTR_ID); // Enable Exceptions Status = irq_global_enable(descPtr); if (Status != SUCCESS) { DBG_ERROR("IRQ global enable FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } return SUCCESS; } // SetupInterruptSystem /****************************************************************************/ /** * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] * tells CPU that the data in OCM is ready! * * @param context * * @return None. * *****************************************************************************/ void Phy_IntrHandler(void *context) { Phy_UpdateState(phyInstPtr); } // PhyIntr_Handler /****************************************************************************/ /** * Handler of periodic 5ms interrupt * * @param callBackRef is the linklayer instance pointer. * * @return None. * *****************************************************************************/ void PeriodicPull_Handler(void *callBackRef) { int32_t Status; Status = Linklayer_Proc(linkInstPtr); if (Status != SUCCESS) { DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status); _nop_(); } } // PeriodicPull_Handler /*****************************************************************************/ /** * @brief Handler of System Bus RX done interrupt. * * @param context * * @return None. * ******************************************************************************/ void Mpc_RxIntrHandler(void *context) { int32_t Status; Status = Mpc_RxIrqHandler(mpcDescPtr); if (Status != SUCCESS) { DBG_ERROR("Mpc_RxIrqHandler exit with error code %" PRId32 ",\n", Status); } } /*****************************************************************************/ /** * @brief Handler of System Bus TX done interrupt. * * @param context * * @return None. * ******************************************************************************/ void Mpc_TxIntrHandler(void *context) { int32_t Status; Status = Mpc_TxIrqHandler(mpcDescPtr); if (Status != SUCCESS) { DBG_ERROR("Mpc_TxIrqHandler exit with error code %" PRId32 ",\n", Status); } } /*****************************************************************************/ /** * @brief Handler of ScuTimer interrupt. * * @param context * * @return None. * ******************************************************************************/ void ScuTimer_IntrHandler(void *context) { struct xil_timer_desc *xdesc; xdesc = (struct xil_timer_desc *)(logTmPtr->extra); if (XScuTimer_IsExpired((XScuTimer *)xdesc->instance)) { // Refresh log Phy_RefreshHwSate(phyInstPtr); if (TimeCtrl_GetIntCnt(tmcInstPtr) - phyInstPtr->lastLogTime >= PHY_LOG_EXPIRE) { Phy_UpdateLogging(phyInstPtr); } if (Mpc_IsEnable(mpcDescPtr)) { if (Mpc_PendRemoteTest(mpcDescPtr) != SUCCESS) { DBG_ERROR("Failed to apply remote test.\n"); } #ifdef APP_EMULATE_DATA if (L2_GetNodeType(linkInstPtr) == L2_NODE_HEAD) { SysMonitor_UpdateSendPayload(testDataFlj, PAYLOAD_LEN_FLJ_TX); } else { SysMonitor_UpdateSendPayload(testDataLj, PAYLOAD_LEN_LJ_TX); } #endif } XScuTimer_ClearInterruptStatus((XScuTimer *)xdesc->instance); } else { DBG_WARNING("UNEXPECTED CALL of ScuTimer_IntrHandler\n"); } } /*****************************************************************************/ /** * @brief Main function, initialize all the device needed, initialize * interrupt system, halt in while(1) wait for event interrupt. * * @param None. * * @return * ******************************************************************************/ int main(void) { int32_t Status; DBG_PRINT("Application Version: %2d.%2d.%4d.\n", _APP_VER_MAIN, _APP_VER_MINOR, _APP_VER_PATCH); /* System Monitor Initialize */ Status = SysMonitor_Init(); if (Status == SUCCESS) { DBG_PRINT("System monitor Init SUCCESS! \n"); } else { DBG_PRINT("System monitor Init FAILED! \n"); return Status; } Status = HARDWARE_initialize(); if (Status == SUCCESS) { DBG_PRINT("Hardware Init SUCCESS! \n"); } else { DBG_PRINT("Hardware Init FAILED! \n"); return Status; } // Init time controller Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); if (Status == SUCCESS) { DBG_PRINT("TmcCtrl Init SUCCESS! \n"); } else { DBG_PRINT("TmcCtrl Init FAILED! \n"); return Status; } /* Physical Layer Initialize */ Status = Phy_Init(&phyInstPtr, &phyConfig); if (Status == SUCCESS) { DBG_PRINT("Physical layer Init SUCCESS! \n"); } else { DBG_PRINT("Physical layer FAILED! \n"); return Status; } /* Link Layer Initialize */ linkConfig.phyInstPtr = phyInstPtr; linkConfig.tmcInstPtr = tmcInstPtr; Status = Linklayer_Init(&linkInstPtr, &linkConfig); if (Status == SUCCESS) { DBG_PRINT("LinkLayer Init SUCCESS! \n"); } else { DBG_PRINT("Linklayer Init FAILED! \n"); 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); if (Status != SUCCESS) { DBG_ERROR("SCU Timer init FAILED, with error code: %" PRId32 "\n", Status); return Status; } /* interrupts Initialize */ Status = SetupInterruptSystem(intcDescPtr); if (Status == SUCCESS) { DBG_INFO("Interrupt system setup SUCCESS!\n"); } else { DBG_ERROR("Interrupt system setup FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } // Start System Monitor logging. timer_start(logTmPtr); DBG_PRINT("Physical started...\n"); Phy_Start(phyInstPtr); 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