nai can int ether
Edit this on GitLab
nai can int ether
Explanation
About the Sample Application Code This C code is associated with North Atlantic Industries' (NAI) systems and is used to interact with their embedded function modules via Ethernet Communication, particularly focusing on handling CAN (Controller Area Network) interrupts and configuring IDR (Interrupt Driven Response) commands. Below is a detailed explanation of the code:
Common Include Files The sample code begins with importing several header files which provide necessary functions and definitions for the application:
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
These headers are for various functionalities such as interrupts, board access and display utilities.
#include "nai_can_int_ether.h"
#include "nai_can_cfg.h"
#include "functions/naibrd_can.h"
#include "maps/nai_map_can.h"
#include "advanced/nai_ether_adv.h"
These files are specific for CAN and Ethernet configurations and functionalities.
Functions
setupIDRConfiguration
This function is responsible for constructing the Ethernet commands as part of the IDR (Interrupt Driven Response) configuration. It initializes and sets the IDR configuration for CAN communication on the board.
void setupIDRConfiguration(CanConfig inputCANConfig, IDRConfig* inputIDRConfig, bool_t bGen4CanIDRCommands){
// Function implementation to clear, initialize, and set IDR configurations.
}
Parameters:
- CanConfig inputCANConfig
: Configuration settings for CAN.
- IDRConfig* inputIDRConfig
: Pointer to IDR configuration settings.
- bool_t bGen4CanIDRCommands
: Boolean to determine the type of CAN IDR commands.
InitCANRxIDRCommands
This function configures the commands for the IDR to handle CAN Rx (Receive) interrupts.
void InitCANRxIDRCommands(CanConfig inputCANConfig, IDRConfig* inputIDRConfig, bool_t bGen4CanIDRCommands){
// Function implementation to initialize IDR commands for handling CAN Rx interrupts.
}
Parameters:
- Same as in setupIDRConfiguration
.
MakeCANRxReadRegsCommand
This function creates an Ethernet read register command to be stored in the IDR. It reads the latched status interrupt register module.
void MakeCANRxReadRegsCommand(IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex){
// Function implementation to construct and store the read register command.
}
Parameters:
- IDRConfig* inputIDRConfig
: Pointer to IDR configuration settings.
- uint32_t boardAddress
: Address of the board.
- int32_t moduleOffset
: Module offset value.
- bool_t bGen4Ether
: Boolean indicating the Ethernet generation.
- uint16_t startIndex
: Starting index for the command.
MakeCANRxReadRegsFIFOStatus
This function constructs an Ethernet read register command to read the FIFO status register for a specified channel.
void MakeCANRxReadRegsFIFOStatus(CanConfig inputCANConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex){
// Function implementation to construct and store the FIFO status register read command.
}
Parameters:
- Same as in MakeCANRxReadRegsCommand
.
MakeCANRxReadFIFOCommand
This function constructs an Ethernet read FIFO command to read the FIFO buffer register for a specified channel.
void MakeCANRxReadFIFOCommand(CanConfig inputCANConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex){
// Function implementation to construct and store the FIFO read command.
}
Parameters:
- Same as in MakeCANRxReadRegsCommand
.
MakeCANRxWriteRegsCommand
This function constructs an Ethernet write register command to clear the interrupt status register on the module and re-arm the interrupts.
void MakeCANRxWriteRegsCommand(CanConfig inputCANConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex){
// Function implementation to construct and store the write register command.
}
Parameters:
- Same as in MakeCANRxReadRegsCommand
.
HandleCANEtherInterrupt
This function processes and handles the IDR response messages when a CAN data interrupt occurs. It interprets the response, updates the FIFO status, and logs necessary information.
void HandleCANEtherInterrupt(uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id){
// Function implementation to handle and interpret the IDR response messages.
}
Parameters:
- uint16_t msglen
: Length of the message.
- uint8_t msg[]
: IDR response message array.
- uint16_t tdr_idr_id
: IDR ID.
getInterruptDataEthernet
This function extracts and processes the FIFO data from the interrupting CAN channel.
void getInterruptDataEthernet(uint8_t msg[], uint16_t msglen, FIFO* fifo){
// Function implementation to get and process the FIFO data.
}
Parameters:
- uint8_t msg[]
: IDR response message array.
- uint16_t msglen
: Length of the message.
- FIFO* fifo
: Pointer to FIFO structure.
This code represents a well-structured approach to configuring and handling CAN interrupts via Ethernet communication using NAI embedded modules.
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common CAN Sample Program include files */
#include "nai_can_int_ether.h"
#include "nai_can_cfg.h"
/* naibrd include files */
#include "functions/naibrd_can.h"
#include "maps/nai_map_can.h"
#include "advanced/nai_ether_adv.h"
/**************************************************************************************************************/
/**
<summary>
Constructs the ethernet commands that are part of the IDR. Configures the IDR on the board.
</summary>
*/
/**************************************************************************************************************/
void setupIDRConfiguration(CanConfig inputCANConfig,IDRConfig* inputIDRConfig,bool_t bGen4CanIDRCommands){
int32_t cardIndex = inputIDRConfig->cardIndex;
uint16_t protocol = inputIDRConfig->protocol;
uint16_t port = inputIDRConfig->port;
uint8_t* ipAddress = inputIDRConfig->ipAddress;
uint8_t ipLength = inputIDRConfig->ipLength;
int32_t vector = NAI_CAN_INTERRUPT_VECTOR;
uint8_t *commands = inputIDRConfig->commands; /*Stores the ethernet commands that are going to be executed as part of the IDR*/
uint16_t *cmdcount = &inputIDRConfig->cmdcount;
uint16_t *cmdlength = &inputIDRConfig->cmdlength;
check_status(naibrd_Ether_ClearIDRConfig(cardIndex,(uint16_t)DEF_ETHERNET_CAN_IDR_ID)); /* clear IDR config */
InitCANRxIDRCommands(inputCANConfig,inputIDRConfig,bGen4CanIDRCommands);
check_status(naibrd_Ether_SetIDRConfig(cardIndex,(uint16_t)DEF_ETHERNET_CAN_IDR_ID,protocol,ipLength,ipAddress,port,vector,*cmdcount,*cmdlength,commands));
}
/**************************************************************************************************************/
/**
<summary>
This function configures the IDR (Interrupt Driven Response) commands when a CAN Rx interrupt occurs.
There are four Ethernet commands that will be processed by the board when a CAN Rx interrupt occurs.
</summary>
*/
/**************************************************************************************************************/
void InitCANRxIDRCommands(CanConfig inputCANConfig,IDRConfig* inputIDRConfig,bool_t bGen4CanIDRCommands)
{
nai_status_t status = NAI_SUCCESS;
uint16_t msgIndex = 0;
uint32_t boardAddress;
uint32_t moduleOffset;
boardAddress = 0;
status = check_status(naibrd_GetModuleOffset(inputCANConfig.cardIndex, inputCANConfig.module, &moduleOffset));
if(status == NAI_SUCCESS)
status = check_status(naibrd_GetAddress(inputCANConfig.cardIndex,&boardAddress));
if (status == NAI_SUCCESS)
{
if (bGen4CanIDRCommands)
{
MakeCANRxReadFIFOCommand(inputCANConfig,inputIDRConfig,boardAddress,moduleOffset,bGen4CanIDRCommands,msgIndex);
msgIndex = inputIDRConfig->cmdlength;
MakeCANRxReadRegsFIFOStatus(inputCANConfig,inputIDRConfig,boardAddress,moduleOffset,bGen4CanIDRCommands,msgIndex);
msgIndex = inputIDRConfig->cmdlength;
MakeCANRxReadRegsCommand(inputIDRConfig,boardAddress,moduleOffset,bGen4CanIDRCommands,msgIndex);
msgIndex = inputIDRConfig->cmdlength;
}
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read reg command and stores it in the IDR Configuration. The read will be performed
on the modules latched status interrupt register.
</summary>
*/
/**************************************************************************************************************/
void MakeCANRxReadRegsCommand(IDRConfig* inputIDRConfig,uint32_t boardAddress,int32_t moduleOffset,bool_t bGen4Ether, uint16_t startIndex)
{
uint16_t msgIndex = startIndex;
uint16_t seqno;
uint32_t count, stride;
uint32_t regaddr;
if (bGen4Ether)
{
seqno = 0;
regaddr = boardAddress + moduleOffset + NAI_CAN_GEN5_REG_RECV_STATUS_LATCHED_ADD;
count = 1;
stride = 4;
msgIndex = (uint16_t)nai_ether_MakeReadMessage(&inputIDRConfig->commands[startIndex],seqno,NAI_ETHER_GEN4,(nai_intf_t)inputIDRConfig->boardInterface,regaddr,stride,count,NAI_REG32);
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
command_index_interrupt_status = inputIDRConfig->cmdcount;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read reg command and stores it in the IDR Configuration. The read will be performed
on the channels FIFO status register. The channel is set in inputCANConfig.
</summary>
*/
/**************************************************************************************************************/
void MakeCANRxReadRegsFIFOStatus(CanConfig inputCANConfig, IDRConfig* inputIDRConfig,uint32_t boardAddress,int32_t moduleOffset,bool_t bGen4Ether, uint16_t startIndex)
{
uint16_t msgIndex = startIndex;
uint16_t seqno;
uint32_t count, stride;
uint32_t regaddr;
uint32_t CAN_GEN5_RxFifoStatus[] = NAI_CAN_GEN5_REG_FIFO_STATUS_ADD;
if (bGen4Ether)
{
seqno = 0;
regaddr = boardAddress + moduleOffset + CAN_GEN5_RxFifoStatus[inputCANConfig.channel-1];
count = 1;
stride = 4;
msgIndex = (uint16_t)nai_ether_MakeReadMessage(&inputIDRConfig->commands[startIndex],seqno,NAI_ETHER_GEN4,(nai_intf_t)inputIDRConfig->boardInterface,regaddr,stride,count,NAI_REG32);
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
command_index_fifo_status = inputIDRConfig->cmdcount;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read FIFO command and stores it in the IDR Configuration. The read will be performed
on the channels FIFO buffer register.
</summary>
*/
/**************************************************************************************************************/
void MakeCANRxReadFIFOCommand(CanConfig inputCANConfig, IDRConfig* inputIDRConfig,uint32_t boardAddress,int32_t moduleOffset,bool_t bGen4Ether, uint16_t startIndex)
{
uint16_t seqno;
uint32_t bufferAddr;
uint32_t bufferCountAddr;
uint32_t CAN_GEN5_RxbufferCountAddr[] = NAI_CAN_GEN5_REG_RX_BUFFER_COUNT_ADD;
uint32_t CAN_GEN5_RxBufferAddr[] = NAI_CAN_GEN5_REG_RX_BUFFER_ADD;
int32_t count;
uint16_t msgIndex;
int32_t channel;
channel = inputCANConfig.channel;
msgIndex = startIndex;
if (bGen4Ether)
{
seqno = 0;
bufferAddr = CAN_GEN5_RxBufferAddr[channel-1] + moduleOffset + boardAddress;
bufferCountAddr = CAN_GEN5_RxbufferCountAddr[channel-1] + moduleOffset + boardAddress;
count = inputCANConfig.maxPayload;
msgIndex = (uint16_t)nai_ether_MakeFifoReadMessage(&inputIDRConfig->commands[startIndex],seqno,NAI_ETHER_GEN4,(nai_intf_t)inputIDRConfig->boardInterface,bufferAddr,bufferCountAddr,count,NAI_REG32,10);
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet write reg command and stores it in the IDR Configuration. The write will be performed
on the modules latched status interrupt register. The purpose of this write is to clear the interrupt status register and re-arm the interrupts
after one has occurred.
</summary>
*/
/**************************************************************************************************************/
void MakeCANRxWriteRegsCommand(CanConfig inputCANConfig, IDRConfig* inputIDRConfig,uint32_t boardAddress,int32_t moduleOffset,bool_t bGen4Ether, uint16_t startIndex)
{
uint16_t msgIndex = startIndex;
uint16_t seqno;
uint32_t count, stride;
uint32_t regaddr;
uint32_t data = 0x1 << (inputCANConfig.channel-1); /* Clear Rx interrupt bits */
if (bGen4Ether)
{
seqno = 0;
regaddr = moduleOffset + boardAddress + NAI_CAN_GEN5_REG_RECV_STATUS_LATCHED_ADD;
count = 1;
stride = 4;
msgIndex = (uint16_t)nai_ether_BeginWriteMessage(&inputIDRConfig->commands[startIndex],seqno,NAI_ETHER_GEN4,(nai_intf_t)inputIDRConfig->boardInterface,regaddr,stride,count,NAI_REG32);
if (msgIndex >= 0)
{
msgIndex = (uint16_t)nai_ether_WriteMessageData(&inputIDRConfig->commands[startIndex],msgIndex,NAI_REG32,&data,NAI_REG32,count);
if (msgIndex >= 0)
{
msgIndex = (uint16_t)nai_ether_FinishMessage(&inputIDRConfig->commands[startIndex],msgIndex,NAI_ETHER_GEN4);
}
}
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
Handles interpreting the idr response msgs received for can data.
displays the IDR ID and status. Also displays the fifo data from the interrupting channel.
Expects to be parsing a message for a SINGLE channel interrupt only.
</summary>
*/
/**************************************************************************************************************/
void HandleCANEtherInterrupt(uint16_t msglen, uint8_t msg[],uint16_t tdr_idr_id)
{
static uint8_t status;
static FIFO* fifo[NAI_GEN5_CAN_MAX_CHANNEL_COUNT];
int32_t channel;
uint16_t seq;
nai_ether_typecode_t typeCode;
nai_ether_gen_t gen = NAI_ETHER_GEN4;
int32_t size;
int32_t commandIndex;
int32_t idrID;
nai_ether_DecodeMessageHeader(msg, msglen, &seq, &typeCode, gen, &size);
channel = inputCANConfig.channel;
if(fifo[channel-1] == NULL)
{
fifo[channel-1] = allocateSpaceForFIFO(MAX_FIFO_COUNT,inputCANConfig.maxPayload);
}
commandIndex = (seq & (0x0F << 6)) >> 6;
idrID = tdr_idr_id;
switch (typeCode)
{
/* Write REG */
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4:
break;
/* READ REG */
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
if(command_index_fifo_status == commandIndex)
{
fifo[channel-1]->fifoStatus = (fifo[channel-1]->fifoStatus | msg[11]);
fifo[channel-1]->fifoStatus = (fifo[channel-1]->fifoStatus | (msg[10] << 8));
}
else if(command_index_interrupt_status == commandIndex)
status = msg[11];
break;
/* Read FIFO */
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_FIFO_4:
getInterruptDataEthernet(msg, msglen,fifo[channel-1]);
break;
}
if(commandIndex == inputIDRConfig.cmdcount-1)
{
printf("\nInterrupt Occurred\n");
printInterruptInformation_CAN(inputCANConfig,idrID,status,fifo,TRUE,fifoDataFile);
if(fifo[channel-1] != NULL)
{
deallocSpaceForFIFO(fifo[channel-1]);
fifo[channel-1] = NULL;
}
}
}
/**************************************************************************************************************/
/**
<summary>
</summary>
*/
/**************************************************************************************************************/
void getInterruptDataEthernet(uint8_t msg[], uint16_t msglen,FIFO* fifo)
{
int32_t msgIndex;
int32_t startOfCanFrame;
int32_t endOfCanFrame;
int32_t endOfHeader;
int32_t dataSectionSize;
int32_t canHeaderSize;
int32_t startOfDataInCanFrame;
int32_t frameBufferIndex;
int32_t amountInDataBuffer;
int32_t dataIndex;
int32_t sizeOfPostamble;
int32_t startOfPayLoad;
int32_t amountOfDataInFrame;
int32_t bufferCapacity;
uint32_t* dataBuffer;
frameBufferIndex = 0;
sizeOfPostamble = 2;
startOfPayLoad = ETHERNET_OVERHEAD_FIFO_COMMAND - sizeOfPostamble;
canHeaderSize = NAI_CAN_FRAME_SIZE*NAI_REG32;
for(msgIndex = startOfPayLoad + NAI_REG32 - 1; msgIndex <= msglen; msgIndex++)
{
startOfCanFrame = msgIndex;
if((msg[msgIndex-1] * 256) == NAI_CAN_MSG_START && fifo->numOfFramesOnFifo < fifo->maxFramesOnFifo)
{
startOfDataInCanFrame = startOfCanFrame + canHeaderSize;
amountInDataBuffer = 0;
dataBuffer = fifo->buffer[frameBufferIndex].data;
bufferCapacity = fifo->buffer[frameBufferIndex].maxLength;
endOfHeader = startOfDataInCanFrame - NAI_REG32;
if(endOfHeader < msglen)
{
amountOfDataInFrame = ((msg[endOfHeader-1]* 256) | msg[endOfHeader]) & 0x7FF;
dataSectionSize = amountOfDataInFrame*NAI_REG32;
endOfCanFrame = msg[endOfHeader + dataSectionSize - 1] * 256;
if(endOfCanFrame == NAI_CAN_MSG_END)
{
for(dataIndex = startOfDataInCanFrame; dataIndex < startOfDataInCanFrame + dataSectionSize;dataIndex = dataIndex + NAI_REG32)
{
if((amountInDataBuffer < bufferCapacity))
{
dataBuffer[amountInDataBuffer] = msg[dataIndex];
amountInDataBuffer++;
}
}
fifo->buffer[frameBufferIndex].length = amountInDataBuffer;
frameBufferIndex++;
frameCount++;
fifo->numOfFramesOnFifo++;
}
}
}
}
}