SER BasicInterrupt
Edit this on GitLab
SER BasicInterrupt Sample Application (SSK 2.x)
Overview
The SER BasicInterrupt sample application demonstrates how to configure and handle hardware interrupts on serial (SER) communication modules using the NAI Software Support Kit (SSK 2.x). It covers configuring a serial channel for asynchronous loopback communication, setting up an interrupt on the receive buffer high watermark status (or transmit complete status for PT1 modules), sending data to trigger the interrupt, and receiving the interrupt in a callback function. The sample provides a complete end-to-end interrupt example: channel configuration, ISR registration, interrupt steering, data transmission, and interrupt reception.
This sample supports the following serial module types: SC1, SC2, SC3, SC5, SC7, SC8, SC9, SCA, SCB, as well as combination modules with serial functionality (CMH, CMR, PT1). For PT1 modules, the sample uses the transmit complete status instead of the high watermark status because PT1 does not support loopback mode.
For the SSK 1.x version, see SER Interrupts (SSK 1.x).
|
Note
|
This sample is not available on DEOS. The interrupt callback mechanism requires POSIX thread support, which DEOS does not provide. Consult the SSK 2.x Software Development Guide for platform-specific build configuration. |
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a serial module installed (SC1-SC7, or a combination module with serial functionality).
-
SSK 2.x installed on your development host.
-
The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.
-
A platform that supports hardware interrupts (Petalinux or VxWorks).
How to Run
Launch the ser_basic_interrupt executable from your build output directory. On startup the application looks for a configuration file (default_SER_BasicInterrupt.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, the application configures the serial channel, sets up interrupts, and sends loopback data to trigger the interrupt automatically.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to SER. |
The main() function follows a standard SSK 2.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_SER_BasicInterrupt.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleName()so downstream code can verify the selected slot contains a serial module. -
Query for a channel number with
naiapp_query_ChannelNumber().
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t SER_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
bool_t stop = NAI_FALSE;
uint32_t moduleID;
int32_t channelCount, chanNum;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (stop != NAI_TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(),
DEF_SER_CARD_INDEX, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, DEF_SER_MODULE, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID != 0))
{
channelCount = naibrd_SER_GetChannelCount(moduleID);
stop = naiapp_query_ChannelNumber(channelCount,
DEF_SER_CHANNEL, &chanNum);
if (stop != NAI_TRUE)
{
g_serParams->cardIndex = cardIndex;
g_serParams->module = module;
g_serParams->modId = moduleID;
g_serParams->channel = chanNum;
Run_SER_BasicInterrupt();
}
}
}
}
}
}
naiapp_access_CloseAllOpenCards();
return 0;
}
Note the SSK 2.x differences from SSK 1.x in this startup sequence:
-
The VxWorks preprocessor guard uses
NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS(SSK 1.x uses__VXWORKS__). -
The module identifier is retrieved with
naibrd_GetModuleName()(SSK 1.x usesnaibrd_GetModuleID()). -
Boolean constants are
NAI_TRUE/NAI_FALSE(SSK 1.x usesTRUE/FALSE). -
Console output uses
naiif_printf()from the platform abstraction layer (SSK 1.x usesprintf()directly).
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms (Petalinux) the entry point is main(). On VxWorks the entry point is SER_BasicInterrupt() — the SSK 2.x build system selects the correct variant via a preprocessor guard.
The startup flow is the same in both cases:
-
Attempt to load the saved configuration file via
naiapp_RunBoardMenu(DEF_CONFIG_FILE). -
Enter a loop that queries for card index, module slot, and channel number.
-
Store the selected parameters in the global
g_serParamsstructure. -
Call
Run_SER_BasicInterrupt()to validate the module, configure the channel, set up interrupts, and send test data. -
On exit, close all open board connections with
naiapp_access_CloseAllOpenCards().
Module Validation
Run_SER_BasicInterrupt() validates the module ID against a list of supported serial module types using a switch statement. Supported types include NAIBRD_MODULE_ID_SC1 through NAIBRD_MODULE_ID_SCB, plus combination modules NAIBRD_MODULE_ID_CMH, NAIBRD_MODULE_ID_CMR, and NAIBRD_MODULE_ID_PT1:
switch (modID)
{
case NAIBRD_MODULE_ID_CMH:
case NAIBRD_MODULE_ID_CMR:
case NAIBRD_MODULE_ID_PT1:
case NAIBRD_MODULE_ID_SC1:
case NAIBRD_MODULE_ID_SC2:
case NAIBRD_MODULE_ID_SC3:
case NAIBRD_MODULE_ID_SC5:
case NAIBRD_MODULE_ID_SC7:
case NAIBRD_MODULE_ID_SC8:
case NAIBRD_MODULE_ID_SC9:
case NAIBRD_MODULE_ID_SCA:
case NAIBRD_MODULE_ID_SCB:
Cfg_SER_Channel();
status = NAI_SUCCESS;
break;
default:
naiif_printf(" *** Module selection not recognized as SER module. ***\r\n\r\n");
status = NAI_ERROR_INVALID_MODULE;
break;
}
Serial Channel Configuration
Before interrupts can be configured, the serial channel must be set up for communication. Cfg_SER_Channel() configures the channel for asynchronous loopback transmission (or RS-422 for PT1):
check_status(naibrd_SER_ChannelReset(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearRxFifo(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearTxFifo(cardIndex, module, chanNum));
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, NAI_TRUE));
check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum,
NAIBRD_SER_PROTOCOL_ASYNC));
check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum,
NAIBRD_SER_INTF_LOOPBACK));
check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum,
NAIBRD_SER_PARITY_NONE));
check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum,
NAIBRD_SER_DATA_BITS_8));
check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum,
NAIBRD_SER_STOP_BITS_1));
check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));
-
Channel reset and FIFO clear — ensures the channel starts in a clean state.
-
Protocol — set to
NAIBRD_SER_PROTOCOL_ASYNCfor asynchronous communication. -
Interface — set to
NAIBRD_SER_INTF_LOOPBACKso transmitted data loops back to the receive buffer, enabling self-test without external wiring. PT1 modules useNAIBRD_SER_INTF_RS422because they do not support loopback. -
Line parameters — 8 data bits, no parity, 1 stop bit, 9600 baud.
Interrupt Configuration
The Cfg_SER_Interrupt() function performs the complete interrupt setup. The serial module uses an "EventMapped" interrupt pattern rather than the "ChanMapped" pattern used by DT and TTL modules.
Interrupt Steering Selection
The sample uses preprocessor defines to select the interrupt steering target. Only one steering option should be active at a time:
#define STEER_ONBOARD
#undef STEER_PCIE
#undef STEER_CPCI
#undef STEER_VME
#if defined (STEER_ONBOARD)
interruptSteering = NAIBRD_INT_STEERING_ONBOARD_ARM;
#elif defined (STEER_PCIE)
interruptSteering = NAIBRD_INT_STEERING_PCIE;
#elif defined (STEER_CPCI)
interruptSteering = NAIBRD_INT_STEERING_CPCI;
#elif defined (STEER_VME)
interruptSteering = NAIBRD_INT_STEERING_VME;
#endif
Status Type and Watermark
The interrupt status type depends on the module. For most serial modules, the sample monitors the receive buffer high watermark status (NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED). For PT1 modules, it uses the transmit complete status (NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED):
if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
{
interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED;
}
else
{
interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED;
status = check_status(naibrd_SER_SetRxBufferHiWatermark(cardIndex, module,
chanNum, 25));
}
The high watermark is set to 25, meaning the interrupt will fire when 25 or more words accumulate in the receive buffer.
Connecting ISR and Configuring Delivery
/* Connect the ISR callback */
status = naibrd_ConnectISR(cardIndex, SampleCallBack);
/* Set edge triggering */
status = check_status(naibrd_SER_SetEventMappedInterruptTriggerType(cardIndex,
module, chanNum, interruptStatus, NAIBRD_INT_TRIGGER_TYPE_EDGE));
/* Set interrupt vector (unique per channel) */
status = check_status(naibrd_SER_SetEventMappedInterruptVector(cardIndex,
module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, interruptVector));
/* Set interrupt steering */
status = check_status(naibrd_SER_SetEventMappedInterruptSteering(cardIndex,
module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, interruptSteering));
/* Enable the interrupt */
status = check_status(naibrd_SER_SetEventMappedInterruptEnable(cardIndex,
module, chanNum, interruptStatus, NAI_TRUE));
-
naibrd_SER_SetEventMappedInterruptTriggerType()— selects edge or level triggering per channel and status type. -
naibrd_SER_SetEventMappedInterruptVector()— assigns a unique vector per channel. The sample uses0xA1through0xA8based on channel number. -
naibrd_SER_SetEventMappedInterruptSteering()— routes the interrupt to the selected bus. -
naibrd_SER_SetEventMappedInterruptEnable()— enables interrupt generation for the specified status type.
Interrupt Vector Assignment
The sample assigns a unique interrupt vector to each channel so the ISR can identify the source:
switch (chanNum)
{
case 1: interruptVector = 0x000000A1u; break;
case 2: interruptVector = 0x000000A2u; break;
case 3: interruptVector = 0x000000A3u; break;
case 4: interruptVector = 0x000000A4u; break;
case 5: interruptVector = 0x000000A5u; break;
case 6: interruptVector = 0x000000A6u; break;
case 7: interruptVector = 0x000000A7u; break;
case 8: interruptVector = 0x000000A8u; break;
default: status = NAI_ERROR_INVALID_CHANNEL; break;
}
Data Transmission and Interrupt Triggering
After the interrupt is configured, Run_SER_BasicInterrupt() loads 30 words of incremental data into the transmit buffer and initiates transmission. In loopback mode, this data arrives in the receive buffer, triggering the high watermark interrupt when the count exceeds 25:
for (i = 0; i < NUM_WORDS_TO_SEND; i++)
{
SendData[i] = (uint8_t)(i + 0x31);
}
check_status(naibrd_SER_LoadBufferWithTimeOut32(cardIndex, module, chanNum,
SendData, NUM_WORDS_TO_SEND, NUM_WORDS_TO_SEND, NAI_TIMEOUT_NONE, &numSent));
naiif_msDelay(150);
check_status(naibrd_SER_TransmitInitiate(cardIndex, module, chanNum));
ISR Callback
The ISR callback executes when the hardware interrupt fires:
static void SampleCallBack(uint32_t vector)
{
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
logMsg("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector, 0, 0, 0, 0, 0);
#else
naibsp_printf("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector);
#endif
}
Platform-Specific Behavior
-
VxWorks — uses
logMsg()for deferred logging from interrupt context. -
Petalinux — uses
naibsp_printf(), a BSP-level print function safe for interrupt context.
|
Note
|
The callback uses naibsp_printf() (BSP layer), not naiif_printf() (application layer). BSP-level print functions are designed for use in interrupt context.
|
Clearing Interrupt Status
The Clear_InterruptStatus() helper clears the latched interrupt status so subsequent interrupts can be received:
static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus)
{
naibrd_SER_ClearEventMappedStatus(cardIndex, module, chanNum, interruptStatus);
}
This function is called before the interrupt is enabled to ensure a clean starting state. After an interrupt fires, you must clear the latched status before a new interrupt of the same type will occur.
Troubleshooting Reference
This table summarizes common errors and symptoms. Consult the SC3 Manual for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, incorrect or missing configuration file, network issue |
Verify hardware is powered and connected. If |
Module not recognized as SER |
Selected slot contains a non-serial module, or module ID not in the supported list |
Verify the slot contains a supported serial module (SC1-SCB, CMH, CMR, or PT1) |
|
Platform does not support hardware interrupts, or interrupt support not enabled |
Verify you are running on Petalinux or VxWorks with interrupt support compiled in |
Interrupt configured but never fires |
High watermark not reached, loopback not configured, or missing configuration step |
Verify the interface is set to loopback and that enough data is sent to exceed the watermark threshold (25 words) |
Interrupt fires once but never again |
Latched status not cleared after interrupt |
Call |
Wrong vector received in ISR |
Vector mismatch between configuration and ISR logic |
Verify the vector assignment matches the channel number |
PT1 module interrupt does not fire with high watermark |
PT1 does not support loopback, high watermark status not applicable |
The sample automatically uses transmit complete status for PT1. Ensure the module ID is correctly detected. |
Ethernet communication does not support interrupts |
Interrupt steering requires a direct bus connection (PCIe, CPCI, VME, or onboard ARM) |
Use a direct hardware connection rather than Ethernet for interrupt-based applications |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — ser_basic_interrupt.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"
/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ser.h"
/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"
/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
#include "logLib.h"
#endif
static const int8_t *DEF_CONFIG_FILE = (const int8_t *) "default_SER_BasicInterrupt.txt";
/* Function prototypes */
static int32_t Run_SER_BasicInterrupt();
static void Cfg_SER_Channel();
static nai_status_t Cfg_SER_Interrupt();
static void SampleCallBack(uint32_t vector);
static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus);
static const int32_t DEF_SER_CARD_INDEX = 0;
static const int32_t DEF_SER_MODULE = 1;
static const int32_t DEF_SER_CHANNEL = 1;
#define NUM_WORDS_TO_SEND 30
naiapp_AppParameters_t g_serparams;
p_naiapp_AppParameters_t g_serParams = &g_serparams;
/**************************************************************************************************************/
/** \defgroup SERInterrupts
\brief This sample application demonstrates how to configure and use interrupts with a serial module.
The SER_BasicInterrupt sample application illustrates the methods to call in the naibrd library to perform basic interrupt operations with
the serial module.
\note There are many ways to configure interrupt steering based on your system and where the application is running. Pleaes refer to the C
preprocessor defines in `Cfg_SER_Interrupt()` to change this for your configuration.
The main steps include:
- Querying the user for the card index and module number.
- Configuring the serial channel for asynchronous communication.
- Setting up interrupts for the serial channel.
- Handling interrupts and displaying the results.
*/
/**************************************************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t SER_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
bool_t stop = NAI_FALSE;
uint32_t moduleID;
int32_t channelCount, chanNum;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (stop != NAI_TRUE)
{
/* Select Card Index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), DEF_SER_CARD_INDEX, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Select Module */
stop = naiapp_query_ModuleNumber(moduleCnt, DEF_SER_MODULE, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID != 0))
{
channelCount = naibrd_SER_GetChannelCount(moduleID);
stop = naiapp_query_ChannelNumber(channelCount, DEF_SER_CHANNEL, &chanNum);
if (stop != NAI_TRUE)
{
g_serParams->cardIndex = cardIndex;
g_serParams->module = module;
g_serParams->modId = moduleID;
g_serParams->channel = chanNum;
Run_SER_BasicInterrupt();
naiif_printf("\r\nType Q to quit or Enter to continue:\r\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
}
}
}
}
naiif_printf("\r\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module to interrupt on the Receive Buffer High Water-mark status.
and monitor the general purpose input.
*/
/**************************************************************************************************************/
static int32_t Run_SER_BasicInterrupt()
{
int32_t cardIndex = g_serParams->cardIndex;
int32_t module = g_serParams->module;
uint32_t modID = g_serParams->modId;
int32_t chanNum = g_serParams->channel;
uint32_t SendData[NUM_WORDS_TO_SEND];
int32_t numSent, i;
uint32_t outRxBuffCnt;
bool_t bQuit = NAI_FALSE;
nai_status_t status;
if (!bQuit)
{
switch (modID)
{
case NAIBRD_MODULE_ID_CMH:
case NAIBRD_MODULE_ID_CMR:
case NAIBRD_MODULE_ID_PT1:
case NAIBRD_MODULE_ID_SC1:
case NAIBRD_MODULE_ID_SC2:
case NAIBRD_MODULE_ID_SC3:
case NAIBRD_MODULE_ID_SC5:
case NAIBRD_MODULE_ID_SC7:
case NAIBRD_MODULE_ID_SC8:
case NAIBRD_MODULE_ID_SC9:
case NAIBRD_MODULE_ID_SCA:
case NAIBRD_MODULE_ID_SCB:
Cfg_SER_Channel();
status = NAI_SUCCESS;
break;
default:
naiif_printf(" *** Module selection not recognized as SER module. ***\r\n\r\n");
status = NAI_ERROR_INVALID_MODULE;
break;
}
if (status == NAI_SUCCESS)
{
Cfg_SER_Interrupt();
naiif_printf("\r\nWaiting for an interrupt .....\r\n");
/* Send some data in loop back to trigger the interrupt */
naiif_printf("Sending Data:\r\n");
for (i = 0; i < NUM_WORDS_TO_SEND; i++)
{
SendData[i] = (uint8_t)(i + 0x31); /* incremental data*/
naiif_printf("data[%2d] = 0x%X\r\n", i, SendData[i]);
}
check_status(naibrd_SER_LoadBufferWithTimeOut32(cardIndex, module, chanNum, SendData, NUM_WORDS_TO_SEND, NUM_WORDS_TO_SEND,
NAI_TIMEOUT_NONE, &numSent));
naiif_msDelay(150);
check_status(naibrd_SER_TransmitInitiate(cardIndex, module, chanNum));
naiif_msDelay(150);
check_status(naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, &outRxBuffCnt));
naiif_printf("\r\n%d words waiting in RX buffer. ", outRxBuffCnt);
}
}
return cardIndex;
}
/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module for asynchronous loopback transmission.
*/
/**************************************************************************************************************/
static void Cfg_SER_Channel()
{
int32_t cardIndex = g_serParams->cardIndex;
int32_t module = g_serParams->module;
int32_t chanNum = g_serParams->channel;
check_status(naibrd_SER_ChannelReset(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearRxFifo(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearTxFifo(cardIndex, module, chanNum));
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, NAI_TRUE)); /* Enable channel */
check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum, NAIBRD_SER_PROTOCOL_ASYNC)); /* Async mode */
if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
{
check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_RS422)); /* PT1 does not support loopback */
}
else
{
check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_LOOPBACK)); /* LoopBack */
}
check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum, NAIBRD_SER_PARITY_NONE)); /* No Parity */
check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum, NAIBRD_SER_DATA_BITS_8)); /* 8 Data Bits */
check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum, NAIBRD_SER_STOP_BITS_1)); /* 1 Stop Bits */
check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600)); /* Baud rate */
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1)); /* Enable the Receiver */
/* Wait for configuration to be ready */
naiif_msDelay(150);
}
/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module to interrupt on the Receive Buffer High Water-mark status and inserts a user callback
interrupt service routine. Prints out interrupt configuration.
*/
/**************************************************************************************************************/
static nai_status_t Cfg_SER_Interrupt()
{
int32_t cardIndex = g_serParams->cardIndex;
int32_t module = g_serParams->module;
int32_t chanNum = g_serParams->channel;
nai_status_t status = NAI_SUCCESS;
naibrd_ser_event_mapped_status_type_t interruptStatus;
uint32_t interruptVector, outvector;
naibrd_int_steering_t interruptSteering, outsteering;
uint32_t hiWaterMark = 0u;
naibrd_int_trigger_type_t outtriggerType;
bool_t outenable;
/* Pick one interrupt steering that applies to the board and system you are using */
#define STEER_ONBOARD
#undef STEER_PCIE
#undef STEER_CPCI
#undef STEER_VME
#define VME_INT_LEVEL 5
#if defined (STEER_ONBOARD)
interruptSteering = NAIBRD_INT_STEERING_ONBOARD_ARM;
#elif defined (STEER_PCIE)
interruptSteering = NAIBRD_INT_STEERING_PCIE;
#elif defined (STEER_CPCI)
interruptSteering = NAIBRD_INT_STEERING_CPCI;
#elif defined (STEER_VME)
interruptSteering = NAIBRD_INT_STEERING_VME;
#endif
if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
{
/* PT1 does not have a loopback interface, so we will not be able to use the high watermark status for an interrupt */
interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED;
}
else
{
interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED;
/* Set serial specific flag, this will trigger an interrupt when 25 words are present in the serial RX buffer */
status = check_status(naibrd_SER_SetRxBufferHiWatermark(cardIndex, module, chanNum, 25));
}
/* Set interrupt vector and status type based on the desired channel */
switch (chanNum)
{
case 1:
interruptVector = 0x000000A1u;
break;
case 2:
interruptVector = 0x000000A2u;
break;
case 3:
interruptVector = 0x000000A3u;
break;
case 4:
interruptVector = 0x000000A4u;
break;
case 5:
interruptVector = 0x000000A5u;
break;
case 6:
interruptVector = 0x000000A6u;
break;
case 7:
interruptVector = 0x000000A7u;
break;
case 8:
interruptVector = 0x000000A8u;
break;
default:
status = NAI_ERROR_INVALID_CHANNEL;
interruptVector = 0x0u;
break;
}
if (status == NAI_SUCCESS)
{
/* Make sure interrupt is cleared before we start */
Clear_InterruptStatus(interruptStatus);
/* Specify callback function for interrupt type */
#ifdef NAI_USE_INTF_VME
if (interruptSteering == NAIBRD_INT_STEERING_VME)
{
naibsp_sys_vme_SetVmeIntLvl(cardIndex, VME_INT_LEVEL); /* HNP VME you need vector, think of a better way to set */
}
#endif
status = naibrd_ConnectISR(cardIndex, SampleCallBack); /* Invoked once per card, not per interrupt type */
if (status == NAI_ERROR_NOT_SUPPORTED)
{
naiif_printf("\r\n**Interrupts are either not supported on this platform or not enabled**\r\n");
}
else if (status != NAI_SUCCESS)
{
naiif_printf("\r\n**Failed to connect ISR!**\r\n");
}
status = check_status(naibrd_SER_SetEventMappedInterruptTriggerType(cardIndex, module, chanNum, interruptStatus,
NAIBRD_INT_TRIGGER_TYPE_EDGE));
status = check_status(naibrd_SER_SetEventMappedInterruptVector(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM,
interruptVector));
status = check_status(naibrd_SER_SetEventMappedInterruptSteering(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM,
interruptSteering));
status = check_status(naibrd_SER_SetEventMappedInterruptEnable(cardIndex, module, chanNum, interruptStatus, NAI_TRUE));
/* Get Interrupt Config */
check_status(naibrd_SER_GetEventMappedInterruptTriggerType(cardIndex, module, chanNum, interruptStatus, &outtriggerType));
check_status(naibrd_SER_GetEventMappedInterruptVector(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, &outvector));
check_status(naibrd_SER_GetEventMappedInterruptSteering(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, &outsteering));
check_status(naibrd_SER_GetEventMappedInterruptEnable(cardIndex, module, chanNum, interruptStatus, &outenable));
check_status(naibrd_SER_GetRxBufferHiWatermark(cardIndex, module, chanNum, &hiWaterMark));
naiif_printf("\r\nInterrupt Configuration\r\n");
naiif_printf("=======================\r\n");
naiif_printf("Card Index:%d\r\n", cardIndex);
naiif_printf("Module Number:%d\r\n", module);
naiif_printf("Channel:%d\r\n", chanNum);
naiif_printf("Trigger Type: %s\r\n", outtriggerType == NAIBRD_INT_TRIGGER_TYPE_EDGE ? "EDGE" : "LEVEL");
naiif_printf("Vector: 0x%x\r\n", outvector);
naiif_printf("Steering: ");
switch (outsteering)
{
case NAIBRD_INT_STEERING_VME:
naiif_printf("VME\r\n");
break;
case NAIBRD_INT_STEERING_ONBOARD_ARM:
naiif_printf("Onboard ARM\r\n");
break;
case NAIBRD_INT_STEERING_PCIE:
naiif_printf("PCIE\r\n");
break;
case NAIBRD_INT_STEERING_CPCI:
naiif_printf("CPCI\r\n");
break;
}
if (interruptStatus == NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED)
{
naiif_printf("Hi watermark interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
naiif_printf("Status: Receive buffer high water-mark (%d bytes)\r\n", hiWaterMark);
naiif_printf("\r\n\r\n Waiting for channel %d's RX buffer to have %d words in it to trigger interrupt.\r\n", chanNum, hiWaterMark);
naiif_printf("Hi watermark interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
}
if (interruptStatus == NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED)
{
naiif_printf("Transmit complete interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
naiif_printf("\r\n\r\n Waiting for transmit complete to trigger interrupt.\r\n");
}
}
return status;
}
/**************************************************************************************************************/
/** \ingroup SERInterrupts
The callback function that is installed via naibrd_ConnectISR(). This function will be called when the
interrupt is received. Prints out that the interrupt has been received.
\param vector (Input) Interrupt vector to identify which channel caused the interrupt.
*/
/**************************************************************************************************************/
static void SampleCallBack(uint32_t vector)
{
/* Printing in an ISR is always a bad idea. For demonstration purposes only.
* logMsg & naibsp_printf are a little better since they queue up messages. */
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
logMsg("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector, 0, 0, 0, 0, 0);
#else
naibsp_printf("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector);
#endif
}
/**************************************************************************************************************/
/** \ingroup SERInterrupts
Clears the interrupt status (in this case either the high watermark or transmit complete status).
This is needed to be able to receive any additional interrupts of this type.
\param interruptStatus (Input) The status to clear.
*/
/**************************************************************************************************************/
static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus)
{
int32_t cardIndex = g_serParams->cardIndex;
int32_t module = g_serParams->module;
int32_t chanNum = g_serParams->channel;
/* Clear the interrupt status */
naibrd_SER_ClearEventMappedStatus(cardIndex, module, chanNum, interruptStatus);
}