forked from 0xha0/datalink_repo
Initial version.
This commit is contained in:
@@ -0,0 +1,779 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Description: main.c
|
||||
*
|
||||
* Date: 2021-11-13 13:19
|
||||
* Last Edit Time: [2023-04-23 21:32]
|
||||
*
|
||||
* Revisions: Rev 0.0
|
||||
* History:
|
||||
* [2021-11-13]: Initial edition.
|
||||
* [2022-03-28]: Add bit error test mode.
|
||||
* [2023-04-23]: Bug fixed,
|
||||
*
|
||||
* Copyright(c) 2021 Beijing Institute of Technology.
|
||||
* Lab of Communication and Networking
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
// Standard
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
// Xilinx
|
||||
#include "xintc.h" // The generic interrupt controller driver component
|
||||
#include "xil_exception.h" // ARM Cortex A9 specific exception related APIs
|
||||
#include "sleep.h" // Sleep APIs for Cortex A9
|
||||
#include "xgpio.h" // GPIO APIs for Cortex A9
|
||||
#include "xbram.h"
|
||||
#include "xtmrctr.h"
|
||||
#include "xsysmon.h"
|
||||
|
||||
// ADI Drivers
|
||||
#include "dev_profile/dev_profile.h"
|
||||
#include "adi_noos/drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "adi_noos/drivers/platform/gpio_extra.h"
|
||||
|
||||
// User
|
||||
#include "common.h"
|
||||
#include "error.h"
|
||||
#include "config/app_config.h"
|
||||
#include "c2c_bridge/c2c_bridge.h"
|
||||
#include "phy_ctrl/phy_ctrl.h"
|
||||
#include "circ_queue/circ_queue.h"
|
||||
#include "inter_comm/inter_comm.h"
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
int32_t SetupInterruptSystem(XIntc* instPtr, uint32_t devId);
|
||||
int32_t XADC_Init(XSysMon* instPtr, uint16_t devId);
|
||||
int32_t ScuTimerInit(XTmrCtr* instPtr, uint16_t devId);
|
||||
|
||||
// Utility functions
|
||||
int32_t Intercom_C2cRecvData(void* buffPtr, int32_t dataLen);
|
||||
int32_t Intercom_C2cSendData2Addr(void* buffPtr, int32_t dataLen, uint16_t subaddrId);
|
||||
|
||||
// IRQ Handlers
|
||||
void C2c_RxIntrHandler(void* callBackRef);
|
||||
void C2c_TxIntrHandler(void* callBackRef);
|
||||
void Timer_IntrHandler(void* CallBackRef);
|
||||
void PhyIntr_Handler(void *callBackRef);
|
||||
/************************** Constant Definitions *****************************/
|
||||
#define C2C_EXTRA_LEN (sizeof(C2C_EXTRA) + COMMON_CRC_LEN)
|
||||
|
||||
C2C_CONFIG c2cConfig = {
|
||||
.capacity = C2C_BUFF_MAX,
|
||||
.dmaConfig = {
|
||||
.devId = C2C_AXI_DMA_DEVICE_ID,
|
||||
.transMax = C2C_BUFF_MAX,
|
||||
.defaultTransLen = C2C_BUFF_MAX,
|
||||
.timeoutTh = 500
|
||||
}
|
||||
};
|
||||
|
||||
INTER_COMM_CONFIG intrCommConfig = {
|
||||
.data_recv = Intercom_C2cRecvData,
|
||||
.data_send = Intercom_C2cSendData2Addr,
|
||||
.phyInstPtr = NULL
|
||||
};
|
||||
|
||||
PHY_CONFIG phyConfig = {
|
||||
.devId = 0,
|
||||
.baseAddr = PHY_CTRL_BASEADDR,
|
||||
.txBramId = PHY_TX_BRAM_BUFF_ID,
|
||||
.rxBramId = PHY_RX_BRAM_BUFF_ID,
|
||||
.antBramId = PHY_ANT_CONFIG_BRAM_ID
|
||||
|
||||
};
|
||||
|
||||
struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = SPI_ENGINE_CS_DELAY,
|
||||
.data_width = SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
struct xil_gpio_init_param xil_gpio_param = {
|
||||
.type = GPIO_PS,
|
||||
.device_id = GPIO_DEVICE_ID
|
||||
};
|
||||
|
||||
/*********************** Driver Instance Definitions **************************/
|
||||
static XIntc intcInst; // General interrupt controller instance
|
||||
static XSysMon SysMonInst;
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
static XTmrCtr axiTimeInst; // PS scu timer
|
||||
static bool isSendRemotCheckAsserted = false;//true when 1s comes
|
||||
#endif
|
||||
static bool isPhyUploadAsserted = false;//true when 1s comes
|
||||
static CIRC_QUEUE *c2cRecvQueue;
|
||||
static PHY_INST* phyInstPtr = NULL;
|
||||
static INTER_COMM_INST* intrCommInstPtr = NULL;
|
||||
static C2C_EXTRA* c2cExtraBuffPtr = NULL;
|
||||
|
||||
// For AD9361
|
||||
struct ad9516_dev *ad9516_inst;
|
||||
struct ad9361_reg_dev *ad9361_1_reg_inst;
|
||||
struct ad9361_reg_dev *ad9361_2_reg_inst;
|
||||
struct ad9361_rf_phy *ad9361_phy;
|
||||
|
||||
/* Helper function for AD9361 IO control*/
|
||||
static int XGpio_WritePin(XGpio *InstPtr, uint32_t Channel, u32 Pin, uint8_t Value){
|
||||
ASSERT(Pin <= 31 && Pin >=0 );
|
||||
ASSERT(InstPtr != NULL);
|
||||
ASSERT(InstPtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
ASSERT((Channel == 1) || ((Channel == 2) && (InstPtr->IsDual == TRUE)));
|
||||
u32 CurrValue = XGpio_DiscreteRead(InstPtr, Channel);
|
||||
CurrValue = (Value == 0)? (CurrValue & (~(0x00000001 << Pin))) : (CurrValue | (0x00000001 << Pin));
|
||||
XGpio_DiscreteWrite(InstPtr, Channel, CurrValue);
|
||||
return SUCCESS;
|
||||
}// XGpio_WritePin
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function dose a hardware initialization.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return SUCCESS if initialize successful.
|
||||
* XST_FAILURE if initialization failed.
|
||||
*
|
||||
*****************************************************************************/
|
||||
static int Hardware_Initialize(void){
|
||||
int Status;
|
||||
XGpio Gpio;
|
||||
Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
XGpio_SetDataDirection(&Gpio, GPIO_BANK_OUT, 0x00000000); // Bank 1 output
|
||||
XGpio_SetDataDirection(&Gpio, GPIO_BANK_IN, 0xFFFFFFFF); // Bank 0 inputT_FAILURE;
|
||||
|
||||
/**********************************************************/
|
||||
/****************** AD9516 Configuration ******************/
|
||||
/**********************************************************/
|
||||
Status = ad9516_init(&ad9516_inst, &ad9516_default_init_param);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_POWEDOWN_B, 1);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 1);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_RESET_B, 0);
|
||||
mdelay(200);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_RESET_B, 1);
|
||||
for(int i = 0; i < ad9516_default_config_len; i++){
|
||||
Status = ad9516_write(ad9516_inst, ad9516_default_config[i].addr, ad9516_default_config[i].value);
|
||||
if (ad9516_default_config[i].addr == 0x0000){
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rd_back;
|
||||
Status = ad9516_read(ad9516_inst, 0x0003, &rd_back);
|
||||
do
|
||||
{
|
||||
Status = ad9516_read(ad9516_inst, 0x001F, &rd_back);
|
||||
}
|
||||
while((rd_back & 0x01) != 0x01);
|
||||
|
||||
/**********************************************************/
|
||||
/***************** AD9361-1 Configuration *****************/
|
||||
/**********************************************************/
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_RX_FIFO_RST, 1);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0);
|
||||
|
||||
ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param);
|
||||
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_RESET_B, 0);
|
||||
mdelay(200);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_RESET_B, 1);
|
||||
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_ENABLE, 0);
|
||||
ad9361_reg_config(ad9361_1_reg_inst);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_ENABLE, 1);
|
||||
|
||||
/**********************************************************/
|
||||
/***************** AD9361-2 Configuration *****************/
|
||||
/**********************************************************/
|
||||
ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param);
|
||||
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_RESET_B, 0);
|
||||
mdelay(200);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_RESET_B, 1);
|
||||
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_ENABLE, 0);
|
||||
ad9361_reg_config(ad9361_2_reg_inst);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_ENABLE, 1);
|
||||
|
||||
// sync clock output
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 0);
|
||||
mdelay(500);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 1);
|
||||
|
||||
// SYNC BBPLL and DIGITAL SAMPLING CLOCKS
|
||||
ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param);
|
||||
ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param);
|
||||
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin
|
||||
mdelay(500);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0);
|
||||
mdelay(2000);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin
|
||||
mdelay(500);
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08);
|
||||
|
||||
XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_RX_FIFO_RST, 0);
|
||||
|
||||
return SUCCESS;
|
||||
}// Hardware_Initialize
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Initialize ScuTimer instance.
|
||||
*
|
||||
* @param InstPtr A pointer to QSPI instance
|
||||
*
|
||||
* @param DevId ScuTimer instance device ID
|
||||
*
|
||||
* @return SUCCESS
|
||||
* XST_FAILURE
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t ScuTimerInit(XTmrCtr* instPtr, uint16_t devId) {
|
||||
int Status = SUCCESS;
|
||||
XTmrCtr_Config *configPtr;
|
||||
/*
|
||||
* Initialize the Scu Private Timer driver.
|
||||
*/
|
||||
configPtr = XTmrCtr_LookupConfig(devId);
|
||||
/*
|
||||
* This is where the virtual address would be used, this example
|
||||
* uses physical address.
|
||||
*/
|
||||
Status = XTmrCtr_Initialize(instPtr, configPtr->DeviceId);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
/*
|
||||
* Perform a self-test to ensure that the hardware was built correctly.
|
||||
*/
|
||||
Status = XTmrCtr_SelfTest(instPtr, XTC_TIMER_0);
|
||||
|
||||
return Status;
|
||||
}// ScuTimerInit
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Initialize XADC instance.
|
||||
*
|
||||
* @param InstPtr A pointer to QSPI instance
|
||||
*
|
||||
* @param DevId ScuTimer instance device ID
|
||||
*
|
||||
* @return SUCCESS
|
||||
* XST_FAILURE
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t XADC_Init(XSysMon* instPtr, uint16_t devId) {
|
||||
int Status = SUCCESS;
|
||||
XSysMon_Config *configPtr;
|
||||
|
||||
/*
|
||||
* Initialize the Scu Private Timer driver.
|
||||
*/
|
||||
configPtr = XSysMon_LookupConfig(devId);
|
||||
if (configPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
XSysMon_CfgInitialize(instPtr, configPtr, configPtr->BaseAddress);
|
||||
|
||||
//safe mode
|
||||
XSysMon_SetSequencerMode(instPtr, XSM_SEQ_MODE_SAFE);
|
||||
|
||||
//enable channels
|
||||
XSysMon_SetSeqChEnables(instPtr, XSM_SEQ_CH_TEMP|XSM_SEQ_CH_VCCINT);
|
||||
|
||||
/* Set the ADCCLK frequency equal to 1/32 of System clock for the System
|
||||
* Monitor/ADC in the Configuration Register 2.
|
||||
*/
|
||||
XSysMon_SetAdcClkDivisor(instPtr, 32);
|
||||
//mode
|
||||
XSysMon_SetSequencerMode(instPtr, XSM_SEQ_MODE_CONTINPASS);
|
||||
|
||||
/*
|
||||
* Wait till the End of Sequence occurs
|
||||
*/
|
||||
XSysMon_GetStatus(instPtr); /* Clear the old status */
|
||||
while ((XSysMon_GetStatus(instPtr) & XSM_SR_EOS_MASK) !=
|
||||
XSM_SR_EOS_MASK);
|
||||
|
||||
return Status;
|
||||
}// XADC_Init
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* 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 deviceID is the XPAR_<GPIO_instance>_DEVICE_ID value from
|
||||
* "xparameters.h".
|
||||
* @param XIntc is a reference to the XScuGic driver Instance.
|
||||
*
|
||||
* @return SUCCESS if initialize successful.
|
||||
* XST_FAILURE if initialization failed.
|
||||
*
|
||||
*****************************************************************************/
|
||||
int32_t SetupInterruptSystem(XIntc* instPtr, uint32_t devId){
|
||||
int Status = SUCCESS;
|
||||
// Initialize the GIC instance.
|
||||
Status = XIntc_Initialize(instPtr, devId);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Perform a self-test to ensure that the hardware was built correctly.
|
||||
Status = XIntc_SelfTest(instPtr);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Hook up interrupt service routine */
|
||||
Status = XIntc_Connect(instPtr, PHY_INTR_ID,
|
||||
(XInterruptHandler) PhyIntr_Handler, (void *) instPtr);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
/* Enable the interrupt vector at the interrupt controller */
|
||||
XIntc_Enable(instPtr, PHY_INTR_ID);
|
||||
|
||||
/* Hook up interrupt service routine */
|
||||
Status = XIntc_Connect(instPtr, C2C_TX_INTR_ID,
|
||||
(XInterruptHandler) C2c_TxIntrHandler, (void *) instPtr);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
Status = XIntc_Connect(instPtr, C2C_RX_INTR_ID,
|
||||
(XInterruptHandler) C2c_RxIntrHandler, (void *) instPtr);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
/* Enable the interrupt vector at the interrupt controller */
|
||||
XIntc_Enable(instPtr, C2C_TX_INTR_ID);
|
||||
XIntc_Enable(instPtr, C2C_RX_INTR_ID);
|
||||
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
// ScuTimer interrupt
|
||||
Status = XIntc_Connect(instPtr, SCUTIMER_INTR_ID,
|
||||
(Xil_ExceptionHandler) Timer_IntrHandler,
|
||||
(void *) &axiTimeInst);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
XIntc_Enable(instPtr, SCUTIMER_INTR_ID);
|
||||
#endif
|
||||
|
||||
/* Start the interrupt controller such that interrupts are recognized
|
||||
* and handled by the processor
|
||||
*/
|
||||
Status = XIntc_Start(instPtr, XIN_REAL_MODE);
|
||||
if (Status != SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Initialize the exception table and register the interrupt controller
|
||||
* handler with the exception table
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
(void *) instPtr);
|
||||
|
||||
// Enable non-critical exceptions
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return SUCCESS;
|
||||
} // SetupInterruptSystem
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This is a utility function to implement a C2C data transmission.
|
||||
*
|
||||
* @param buffPtr a pointer to data buffer, which need to be 2 byte aligned.
|
||||
* @param dataLen length of data needs to be sent.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*****************************************************************************/
|
||||
int32_t Intercom_C2cRecvData(void* buffPtr, int32_t buffSize){
|
||||
int Status;
|
||||
uint8_t* c2cRecvDataPtr;
|
||||
|
||||
if(isCircQueueEmpty(c2cRecvQueue)){
|
||||
return EIGNORE;
|
||||
}
|
||||
else{
|
||||
Status = CircQueuePop(c2cRecvQueue, (void**)(&c2cRecvDataPtr));
|
||||
if(Status == false || c2cRecvDataPtr == NULL){
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t recvLen = IO_In32((uintptr_t)(c2cRecvDataPtr + C2C_DLEN_OFFSET)) - C2C_HEADER_LEN;
|
||||
memcpy(buffPtr, c2cRecvDataPtr + C2C_PLOAD_OFFSET, recvLen);
|
||||
|
||||
// Check if buffer is big enough.
|
||||
if(buffSize < recvLen - C2C_EXTRA_LEN){
|
||||
DBG_ERROR("Buffer too small.\r\n",);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Check CRC
|
||||
if(CrcCheck(buffPtr + recvLen - C2C_EXTRA_LEN, C2C_EXTRA_LEN) == true){
|
||||
// Store received data
|
||||
memcpy(c2cExtraBuffPtr, buffPtr + recvLen - C2C_EXTRA_LEN, sizeof(C2C_EXTRA));
|
||||
}
|
||||
else{
|
||||
DBG_ERROR("C2C extra crc check failed.\r\n");
|
||||
return ECRC;
|
||||
}
|
||||
return SUCCESS;
|
||||
} //Intercom_C2cRecvData
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This is a utility function to implement a C2C data transmission.
|
||||
*
|
||||
* @param buffPtr a pointer to data buffer, which need to be 2 byte aligned.
|
||||
* @param dataLen length of data needs to be sent.
|
||||
* @param subaddrId taget subAddress
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*****************************************************************************/
|
||||
int32_t Intercom_C2cSendData2Addr(void* buffPtr, int32_t dataLen, uint16_t subaddrId){
|
||||
int Status;
|
||||
if(dataLen > (C2C_BUFF_MAX - (sizeof(C2C_EXTRA)+COMMON_CRC_LEN))){
|
||||
return FAILURE;
|
||||
}
|
||||
c2cExtraBuffPtr->glinkSubAddr = subaddrId;
|
||||
memcpy((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET), buffPtr, dataLen);
|
||||
memcpy((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET + dataLen), c2cExtraBuffPtr, sizeof(C2C_EXTRA));
|
||||
Status = AppendCrc((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET + dataLen), C2C_EXTRA_LEN);
|
||||
if(Status != SUCCESS){
|
||||
DBG_ERROR("C2C extra data crc append error, with error code: %d.\r\n", Status);
|
||||
return Status;
|
||||
}
|
||||
Status = C2c_BlockingSendData(c2cInstPtr, (uint8_t *)C2C_TXBUFF_ADDR_BASE, dataLen + C2C_EXTRA_LEN);
|
||||
// FIXME
|
||||
usleep(1);
|
||||
return Status;
|
||||
}// Intercom_C2cSendData2Addr
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* 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 callBackRef is the SCUGIC instance pointer.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t c2cRecvCnt = 0;
|
||||
void C2c_RxIntrHandler(void *callBackRef) {
|
||||
int32_t Status;
|
||||
Status = C2c_RecvIrqHandler(c2cInstPtr);
|
||||
if(Status != SUCCESS){
|
||||
_nop_();
|
||||
}
|
||||
CircQueuePush(c2cRecvQueue, (void *)c2cInstPtr->lastRxBuff);
|
||||
uint8_t* nextRxBuff = (c2cInstPtr->lastRxBuff >= C2C_RXBUFF_ADDR_BASE + (C2C_BUFF_NUM-1)*C2C_BUFF_SIZE) ?
|
||||
(uint8_t*)C2C_RXBUFF_ADDR_BASE : (uint8_t*)(c2cInstPtr->lastRxBuff + C2C_BUFF_SIZE);
|
||||
C2c_RecvData(c2cInstPtr, nextRxBuff, C2C_BUFF_SIZE);
|
||||
c2cRecvCnt ++;
|
||||
return;
|
||||
} // C2cRxIntr_Handler
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* 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 callBackRef is the SCUGIC instance pointer.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t c2cSendvCnt = 0;
|
||||
void C2c_TxIntrHandler(void *callBackRef) {
|
||||
int32_t Status;
|
||||
Status = C2c_SendIrqHandler(c2cInstPtr);
|
||||
if(Status != SUCCESS){
|
||||
_nop_();
|
||||
}
|
||||
c2cSendvCnt ++;
|
||||
return;
|
||||
} // C2cTxIntr_Handler
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* 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 callBackRef is the SCUGIC instance pointer.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t phyIntrCnt = 0;
|
||||
void PhyIntr_Handler(void *callBackRef) {
|
||||
phyIntrCnt++;
|
||||
Phy_UpdateState(phyInstPtr);
|
||||
// Check last frame.
|
||||
if (Phy_IsFrameValid(phyInstPtr) == true) {
|
||||
Phy_RetrieveRecvData(phyInstPtr, intrCommInstPtr->phyRecvBuff);
|
||||
isPhyUploadAsserted = true;
|
||||
}
|
||||
return;
|
||||
} // PhyIntr_Handler
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Handler of ScuTimer interrupt.
|
||||
*
|
||||
* @param CallBackRef A pointer to corresponding ScuTimer instance.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
void Timer_IntrHandler(void* CallBackRef) {
|
||||
ASSERT(CallBackRef != NULL);
|
||||
XTmrCtr *TimerInstPtr = (XTmrCtr *) CallBackRef;
|
||||
XTmrCtr_InterruptHandler(TimerInstPtr);
|
||||
isSendRemotCheckAsserted = true;
|
||||
return;
|
||||
} //Timer_IntrHandler
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @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;
|
||||
|
||||
/*** Initialize Hardware AD9361 AD9516 ***/
|
||||
Status = Hardware_Initialize();
|
||||
if (Status == SUCCESS) {
|
||||
DBG_PRINT("Hardware Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_PRINT("Hardware Init FAILED! \r\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
/*** Initialize Remote Test Updater Module ***/
|
||||
//-- ScuTimer Initialization
|
||||
Status = ScuTimerInit(&axiTimeInst, SCUTIMER_DEVICE_ID);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("ScuTimer Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("ScuTimer Init FAILED, ErrorCode: 0x%08X\r\n, Status");
|
||||
return Status;
|
||||
}
|
||||
XTmrCtr_InitHw(&axiTimeInst);
|
||||
|
||||
//-- XADC Initialization
|
||||
Status = XADC_Init(&SysMonInst, SYSMON_DEVICE_ID);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("XADC Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("XADC Init FAILED, ErrorCode: 0x%08X\r\n, Status");
|
||||
return Status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** Initialize C2C bridge ***/
|
||||
//-- Buffer Initialization
|
||||
Status = CircQueueCreate(&c2cRecvQueue, C2C_BUFF_NUM);
|
||||
if (Status == true) {
|
||||
DBG_PRINT("CircQueue Creat SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_PRINT("CircQueue Creat FAILED! \r\n");
|
||||
return EUNEXP;
|
||||
}
|
||||
|
||||
c2cExtraBuffPtr = (C2C_EXTRA*) malloc(sizeof(C2C_EXTRA));
|
||||
if ((c2cExtraBuffPtr) == NULL) {
|
||||
DBG_PRINT("c2cExtraBuffPtr allocate FAILED! \r\n");
|
||||
return EALLOC;
|
||||
}
|
||||
|
||||
//-- C2C Hardware Initialization
|
||||
Status = C2c_Init(&c2cInstPtr, &c2cConfig);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("C2C bridge Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("C2C bridge Init FAILED, ErrorCode: %d\r\n, Status");
|
||||
return Status;
|
||||
}
|
||||
|
||||
//-- C2C Intercommunication Module Initialization
|
||||
intrCommConfig.phyInstPtr = phyInstPtr;
|
||||
Status = InterComm_Init(&intrCommInstPtr, &intrCommConfig);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("nterComm Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("nterComm Init FAILED, ErrorCode: %d\r\n, Status");
|
||||
return Status;
|
||||
}
|
||||
|
||||
//-- Start C2C Receiving Process
|
||||
Status = C2c_RecvData(c2cInstPtr, (uint8_t*)C2C_RXBUFF_ADDR_BASE, C2C_BUFF_SIZE);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_PRINT("C2C start listening SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_PRINT("C2C start listening FAILED! \r\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
//-- Enable C2C Interrupts
|
||||
Status = C2c_IrqEnable(c2cInstPtr);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("Glink interrupts enable SUCCESS!\r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("Glink interrupts enable FAILED, with error code: %d.\r\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*** Initialize Physical Layer Control Module ***/
|
||||
//-- Physical Layer Hardware Initialization
|
||||
Status = Phy_InstInit(&phyInstPtr, &phyConfig);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_PRINT("PhyCtrl Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_PRINT("PhyCtrl Init FAILED! \r\n");
|
||||
return Status;
|
||||
}
|
||||
//-- Set Physical Layer Mode
|
||||
Status = Phy_SetMode(phyInstPtr, PHY_MODE_PULL);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_PRINT("Physical Mode %u Setup SUCCESS! \r\n", PHY_MODE_LISTEN);
|
||||
}
|
||||
else {
|
||||
DBG_PRINT("Physical Mode %u Setup FAILED! \r\n", PHY_MODE_LISTEN);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*** Initialize GIC ***/
|
||||
Status = SetupInterruptSystem(&intcInst, INTC_DEVICE_ID);
|
||||
if (Status == SUCCESS) {
|
||||
DBG_INFO("Intc Init SUCCESS! \r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("Intc Init FAILED, ErrorCode: %d\r\n, Status");
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
// Start Remote Control Timer
|
||||
XTmrCtr_SetLoadReg(axiTimeInst.BaseAddress, XTC_TIMER_0, TIMER_COUNT_MAX);
|
||||
XTmrCtr_SetControlStatusReg(axiTimeInst.BaseAddress, XTC_TIMER_0,
|
||||
XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK |
|
||||
XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK);
|
||||
XTmrCtr_Start(&axiTimeInst,XTC_TIMER_0);
|
||||
XTmrCtr_Start(&axiTimeInst,XTC_TIMER_0);
|
||||
#endif
|
||||
|
||||
DBG_PRINT("Starting Physical Layer...");
|
||||
Phy_Start(phyInstPtr);
|
||||
|
||||
/*** Main Routine - Handling C2C Handshake ***/
|
||||
while(true){
|
||||
// Upload physical frame data if new frame received.
|
||||
if(isPhyUploadAsserted && !C2c_IsSendBusy(c2cInstPtr)){
|
||||
isPhyUploadAsserted = false;
|
||||
Status = InterComm_PhyDataUpload(intrCommInstPtr);
|
||||
if(Status != SUCCESS){
|
||||
DBG_PRINT("####\tInterComm L1 data upload finished with code: %d", Status);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle received intercom frame if received.
|
||||
else if(isCircQueueEmpty(c2cRecvQueue) == false){
|
||||
Status = InterComm_RecvMsg(intrCommInstPtr);
|
||||
if(Status != SUCCESS){
|
||||
DBG_PRINT("####\tInterComm L1 data upload finished with code: %d.\r\n", Status);
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
Status = InterComm_MsgHandler(intrCommInstPtr);
|
||||
if(Status != SUCCESS){
|
||||
DBG_PRINT("####\tInterComm message handler finished with code: %d\n\r", Status);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef GLINK_REMOTE_TEST_ENABLE
|
||||
// Update remote monitoring info if needed.
|
||||
else if(isSendRemotCheckAsserted && !C2c_IsSendBusy(c2cInstPtr)){
|
||||
isSendRemotCheckAsserted = false;
|
||||
Status = InterComm_SendRemotCheck(intrCommInstPtr, &SysMonInst, c2cExtraBuffPtr);
|
||||
if(Status != SUCCESS){
|
||||
DBG_PRINT("####\tInterComm L1 data upload finished with code: %d", Status);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}// Waiting for interrupt
|
||||
|
||||
// uint8_t * sendBuffPtr = (uint8_t *)C2C_TXBUFF_ADDR_BASE;
|
||||
// uint32_t cnt = 0;
|
||||
// while(cnt < 10240){
|
||||
// if(!C2c_IsSendBusy(c2cInstPtr)){
|
||||
// for(int i = 0; i < 512; i++){
|
||||
// sendBuffPtr[i] = i + cnt;
|
||||
// }
|
||||
// C2c_BlockingSendData(c2cInstPtr, sendBuffPtr, 512);
|
||||
// cnt++;
|
||||
// }
|
||||
// }
|
||||
// while(true);
|
||||
} // main
|
||||
Reference in New Issue
Block a user