Hello Forum,
Here is a summary of my issue:
- Started with example code: adc_ex11_multiple_soc_epwm.
- Modified the code to read 3 channels from each of ADCA, ADCB and ADCC
- Added DMA transfer of ADC data to memory
- Added FSI Lead to transmit data to another control board via two FSI adapter boards
The code works well only when I have an ESTOP or a break point in debug mode.
When I run the code without a breakpoint all ADC channels read zero.
Please take a look at the code below and let me know what is wrong with it.
Note: The FSI part is working fine. It does transfer what it gets in the Tx buffer.
//#############################################################################
//
// TITLE: ADC ePWM Triggering Multiple SOC
//
//!
//! This software sets up ePWM3 to periodically trigger a set of conversions on
//! ADCA, ADCB and ADCC. Multiple ADCs work together to process a batch of conversions
//! using the available parallelism across the ADCs.
//!
//! ADCA Interrupt ISRs are used to read results of ADCA, ADCB and ADCC.
//!
//! \b External \b Connections \n
//! - A0, A4, A5, B0, B2, B3, C2 and C4 pins should be connected to signals to be
//! converted.
//!
//!
//! \b External \b Connections \n
//! - A0, A4, A5, B0, B2, B3, C2 and C4 should be connected to signals to convert
//! \b Watch \b Variables \n
//! - \b adcAResult0 - Digital representation of the voltage on pin A0 (pin-43)
//! - \b adcAResult1 - Digital representation of the voltage on pin A4 (pin-39)
//! - \b adcAResult2 - Digital representation of the voltage on pin A5 (pin-38)
//! - \b adcBResult0 - Digital representation of the voltage on pin B0 (pin-46)
//! - \b adcBResult1 - Digital representation of the voltage on pin B2 (pin-48)
//! - \b adcBResult2 - Digital representation of the voltage on pin B3 (pin-49)
//! - \b adcCResult0 - Digital representation of the voltage on pin C2 (pin-31)
//! - \b adcCResult1 - Digital representation of the voltage on pin C4 (pin-29)
//
//#############################################################################
// $TI Release: F2838x Support Library v3.04.00.00 $
// $Release Date: Fri Feb 12 19:08:49 IST 2021 $
// $Copyright:
// Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
//#############################################################################
//
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "fsi_app.h"
//
// Defines
//
#define RESULTS_BUFFER_SIZE 3
//buffer for storing conversion results
// 1024 x 16-bit words
#define EX_ADC_RESOLUTION 12
// 12 for 12-bit conversion resolution, which supports single-ended signaling
// Or 16 for 16-bit conversion resolution, which supports single-ended or
// differential signaling
#define EX_ADC_SIGNALMODE "SINGLE-ENDED"
//"SINGLE-ENDED" for ADC_MODE_SINGLE_ENDED:
// Sample on single pin (VREFLO is the low reference)
// Or "Differential" for ADC_MODE_DIFFERENTIAL:
// Sample on pair of pins (difference between pins is converted, subject to
// common mode voltage requirements; see the device data manual)
#define PRESCALER_VAL FSI_PRESCALE_50MHZ
//
// Globals
//
#pragma DATA_SECTION(adcADataBuffer, "ramgs0");
#pragma DATA_SECTION(adcBDataBuffer, "ramgs0");
#pragma DATA_SECTION(adcCDataBuffer, "ramgs0");
#pragma DATA_SECTION(adcResults, "ramgs0");
uint16_t adcADataBuffer[RESULTS_BUFFER_SIZE];
uint16_t adcBDataBuffer[RESULTS_BUFFER_SIZE];
uint16_t adcCDataBuffer[RESULTS_BUFFER_SIZE];
uint16_t adcResults[8];
volatile uint16_t done;
//
// Function Prototypes
//
void configureADC(uint32_t adcBase);
void initEPWM();
void initADCSOC(void);
void initializeDMA(void);
void configureDMAChannels(void);
__interrupt void adcA1ISR(void);
__interrupt void dmach1ISR(void);
//
// Main
//
void main(void)
{
uint16_t resultsIndex;
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();
//
// Initialize basic settings for FSI
//
initFSI();
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// Interrupts that are re-mapped to ISR functions
//
// ISR for ADCA INT1 - occurs after first conversion
// ISR for DMA ch1 - occurs when DMA transfer is complete
//
Interrupt_register(INT_ADCA1, &adcA1ISR);
Interrupt_register(INT_DMA_CH1, &dmach1ISR);
//
// ISR for FSI Tx/Rx :: INT1/INT2
//
Interrupt_register(INT_FSITXA1, &fsiTxInt1ISR);
Interrupt_register(INT_FSITXA2, &fsiTxInt2ISR);
Interrupt_register(INT_FSIRXA1, &fsiRxInt1ISR);
Interrupt_register(INT_FSIRXA2, &fsiRxInt2ISR);
//
// Enable specific PIE & CPU interrupts:
// ADCA INT1 - Group 1, interrupt 1
// DMA interrupt - Group 7, interrupt 1
//
Interrupt_enable(INT_ADCA1);
Interrupt_enable(INT_DMA_CH1);
//
// Enable FSI Tx/Rx interrupts
//
Interrupt_enable(INT_FSITXA1);
Interrupt_enable(INT_FSITXA2);
Interrupt_enable(INT_FSIRXA1);
Interrupt_enable(INT_FSIRXA2);
//
// Initialize basic settings for FSI
//
//initFSI();
//
// Set up the ADC and the ePWM and initialize the SOC
//
configureADC(ADCA_BASE);
configureADC(ADCB_BASE);
configureADC(ADCC_BASE);
initEPWM();
initADCSOC();
//
// Initialize the DMA & configure DMA channels 1, 2 & 3
//
initializeDMA();
configureDMAChannels();
//
// Initialize results buffer
//
for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
{
adcADataBuffer[resultsIndex] = 0;
adcBDataBuffer[resultsIndex] = 0;
adcCDataBuffer[resultsIndex] = 0;
}
//
// Clearing all pending interrupt flags
//
DMA_clearTriggerFlag(DMA_CH1_BASE); // DMA channel 1
DMA_clearTriggerFlag(DMA_CH2_BASE); // DMA channel 2
DMA_clearTriggerFlag(DMA_CH3_BASE); // DMA channel 3
HWREGH(ADCA_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCA
HWREGH(ADCB_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCB
HWREGH(ADCC_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCC
EPWM_forceADCTriggerEventCountInit(EPWM3_BASE, EPWM_SOC_A); // EPWM3 SOCA
EPWM_clearADCTriggerFlag(EPWM3_BASE, EPWM_SOC_A); // EPWM3 SOCA
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
fsi_SetupTransfer();
//
// Start DMA
//
done = 0;
DMA_startChannel(DMA_CH1_BASE);
DMA_startChannel(DMA_CH2_BASE);
DMA_startChannel(DMA_CH3_BASE);
//
// Start ePWM3, enabling SOCA and putting the counter in up-count mode
//
EPWM_enableADCTrigger(EPWM3_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP);
//
// Loop until the ISR signals the transfer is complete
//
while(1)
{
if(done == 0)
{
__asm(" NOP");
}
}
}
//
// configureADC - Write ADC configurations and power up the ADC for the
// selected ADC
//
void configureADC(uint32_t adcBase)
{
//
// Set ADCCLK divider to /4 (This is 50 MHz)
//
ADC_setPrescaler(adcBase, ADC_CLK_DIV_4_0);
//
// Set resolution and signal mode (see #defines above) and load
// corresponding trims.
//
ADC_setMode(adcBase, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
//
// Set pulse positions to late (end of conversion)
//
ADC_setInterruptPulseMode(adcBase, ADC_PULSE_END_OF_CONV);
//
// Power up the ADCs and then delay for 1 ms
//
ADC_enableConverter(adcBase);
//
// Delay for 1ms to allow ADC time to power up
//
DEVICE_DELAY_US(1000);
}
//
// Function to configure ePWM3 to generate the SOC.
//
void initEPWM(void)
{
//
// Disable SOCA
//
EPWM_disableADCTrigger(EPWM3_BASE, EPWM_SOC_A);
//
// Configure the SOC to occur on the first up-count event
//
EPWM_setADCTriggerSource(EPWM3_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
EPWM_setADCTriggerEventPrescale(EPWM3_BASE, EPWM_SOC_A, 1);
//
// Set the compare A value to 1250 and the period to 2499
// Assuming ePWM clock is 100MHz, this would give 40kHz sampling
// 50MHz ePWM clock would give 25kHz sampling, etc.
// The sample rate can also be modulated by changing the ePWM period
// directly (ensure that the compare A value is less than the period).
// Tpwm = (TBPRD+1) x TBCLK // Tpwm = 2500 * 1/100E+6 = 25 Us
// Fpwm = 1/Tpwm = 1/25E-6 = 40kHz
//
EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, 1250);//1250/2500 = 50% duty cycle
EPWM_setTimeBasePeriod(EPWM3_BASE, 2499);//2499
//EPWM_disablePhaseShiftLoad(EPWM3_BASE);// Clear PHSEN bit
//EPWM_setPeriodLoadMode(EPWM3_BASE, EPWM_PERIOD_SHADOW_LOAD);
//EPWM_enableSyncOutPulseSource(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
//
// Set the local ePWM module clock divider to /1
//
EPWM_setClockPrescaler(EPWM3_BASE,
EPWM_CLOCK_DIVIDER_1,
EPWM_HSCLOCK_DIVIDER_1);
//
// Freeze the counter
//
EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
}
//
// Function to configure SOCs on ADCA, ADCB and ADCC to be triggered by ePWM3.
//
void initADCSOC(void)
{
uint16_t acqps;
//
// Minimum acquisition window (in SYSCLKS) based on 12-bit resolution
//
acqps = 14;// 15 is 80ns
//
// - NOTE: A longer sampling window will be required if the ADC driving
// source is less than ideal (an ideal source would be a high bandwidth
// op-amp with a small series resistance). See TI application report
// SPRACT6 for guidance on ADC driver design.
// - NOTE: SOCs need not use the same S+H window duration, but SOCs
// occurring in parallel (SOC0 on ADCA, ADCB, ADCC occur in
// parallel, as do the SOC1s on the 3 ADCs, etc.) should usually
// use the same value to ensure simultaneous samples and synchronous
// operation.
//
// Select the channels to convert and configure the ePWM trigger
//
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN0, acqps);
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN4, acqps);
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN5, acqps);
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN0, acqps);
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN2, acqps);
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN3, acqps);
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN2, acqps);
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN4, acqps);
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM3_SOCA,
ADC_CH_ADCIN5, acqps);
//
// Select SOC2 on ADCA as the interrupt source.
//
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER2);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER2);
ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER3);
ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER4);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// ADC A Interrupt 1 ISR
//
#pragma CODE_SECTION(adcA1ISR, ".TI.ramfunc");
__interrupt void adcA1ISR(void)
{
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
//
// Check if overflow has occurred
//
if(true == ADC_getInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// Acknowledge interrupt
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
//
// dmach1ISR - This is called at the end of the DMA transfer, the conversions
//
#pragma CODE_SECTION(dmach1ISR, ".TI.ramfunc");
__interrupt void dmach1ISR(void)
{
//
done = 1;
fsi_DataTransfer();
// Acknowledge interrupt
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
//ESTOP0;
done = 0;
}
//
// initializeDMA - Initialize DMA through hard reset
//
void initializeDMA(void)
{
//
// Perform a hard reset on DMA
//
DMA_initController();
//
// Allow DMA to run free on emulation suspend
//
DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);
}
//
// configureDMAChannels - Initialize DMA ch 1 to transfer ADCA results
// , DMA ch 2 to transfer ADCB results
// and ch 3 to transfer ADCC results
//
void configureDMAChannels(void)
{
//
// DMA channel 1 set up for ADCA
//
DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)&adcADataBuffer,
(uint16_t *)ADCARESULT_BASE);
//
// Perform enough 3-word burst to fill the results buffer. Data will be
// transferred 16 bits at a time hence the address steps below.
//
DMA_configBurst(DMA_CH1_BASE, 3, 1, 1);
DMA_configTransfer(DMA_CH1_BASE, 1, 0, 0);
DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_ADCA1,
(DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
DMA_CFG_SIZE_16BIT));
DMA_enableTrigger(DMA_CH1_BASE);
DMA_disableOverrunInterrupt(DMA_CH1_BASE);
DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH1_BASE);
//
// DMA channel 2 set up for ADCB
//
DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)&adcBDataBuffer,
(uint16_t *)ADCBRESULT_BASE);
//
// Perform enough 3-word burst to fill the results buffer. Data will be
// transferred 32 bits at a time hence the address steps below.
//
DMA_configBurst(DMA_CH2_BASE, 3, 1, 1);
DMA_configTransfer(DMA_CH2_BASE, 1, 0, 0);
DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_ADCA1,
(DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
DMA_CFG_SIZE_16BIT));
DMA_enableTrigger(DMA_CH2_BASE);
DMA_disableOverrunInterrupt(DMA_CH2_BASE);
DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH2_BASE);
//
// DMA channel 3 set up for ADCC
//
DMA_configAddresses(DMA_CH3_BASE, (uint16_t *)&adcCDataBuffer,
(uint16_t *)ADCCRESULT_BASE);
//
// Perform enough 3-word burst to fill the results buffer. Data will be
// transferred 16 bits at a time hence the address steps below.
//
DMA_configBurst(DMA_CH3_BASE, 3, 1, 1);
DMA_configTransfer(DMA_CH3_BASE, 1, 0, 0);
DMA_configMode(DMA_CH3_BASE, DMA_TRIGGER_ADCA1,
(DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
DMA_CFG_SIZE_16BIT));
DMA_enableTrigger(DMA_CH3_BASE);
DMA_disableOverrunInterrupt(DMA_CH3_BASE);
DMA_setInterruptMode(DMA_CH3_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH3_BASE);
}
// initFSI - Initializes FSI Tx/Rx with internal loopback and also sends FLUSH
// sequence.
//
void initFSI(void)
{
FSI_disableRxInternalLoopback(FSIRXA_BASE);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_TXCLK);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_TX0);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_RXCLKA);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_RX0A);
if(nLanes == FSI_DATA_WIDTH_2_LANE)
{
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_TX1);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_RX1A);
}
//
// Set RX GPIO to be asynchronous
// (pass through without delay)
// Default setting is to have 2 SYS_CLK cycles delay
//
GPIO_setQualificationMode(DEVICE_GPIO_PIN_FSI_RX0A, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(DEVICE_GPIO_PIN_FSI_RXCLKA, GPIO_QUAL_ASYNC);
if(nLanes == FSI_DATA_WIDTH_2_LANE)
{
GPIO_setQualificationMode(DEVICE_GPIO_PIN_FSI_RX1A, GPIO_QUAL_ASYNC);
}
// TODO- Add logic to calculate PRESCALER_VAL based on user input FSI CLK
FSI_performTxInitialization(FSITXA_BASE, PRESCALER_VAL);
FSI_performRxInitialization(FSIRXA_BASE);
txBufAddr = (uint16_t *)FSI_getTxBufferAddress(FSITXA_BASE);
rxBufAddr = (uint16_t *)FSI_getRxBufferAddress(FSIRXA_BASE);
}
//
// fsiTxInt1ISR - FSI Tx Interrupt on INsT1 line
//
__interrupt void fsiTxInt1ISR(void)
{
fsiTxInt1Received = 1U;
txEventSts = FSI_getTxEventStatus(FSITXA_BASE);
//
// Clear the interrupt flag and issue ACK
//
FSI_clearTxEvents(FSITXA_BASE, FSI_TX_EVTMASK);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);
}
//
// fsiTxInt2ISR - FSI Tx Interrupt on INT2 line
//
__interrupt void fsiTxInt2ISR(void)
{
fsiTxInt2Received = 1U;
txEventSts = FSI_getTxEventStatus(FSITXA_BASE);
//
// Clear the interrupt flag and issue ACK
//
FSI_clearTxEvents(FSITXA_BASE, FSI_TX_EVTMASK);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);
disableAllFSIInterrupts();
//
// INT2 line is set to fire for error events, stop immediately. Actual Error
// is captured in txEventSts for debug
//
ESTOP0;
}
//
// fsiRxInt1ISR - FSI Rx Interrupt on INT1 line
//
__interrupt void fsiRxInt1ISR(void)
{
rxEventSts = FSI_getRxEventStatus(FSIRXA_BASE);
fsiRxInt1Received = 1U;
//
// Clear the interrupt flag and issue ACK
//
FSI_clearRxEvents(FSIRXA_BASE,rxEventSts);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);
}
//
// fsiRxInt2ISR - FSI Rx Interrupt on INT2 line
//
__interrupt void fsiRxInt2ISR(void)
{
rxEventSts = FSI_getRxEventStatus(FSIRXA_BASE);
fsiRxInt2Received = fsiRxInt2Received + 1U;
//
// Clear the interrupt flag and issue ACK
//
FSI_clearRxEvents(FSIRXA_BASE,rxEventSts);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);
disableAllFSIInterrupts();
//
// INT2 line is set to fire for error events, stop immediately. Error
// is captured in rxEventSts for debug
//
ESTOP0;
}
//
// disableAllFSIInterrupts - Disables all event interrupts in both FSI Tx/Rx,
// also clear them
//
void disableAllFSIInterrupts(void)
{
FSI_disableTxInterrupt(FSITXA_BASE, FSI_INT1, FSI_TX_EVTMASK);
FSI_disableTxInterrupt(FSITXA_BASE, FSI_INT2, FSI_TX_EVTMASK);
FSI_disableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVTMASK);
FSI_disableRxInterrupt(FSIRXA_BASE, FSI_INT2, FSI_RX_EVTMASK);
FSI_clearTxEvents(FSITXA_BASE, FSI_TX_EVTMASK);
FSI_clearRxEvents(FSIRXA_BASE, FSI_RX_EVTMASK);
}
//
// compare16 - Compares two 16 bit values and increments global error flag by 1
// for mismatch
//
static inline void compare16(uint16_t val1, uint16_t val2)
{
if(val1 != val2)
{
error++;
}
}
//
// compareBufData - Compares if received data is same as transmitted ones
// It doesn't consider wrap-up cases, but, can be enhanced
//
void compareBufData(uint16_t txBufIndex, uint16_t rxBufIndex, uint16_t nWords)
{
uint16_t i;
uint16_t rxDataArray[16];
FSI_readRxBuffer(FSIRXA_BASE, rxDataArray, nWords, rxBufIndex);
for(i = 0; i < nWords; i++)
{
if(rxDataArray[i] != txBufAddr[txBufIndex])
{
error++;
return;
}
txBufIndex++;
}
}
//
// checkReceivedFrameTypeTag - Checks received frame type/tag and updates global
// error flag
//
void checkReceivedFrameTypeTag(FSI_FrameType type, FSI_FrameTag tag)
{
compare16((uint16_t)FSI_getRxFrameType(FSIRXA_BASE), (uint16_t)type);
if(type == FSI_FRAME_TYPE_PING)
{
compare16(FSI_getRxPingTag(FSIRXA_BASE), (uint16_t)tag);
}
else
{
compare16(FSI_getRxFrameTag(FSIRXA_BASE), (uint16_t)tag);
}
}
#pragma CODE_SECTION(fsi_SetupTransfer, ".TI.ramfunc")
void fsi_SetupTransfer(void)
{
//
// Enable normal data transfer events to be sent over INT1 line
//
FSI_enableTxInterrupt(FSITXA_BASE, FSI_INT1, FSI_TX_EVT_FRAME_DONE);
FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_PING_FRAME);
//
// Wait till interrupt is received on FSIRX INT1 line, verify it's for FRAME
// DONE event for PING Frame reception
//
while(1)
{
//
// Send the flush sequence
//
FSI_executeTxFlushSequence(FSITXA_BASE, PRESCALER_VAL);
//
// Send a ping frame with frame tag 0000b
//
FSI_setTxFrameTag(FSITXA_BASE, FSI_FRAME_TAG0);
FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_PING);
FSI_startTxTransmit(FSITXA_BASE);
while(fsiRxInt1Received != 1U && rxTimeOutCntr != 0U)
{
DEVICE_DELAY_US(1);
rxTimeOutCntr--;
}
if(rxTimeOutCntr == 0)
{
rxTimeOutCntr = 0x100000;
continue;
}
else
{
compare16(rxEventSts, (FSI_RX_EVT_PING_FRAME | FSI_RX_EVT_FRAME_DONE));
checkReceivedFrameTypeTag(FSI_FRAME_TYPE_PING, FSI_FRAME_TAG1);
//
// If received frame type and tag matches, exit this loop and proceed
// to next step by sending flush sequence, otherwise clear error and
// interrupt flag and continue looping.
//
if(error == 0)
{
fsiRxInt1Received = 0;
break;
}
fsiRxInt1Received = 0;
error = 0;
}
}
//
// Send a ping frame with frame tag 0001b
//
FSI_setTxFrameTag(FSITXA_BASE, FSI_FRAME_TAG1);
FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_PING);
FSI_startTxTransmit(FSITXA_BASE);
DEVICE_DELAY_US(100);
FSI_setTxSoftwareFrameSize(FSITXA_BASE, nWords);
FSI_setTxDataWidth(FSITXA_BASE, nLanes);
FSI_setTxUserDefinedData(FSITXA_BASE, txUserData);
FSI_setTxFrameTag(FSITXA_BASE, txDataFrameTag);
FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_NWORD_DATA);
}
#pragma CODE_SECTION(fsi_DataTransfer, ".TI.ramfunc")
void fsi_DataTransfer(void)
{
//
// Write data into Tx buffer and set other Frame specific fields
//
memcpy(txBufData, &adcADataBuffer, 8);// 8 ADC channels
FSI_writeTxBuffer(FSITXA_BASE, txBufData, nWords, 0U);
while(fsiTxInt1Received != 1U);
//
// Start Transfer
//
FSI_startTxTransmit(FSITXA_BASE);
while(fsiTxInt1Received != 1);
//
// Re-initialize flags and buffer pointer before next transmission
//
fsiTxInt1Received = 0U;
dataFrameCntr++;
FSI_setTxBufferPtr(FSITXA_BASE, 0U);
}
//
// End of file
//