462 lines
12 KiB
C
462 lines
12 KiB
C
/*****************************************************************************/
|
|
/**
|
|
* 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 *********************************/
|
|
#include <stdint.h>
|
|
#include "config/app_config.h"
|
|
#include "xscugic.h" // The generic interrupt controller driver component
|
|
#include "xil_exception.h" // ARM Cortex A9 specific exception related APIs
|
|
#include "xgpio.h"
|
|
#include "sleep.h" // Sleep APIs for Cortex A9
|
|
#include "xil_cache.h"
|
|
#include "linklayer/linklayer814.h"
|
|
#include "linklayer/msg_def.h"
|
|
#include "phy_ctrl/phy_ctrl.h"
|
|
#include "bit_array/bit_array.h"
|
|
#include "mpc/mpc_ctrl.h"
|
|
|
|
#ifdef _MPC_CTRL
|
|
#include "./mpc/mpc_ctrl.h"
|
|
#endif
|
|
|
|
#include "hardware/headless.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
L2_CONFIG l2Config = {
|
|
.myType = L2_NODE_MEMBER,
|
|
.isInterHead = false,
|
|
.myId = 2,
|
|
.clustId = 1,
|
|
.headId = 1,
|
|
.bkpHeadId = 1,
|
|
.netScale = 2,
|
|
.phyInstPtr = NULL,
|
|
.tmcInstPtr = NULL};
|
|
|
|
TIMECTRL_CONFIG tmcConfig = {
|
|
.baseAddr = TIME_CONTROLLER_BASEADDR,
|
|
.reset = 10};
|
|
|
|
PHY_CONFIG l1Config = {
|
|
.devId = PHY_DEVICE_ID,
|
|
.txBramId = TXBUFF_BRAM_ID,
|
|
.rxBramId = RXBUFF_BRAM_ID,
|
|
.antBramId = ANTCONFIG_BRAM_ID,
|
|
.baseAddr = PHY_CTRL_BASEADDR};
|
|
MPC_CONFIG mpcConfig = {
|
|
.bramDevId = MPC_PCIE_BRAM_ID,
|
|
.msgLenMax = MPC_BUFFER_LENGTH // byte
|
|
};
|
|
static bool mpcStatusUpAssert = false;
|
|
/************************** Function Prototypes ******************************/
|
|
int SetupInterruptSystem(XScuGic *instPtr, uint32_t devId);
|
|
void PhysicalIntr_Handler(void *callBackRef);
|
|
void PeriodicPull_Handler(void *callBackRef);
|
|
#ifdef _MPC_CTRL
|
|
void MPC_IntrHandler(void *callBackRef);
|
|
#endif
|
|
|
|
/*********************** Driver Instance Definitions **************************/
|
|
TIMECTRL_INST *tmcInstPtr = NULL;
|
|
PHY_INST *phyInstPtr = NULL;
|
|
L2_INST *linkInstPtr = NULL;
|
|
static XScuGic gicInst; // General interrupt controller intance
|
|
// FIXME: Only for test...
|
|
XGpio configGpio; /* The Instance of the GPIO Driver */
|
|
/****************************************************************************/
|
|
/**
|
|
* 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 devId is the XPAR_<GPIO_instance>_DEVICE_ID value from
|
|
* "xparameters.h".
|
|
* @param instPtr is a reference to the XScuGic driver Instance.
|
|
*
|
|
* @return SUCCESS if initialize successful.
|
|
* FAILURE if initialization failed.
|
|
*
|
|
*****************************************************************************/
|
|
int SetupInterruptSystem(XScuGic *instPtr, uint32_t devId)
|
|
{
|
|
XScuGic_Config *configPtr;
|
|
int Status;
|
|
uint32_t intrState;
|
|
// Initialize the GIC instance.
|
|
configPtr = XScuGic_LookupConfig(devId);
|
|
Status = XScuGic_CfgInitialize(instPtr, configPtr,
|
|
configPtr->CpuBaseAddress);
|
|
if (Status != SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
// Perform a self-test to ensure that the hardware was built correctly.
|
|
Status = XScuGic_SelfTest(instPtr);
|
|
if (Status != SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
// Clear any pending interrupt flags
|
|
intrState = XScuGic_CPUReadReg(instPtr, XSCUGIC_INT_ACK_OFFSET);
|
|
XScuGic_CPUWriteReg(instPtr, XSCUGIC_EOI_OFFSET, intrState);
|
|
/*
|
|
* FOR PRIORITY:
|
|
* 0 is highest priority, 0xF8(248) is lowest. There are 32 priority levels
|
|
* supported with a step of 8. Hence the supported priorities are 0, 8, 16,
|
|
* 32, 40 ..., 248.
|
|
*
|
|
* FOR TRIGGER:
|
|
* SFI Read Only b10 always
|
|
* PPI Read Only depending on how the PPIs are configured.
|
|
* b01 Active HIGH level sensitive
|
|
* b11 Rising edge sensitive
|
|
* SPI LSB is read only.
|
|
* b01 Active HIGH level sensitive
|
|
* b11 Rising edge sensitive
|
|
*/
|
|
/* Set the priority of IRQ_F2P[1:1] to 0x00 (highest) and a trigger for a
|
|
* rising edge 0x03.
|
|
*/
|
|
|
|
// Initialize physical layer interrupt.
|
|
XScuGic_SetPriorityTriggerType(instPtr, PHY_INTR_ID, 0x00, 0x03);
|
|
|
|
// Connect the interrupt service routine isr1 to the interrupt controller
|
|
Status = XScuGic_Connect(instPtr, PHY_INTR_ID,
|
|
(Xil_ExceptionHandler)PhysicalIntr_Handler, (void *)phyInstPtr);
|
|
if (Status != SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
// Initialize physical layer interrupt.
|
|
XScuGic_SetPriorityTriggerType(instPtr, PERIODIC_5MS_INTR_ID, 0x00, 0x03);
|
|
|
|
// Connect the interrupt service routine isr1 to the interrupt controller
|
|
Status = XScuGic_Connect(instPtr, PERIODIC_5MS_INTR_ID,
|
|
(Xil_ExceptionHandler)PeriodicPull_Handler, (void *)linkInstPtr);
|
|
if (Status != SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
#ifdef _MPC_CTRL
|
|
// Initialize MPC interrupt.
|
|
XScuGic_SetPriorityTriggerType(instPtr, MPC_RX_DONE_INTR_ID, 0x00, 0x03);
|
|
// Connect the interrupt service routine isr1 to the interrupt controller
|
|
Status = XScuGic_Connect(instPtr, MPC_RX_DONE_INTR_ID,
|
|
(Xil_ExceptionHandler)MPC_IntrHandler, (void *)mpcInstPtr);
|
|
if (Status != XST_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
XScuGic_Enable(instPtr, MPC_RX_DONE_INTR_ID);
|
|
#endif
|
|
|
|
XScuGic_Enable(instPtr, PHY_INTR_ID);
|
|
XScuGic_Enable(instPtr, PERIODIC_5MS_INTR_ID);
|
|
|
|
/* Initialize the exception table and register the interrupt controller
|
|
* handler with the exception table
|
|
*/
|
|
Xil_ExceptionInit();
|
|
|
|
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
|
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
|
|
(void *)instPtr);
|
|
|
|
// Enable non-critical exceptions
|
|
Xil_ExceptionEnable();
|
|
|
|
return Status;
|
|
} // SetupInterruptSystem
|
|
|
|
#ifdef _MPC_CTRL
|
|
void MPC_PCIESentStart()
|
|
{
|
|
uint32_t GpioConfig = XGpio_DiscreteRead(&configGpio, 2);
|
|
GpioConfig ^= 0x00000002;
|
|
XGpio_DiscreteWrite(&configGpio, 2, GpioConfig);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Handler of mater pc contrl interrupt.
|
|
*
|
|
* @param CallBackRef A pointer to corresponding mpcInstPtr instance.
|
|
*
|
|
* @return None.
|
|
*
|
|
******************************************************************************/
|
|
void MPC_IntrHandler(void *CallBackRef)
|
|
{
|
|
MPC_MsgHandler(mpcInstPtr);
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Handler of physical layer interrupt.
|
|
*
|
|
* @param CallBackRef A pointer to corresponding physical layer instance.
|
|
*
|
|
* @return None.
|
|
*
|
|
******************************************************************************/
|
|
void PhysicalIntr_Handler(void *callBackRef)
|
|
{
|
|
uint32_t GpioConfig = XGpio_DiscreteRead(&configGpio, 2);
|
|
if (L2_isDataAvail(linkInstPtr) == true)
|
|
{
|
|
GpioConfig ^= 0x00000001;
|
|
}
|
|
Phy_UpdateState(phyInstPtr);
|
|
if (phyInstPtr->TOR.curr == PHY_TOR_TX)
|
|
{
|
|
switch (phyInstPtr->frameType.curr)
|
|
{
|
|
case L1_1M2BPS_5MS_FRAME:
|
|
mpcRecord->frame1Sent++;
|
|
break;
|
|
case L1_200KBPS_5MS_FRAME:
|
|
mpcRecord->frame2Sent++;
|
|
break;
|
|
case L1_40KBPS_10MS_FRAME:
|
|
mpcRecord->frame3Sent++;
|
|
break;
|
|
case L1_40KBPS_20MS_FRAME:
|
|
mpcRecord->frame4Sent++;
|
|
break;
|
|
case L1_10KBPS_20MS_FRAME:
|
|
mpcRecord->frame5Sent++;
|
|
break;
|
|
case L1_2KBPS_100MS_FRAME:
|
|
mpcRecord->frame6Sent++;
|
|
break;
|
|
case L1_10KBPS_10MS_FRAME:
|
|
mpcRecord->frame7Sent++;
|
|
break;
|
|
case L1_2KBPS_20MS_FRAME:
|
|
mpcRecord->frame8Sent++;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (phyInstPtr->TOR.last == PHY_TOR_RX && phyInstPtr->isFrameSync)
|
|
{
|
|
switch (phyInstPtr->frameType.last)
|
|
{
|
|
case L1_1M2BPS_5MS_FRAME:
|
|
mpcRecord->frame1Recv++;
|
|
break;
|
|
case L1_200KBPS_5MS_FRAME:
|
|
mpcRecord->frame2Recv++;
|
|
break;
|
|
case L1_40KBPS_10MS_FRAME:
|
|
mpcRecord->frame3Recv++;
|
|
break;
|
|
case L1_40KBPS_20MS_FRAME:
|
|
mpcRecord->frame4Recv++;
|
|
break;
|
|
case L1_10KBPS_20MS_FRAME:
|
|
mpcRecord->frame5Recv++;
|
|
break;
|
|
case L1_2KBPS_100MS_FRAME:
|
|
mpcRecord->frame6Recv++;
|
|
break;
|
|
case L1_10KBPS_10MS_FRAME:
|
|
mpcRecord->frame7Recv++;
|
|
break;
|
|
case L1_2KBPS_20MS_FRAME:
|
|
mpcRecord->frame8Recv++;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
XGpio_DiscreteWrite(&configGpio, 2, GpioConfig);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/**
|
|
* 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: %ld\n", Status);
|
|
_nop_();
|
|
}
|
|
|
|
if (linkInstPtr->slotNum.next % DATA_STORE_INTERVAL == 1)
|
|
{
|
|
mpcStatusUpAssert = true;
|
|
mpcRecord->frame1Cnt = mpcRecord->frame1Recv - mpcRecord->frame1CntLast;
|
|
mpcRecord->frame2Cnt = mpcRecord->frame2Recv - mpcRecord->frame2CntLast;
|
|
mpcRecord->frame3Cnt = mpcRecord->frame3Recv - mpcRecord->frame3CntLast;
|
|
mpcRecord->frame4Cnt = mpcRecord->frame4Recv - mpcRecord->frame4CntLast;
|
|
mpcRecord->frame5Cnt = mpcRecord->frame5Recv - mpcRecord->frame5CntLast;
|
|
mpcRecord->frame6Cnt = mpcRecord->frame6Recv - mpcRecord->frame6CntLast;
|
|
mpcRecord->frame7Cnt = mpcRecord->frame7Recv - mpcRecord->frame7CntLast;
|
|
mpcRecord->frame8Cnt = mpcRecord->frame8Recv - mpcRecord->frame8CntLast;
|
|
|
|
// Store last time received frame number
|
|
mpcRecord->frame1CntLast = mpcRecord->frame1Recv;
|
|
mpcRecord->frame2CntLast = mpcRecord->frame2Recv;
|
|
mpcRecord->frame3CntLast = mpcRecord->frame3Recv;
|
|
mpcRecord->frame4CntLast = mpcRecord->frame4Recv;
|
|
mpcRecord->frame5CntLast = mpcRecord->frame5Recv;
|
|
mpcRecord->frame6CntLast = mpcRecord->frame6Recv;
|
|
mpcRecord->frame7CntLast = mpcRecord->frame7Recv;
|
|
mpcRecord->frame8CntLast = mpcRecord->frame8Recv;
|
|
}
|
|
} // PhyIntr_Handler
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @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)
|
|
{
|
|
int Status;
|
|
Status = HARDWARE_initialize();
|
|
if (Status == SUCCESS)
|
|
{
|
|
DBG_PRINT("Hardware Init SUCCESS! \n");
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINT("Hardware Init FAILED! \n");
|
|
return Status;
|
|
}
|
|
|
|
Status = XGpio_Initialize(&configGpio, XPAR_CONFIG_GPIO_DEVICE_ID);
|
|
if (Status != SUCCESS)
|
|
{
|
|
DBG_PRINT("Config Gpio Initialization Failed\n");
|
|
return FAILURE;
|
|
}
|
|
XGpio_SetDataDirection(&configGpio, 1, 0xFFFFFFFF);
|
|
XGpio_SetDataDirection(&configGpio, 2, 0x00000000);
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Init physical layer
|
|
Status = Phy_InstInit(&phyInstPtr, &l1Config);
|
|
if (Status == SUCCESS)
|
|
{
|
|
DBG_PRINT("PhyCtrl Init SUCCESS! \n");
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINT("PhyCtrl Init FAILED! \n");
|
|
return Status;
|
|
}
|
|
|
|
// Update l2 config
|
|
l2Config.phyInstPtr = phyInstPtr;
|
|
l2Config.tmcInstPtr = tmcInstPtr;
|
|
|
|
Status = Linklayer_Init(&linkInstPtr, &l2Config);
|
|
if (Status == SUCCESS)
|
|
{
|
|
DBG_PRINT("LinkLayer Init SUCCESS! \n");
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINT("Linklayer Init FAILED! \n");
|
|
return Status;
|
|
}
|
|
|
|
// Init MPC
|
|
Status = MPC_Init(&mpcInstPtr, &mpcConfig);
|
|
if (Status == SUCCESS)
|
|
{
|
|
DBG_PRINT("MPC Init SUCCESS! \n");
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINT("MPC Init FAILED! \n");
|
|
return Status;
|
|
}
|
|
|
|
// Initialize GIC.
|
|
Status = SetupInterruptSystem(&gicInst, SCUGIC_DEVICE_ID);
|
|
if (Status == SUCCESS)
|
|
{
|
|
DBG_PRINT("Intc Init SUCCESS! \n");
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINT("Intc Init FAILED! \n");
|
|
return Status;
|
|
}
|
|
|
|
DBG_PRINT("Starting Physical Layer...");
|
|
Phy_Start(phyInstPtr);
|
|
|
|
// FIXME: only for debug, linklayer should be start by MPC
|
|
Linklayer_Start(linkInstPtr);
|
|
|
|
while (true)
|
|
{
|
|
if (mpcStatusUpAssert == true)
|
|
{
|
|
mpcStatusUpAssert = false;
|
|
if (linkInstPtr->buffSwitch == 0)
|
|
{
|
|
MPC_StateUpload(mpcInstPtr, linkInstPtr->mgmtMsgRecvBuff1, linkInstPtr->mgmtMsgRecvCnt1,
|
|
linkInstPtr->svcMsgRecvBuff1, linkInstPtr->svcMsgRecvCnt1, &(linkInstPtr->mgmtNetFSM->mgmtMsgLog));
|
|
}
|
|
else
|
|
{
|
|
MPC_StateUpload(mpcInstPtr, linkInstPtr->mgmtMsgRecvBuff0, linkInstPtr->mgmtMsgRecvCnt0,
|
|
linkInstPtr->svcMsgRecvBuff0, linkInstPtr->svcMsgRecvCnt0, &(linkInstPtr->mgmtNetFSM->mgmtMsgLog));
|
|
}
|
|
}
|
|
}
|
|
} // main
|