iLLD_TC27xC  1.0
How to use the ERAY Interface driver?
Collaboration diagram for How to use the ERAY Interface driver?:

Preparation

Include Files

Include following header file into your C code:

#include <eray_commands.h>

Variables

// global variables
static IfxEray_Eray eray;
volatile unsigned receivedDataCounter;

Defines

// Number of tested communication cycles
#define NUMBER_ERAY_COMM_CYCLES 8

Interrupt Handler Installation

Define priorities for the Interrrupt handler. This is normally done in the Ifx_IntPrioDef.h file:

#define IFX_ERAY_INT0_PRIO 1
#define IFX_ERAY_INT1_PRIO 2
#define IFX_ERAY_NDAT0_PRIO 3
#define IFX_ERAY_NDAT1_PRIO 4
#define IFX_ERAY_MBSC0_PRIO 5
#define IFX_ERAY_MBSC1_PRIO 6

Add the interrupt service routine to your C code. It has to call the ERAY interrupt handler:

// ISR routines for interrupt handling
void ERAY_irqInt0Handler();
void ERAY_irqInt1Handler();
void ERAY_irqNdat0Handler();
void ERAY_irqNdat1Handler();
void ERAY_irqMbsc0Handler();
void ERAY_irqMbsc1Handler();
IFX_INTERRUPT(eray0Int0ISR, 0, IFX_ERAY_INT0_PRIO)
{
ERAY_irqInt0Handler();
}
IFX_INTERRUPT(eray0Int1ISR, 0, IFX_ERAY_INT1_PRIO)
{
ERAY_irqInt1Handler();
}
IFX_INTERRUPT(eray0Ndat0ISR, 0, IFX_ERAY_NDAT0_PRIO)
{
ERAY_irqNdat0Handler();
}
IFX_INTERRUPT(eray0Ndat1ISR, 0, IFX_ERAY_NDAT1_PRIO)
{
ERAY_irqNdat1Handler();
}
IFX_INTERRUPT(eray0Mbsc0ISR, 0, IFX_ERAY_MBSC0_PRIO)
{
ERAY_irqMbsc0Handler();
}
IFX_INTERRUPT(eray0Mbsc1ISR, 0, IFX_ERAY_MBSC1_PRIO)
{
ERAY_irqMbsc1Handler();
}

Finally install the interrupt handlers in your initialisation function:

// install interrupt handler
IfxCpu_Irq_installInterruptHandler(&eray0Int0ISR, IFX_ERAY_INT0_PRIO);
IfxCpu_Irq_installInterruptHandler(&eray0Int1ISR, IFX_ERAY_INT1_PRIO);
IfxCpu_Irq_installInterruptHandler(&eray0Ndat0ISR, IFX_ERAY_NDAT0_PRIO);
IfxCpu_Irq_installInterruptHandler(&eray0Ndat1ISR, IFX_ERAY_NDAT1_PRIO);
IfxCpu_Irq_installInterruptHandler(&eray0Mbsc0ISR, IFX_ERAY_MBSC0_PRIO);
IfxCpu_Irq_installInterruptHandler(&eray0Mbsc1ISR, IFX_ERAY_MBSC1_PRIO);
// enable all cpu0 interrupts

Module Initialisation

First ensure that the ERAY PLL is configured to output a 80 MHz clock for the ERAY module:

// initialize Eray PLL
clib_ver_printf("Initialize ERAY PLL\n");
{
IfxScuCcu_ErayPllConfig ErayPllConfig;
IfxScuCcu_initErayPllConfig(&ErayPllConfig);
result |= IfxScuCcu_initErayPll(&ErayPllConfig);
}

Thereafter initialize the module:

// create module config
IfxEray_Eray_Config erayModuleConfig;
#if TEST_ERAY1
clib_ver_printf("Initialize ERAY1\n");
IfxEray_Eray_initModuleConfig(&erayModuleConfig, &MODULE_ERAY1);
#else
clib_ver_printf("Initialize ERAY0\n");
IfxEray_Eray_initModuleConfig(&erayModuleConfig, &MODULE_ERAY0);
#endif
// ISR priorities
erayModuleConfig.interrupt.int0Priority = IFX_ERAY_INT0_PRIO;
erayModuleConfig.interrupt.int1Priority = IFX_ERAY_INT1_PRIO;
erayModuleConfig.interrupt.ndat0Priority = IFX_ERAY_NDAT0_PRIO;
erayModuleConfig.interrupt.ndat1Priority = IFX_ERAY_NDAT1_PRIO;
erayModuleConfig.interrupt.mbsc0Priority = IFX_ERAY_MBSC0_PRIO;
erayModuleConfig.interrupt.mbsc1Priority = IFX_ERAY_MBSC1_PRIO;
// init module
IfxEray_Eray_initModule( &eray, &erayModuleConfig );

Node Initialisation

The node initialisation can be done in the same function.

// get ERAY node default configuration
// configuration changes for interaction with external testbench element
{
// only for simulation: start external ERAY node
{
TbeMessage reply;
// start ERay Testbench Element
sendMessage(MSG_ID_TESTBENCH_ERAY, CMD_ERAY_TBE_START, 0 );
receiveMessageBlockingFrom(MSG_ID_TESTBENCH_ERAY, reply);
}
{
// SUCC1
}
{
// PRTC1
prtc1->transmissionStartTime = 10;
}
{
// PRTC2
prtc2->receiveWakeupIdleTime = 18;
prtc2->receiveWakeupLowTime = 18;
prtc2->transmitWakeupIdleTime = 180;
prtc2->transmitWakeupLowTime = 60;
}
{
// SUCC2
succ2->listenTimeOut = 2500;
}
{
// GTU
gtu->gtu09Config.idleDynamicSlots = IfxEray_IdleDynamicSlots_1; // bug: not set by IfxEray_setDynamicSlots
}
}
// Messages
// Frame header
IfxEray_Header header[2] = {
// fid cyc cha chb buffer direction ppit transmission mode mbi pl dp startupfr syncfr
};
// slot buffer
IfxEray_SlotConfig slot[2] = {
// header data stxrh buffNum
{ TRUE, TRUE, TRUE, 0 },
{ TRUE, FALSE, FALSE, 1 },
};
for(int i=0; i < 2; ++i) {
nodeConfig.messageRAMConfig.header[i] = &header[i];
nodeConfig.messageRAMConfig.slotControl[i] = &slot[i];
nodeConfig.messageRAMConfig.data[i] = NULL_PTR;
}
#if TEST_ERAY1
// channel A pins
const IfxEray_Eray_NodeA nodeAPins = {
&IfxEray1_RXDA0_P14_8_IN, &IfxEray1_TXDA_P14_10_OUT,
&IfxEray1_TXENA_P14_9_OUT
};
// channel B pins
const IfxEray_Eray_NodeB nodeBPins = {
&IfxEray1_RXDB0_P14_7_IN, &IfxEray1_TXDB_P14_5_OUT,
&IfxEray1_TXENB_P14_6_OUT
};
#else
// channel A pins
const IfxEray_Eray_NodeA nodeAPins = {
};
// channel B pins
const IfxEray_Eray_NodeB nodeBPins = {
};
#endif
const IfxEray_Eray_Pins pins = { (IfxEray_Eray_NodeA *)&nodeAPins, (IfxEray_Eray_NodeB *)&nodeBPins };
nodeConfig.pins = (IfxEray_Eray_Pins *)&pins;
// ERAY node initialisation with supplied configuration
IfxEray_Eray_Node_init(&eray, &nodeConfig);
// set interrupt outputs for data and message buffers
IfxEray_Eray_setNewDataInterruptDestination(&eray, 0, 0); // New Data #0 -> NDAT0
IfxEray_Eray_setNewDataInterruptDestination(&eray, 1, 1); // New Data #1 -> NDAT1
IfxEray_Eray_setMessageBufferInterruptDestination(&eray, 0, 0); // Message Buffer #0 -> MBSC0
IfxEray_Eray_setMessageBufferInterruptDestination(&eray, 1, 1); // Message Buffer #1 -> MBSC1
clib_ver_printf("Send wakeup pattern\n");
// send wakeup pattern on default configured channel ( IfxEray_Channel_a )
IfxEray_PocState pocState;
do {
pocState = IfxEray_Eray_getPocState( &eray );
if ( pocState != IfxEray_PocState_wakeupListen ) {
}
} while ( pocState != IfxEray_PocState_wakeupListen );
// allow node to cold-start and wait until cold-start is successful
while( !IfxEray_Eray_allowColdStart(&eray) );
// start the communication in cluster and wait until communication is successfull
// wait until communication Controller enters NORMAL_ACTIVE or NORMAL_PASSIVE state, exit if communication Controller enters HALT state.
do {
pocState = IfxEray_Eray_getPocState( &eray );
// if communication Controller enters HALT state, break the loop.
if( pocState == IfxEray_PocState_halt) {
break;
}
} while( !((pocState == IfxEray_PocState_normalActive) || (pocState == IfxEray_PocState_normalPassive)) );
// enter ALL_SLOTS mode when Communication Controller is in NORMAL_ACTIVE or NORMAL_PASSIVE state only.
while ( !IfxEray_Eray_setPocAllSlots(&eray) );
}

Transactions

unsigned prevReceivedDataCounter = 0;
while( 1 ) {
if( receivedDataCounter != prevReceivedDataCounter ) {
prevReceivedDataCounter = receivedDataCounter;
clib_ver_printf("Received %d packets", receivedDataCounter);
if( receivedDataCounter >= NUMBER_ERAY_COMM_CYCLES )
break;
}
};

Interrupt Service Handlers

The ISR has to be implemented in the application. Following templates can be used to react on the events:

void ERAY_irqInt0Handler()
{
clib_ver_note(1); // for debugging in simulation: notify Int0
Ifx_ERAY_EIR ErrIntStat = IfxEray_Eray_getErrorInterrupts( &eray );
Ifx_ERAY_SIR StatusIntStat = IfxEray_Eray_getStatusInterrupts( &eray );
if(StatusIntStat.B.SDS)
{
// SDS must be cleared for getting the next interrupt
}
if(StatusIntStat.B.CYCS)
{
// CYCS must be cleared for getting the next interrupt
}
if(StatusIntStat.B.SUCS)
{
// SUCS must be cleared for getting the next interrupt
}
if(StatusIntStat.B.TIBC)
{
// TIBC must be cleared for getting the next interrupt
}
if(ErrIntStat.B.MHF)
{
// clear flag MHF
}
}
void ERAY_irqInt1Handler()
{
clib_ver_note(2); // for debugging in simulation: notify Int1
// TOBC must be cleared for getting the next interrupt
}
void ERAY_irqNdat0Handler()
{
clib_ver_note(3); // for debugging in simulation: notify Ndat0
}
void ERAY_irqNdat1Handler()
{
clib_ver_note(4); // for debugging in simulation: notify Ndat1
// message received in slot1 buffer?
{
// read data
uint32 data[2];
{
config.headerReceived = TRUE;
config.dataReceived = TRUE;
config.swapRequested = TRUE;
config.bufferIndex = 1;
IfxEray_Eray_receiveFrame(&eray, &config);
IfxEray_Eray_readData(&eray, data, 2*2);
}
// display received data
clib_ver_data(data[0]);
clib_ver_data(data[1]);
// store received data
if( receivedDataCounter < NUMBER_ERAY_COMM_CYCLES ) {
receivedData[receivedDataCounter][0] = data[0];
receivedData[receivedDataCounter][1] = data[1];
}
++receivedDataCounter;
// put some new data into slot0
++data[0];
++data[1];
{
config.dataTransfered = TRUE;
config.bufferIndex = 0;
IfxEray_Eray_writeData(&eray, data, 2*2);
IfxEray_Eray_transmitFrame(&eray, &config);
}
}
}
void ERAY_irqMbsc0Handler()
{
clib_ver_note(5); // for debugging in simulation: notify Mbsc0
}
void ERAY_irqMbsc1Handler()
{
clib_ver_note(6); // for debugging in simulation: notify Mbsc1
}