Hi,
I am trying to test how to use DMA control for FSI communication between 2 devices, so actually I am combining the example projects of fsi_ex3_loopback_dmacontrol.c and fsi_ex8_ext_p2pconnection_tx.c & fsi_ex8_ext_p2pconnection_rx.c .
Configuration:
Two DMA channels are setup for FSI TX operation and two for RX
Device 1: DMA_CH1,DMA_CH2 for TX; DMA_CH3, DMA_CH4 for RX
Device 2: DMA_CH1,DMA_CH2 for RX; DMA_CH3, DMA_CH4 for TX
Four areas in GSx memories for as source and sink for data and tag values
GS0 RAM to store Tx frame data
GS1 RAM to store Tx frame tag and Userdata
GS2 RAM to save received Rx frame data
GS3 RAM to save received Rx frame tag and Userdata
However, the test workef successfully for DMA continuous mode disabled, but failed with DMA continuous mode. When using DMA continuous mode, the project will run into fsiRxInt2ISR with FSI_RX_EVT_EOF_ERR. (FSI_RX_EVT_CRC_ERR is enabled)
I have not found the reason, could you help me about this? The main.c files of 2 projects are as attached.
//#############################################################################
//
// FILE: fsi_ex8_ext_p2pconnection_tx.c
//
// TITLE: FSI Transmit in Point to Point Connection
//
//! \addtogroup driver_example_list
//! <h1>FSI P2Point Connection:Tx Side</h1>
//!
//! Example sets up FSI transmitting device in a point to point connection
//! to the FSI receiving device. Example code to set up FSI receiving device is
//! implemented in a separate file.
//!
//! In a real scenario two separate devices may power up in arbitrary order and
//! there is a need to establish a clean communication link which ensures that
//! receiver side is flushed to properly interpret the start of a new valid
//! frame.
//!
//! There is no true concept of a master or a slave node in the FSI protocol,
//! but to simplify the data flow and connection we can consider transmitting
//! device as master and receiving side as slave. Transmitting side will be
//! driver of initialization sequence.
//!
//! Handshake mechanism which must take place before actual data transmission
//! can be usecase specific; points described below can be taken as an example
//! on how to implement the handshake from transmitting side -
//!
//! - Setup the receiver interrupts to detect PING type frame reception
//! - Begin the PING loop
//! + Send the Flush sequence
//! + Send a PING frame with the frame tag \b FSI_FRAME_TAG0
//! + Wait for some time(determined by application)
//! + If the FSI Rx has received a PING frame with \b FSI_FRAME_TAG1, come
//! out of loop. Otherwise iterate the loop again
//! - Send a PING frame with the frame tag FSI_FRAME_TAG1
//!
//! After above synchronization steps, FSI Tx can be configured as per usecase
//! i.e. nWords, lane width, enabling events etc and start the infinite
//! transfers. More details on establishing the communication link can be found
//! in device TRM.
//!
//! User can edit some of configuration parameters as per usecase, similar to
//! other examples.
//!
//! \b nWords - Number of words per transfer may be from 1 -16
//! \b nLanes - Choice to select single or double lane for frame transfers
//! \b fsiClock - FSI Clock used for transfers
//! \b txUserData - User data to be sent with Data frame
//! \b txDataFrameTag - Frame tag used for Data transfers
//! \b txPingFrameTag - Frame tag used for Ping transfers
//! \b txPingTimeRefCntr - Tx Ping timer reference counter
//! \b rxWdTimeoutRefCntr - Rx Watchdog timeout reference counter
//!
//!\b External \b Connections \n
//! For FSI external P2P connection, make below GPIO settings in
//! example code.
//! - GPIO_7 -> FSITX_CLK
//! - GPIO_6 -> FSITX_TX0
//! - GPIO_5 -> FSITX_TX1
//! - GPIO_13 (GPIO_33 on LaunchPad) -> FSIRX_CLK
//! - GPIO_12 -> FSIRX_RX0
//! - GPIO_11 -> FSIRX_RX1
//!
//! \b Watch \b Variables \n
//! - \b txdataFrameCntr Number of Data frame transmitted
//! - \b rxdataFrameCntr Number of Data frame received
//! - \b error Non zero for transmit/receive data mismatch
//!
//
//#############################################################################
// $TI Release: F28004x Support Library v1.05.00.00 $
// $Release Date: Tue Jun 26 03:10:30 CDT 2018 $
// $Copyright:
// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
//#include "GPIO.h"
#define PRESCALER_VAL 2U
#define DMA_TRANSFER_SIZE_IN_BURSTS 1U
#define TOTAL_WORDS_IN_TRANSFER (DMA_TRANSFER_SIZE_IN_BURSTS * nWords)
// GS0 RAM to store Tx frame data which DMA will read
#define GS0_START_ADDR 0xC100
// GS1 RAM to store Tx frame tag and Userdata
#define GS1_START_ADDR 0xE000
// GS2 RAM to save received Rx frame data
#define GS2_START_ADDR 0x10000
// GS3 RAM to save received Rx frame tag and Userdata
#define GS3_START_ADDR 0x12000
//
// FSI Tx/Rx Frame tag User Data register address, used by DMA channel to
// write(and trigger transfer) read userdata respectively
//
#define FSI_TX_FRAME_TAG_UDATA_REGADDR (FSITXA_BASE + FSI_O_TX_FRAME_TAG_UDATA)
#define FSI_RX_FRAME_TAG_UDATA_REGADDR (FSIRXA_BASE + FSI_O_RX_FRAME_TAG_UDATA)
//TODO
//#define TX_FRAME_DONE_IO 15
//#define TX_FRAME_DONE_IO_CONF GPIO_15_GPIO15
//
//#define RX_DATA_FRAME_IO 16
//#define RX_DATA_FRAME_IO_CONF GPIO_16_GPIO16
#define TX_FRAME_DONE_IO 31
#define TX_FRAME_DONE_IO_CONF GPIO_34_GPIO34
#define RX_DATA_FRAME_IO 34
#define RX_DATA_FRAME_IO_CONF GPIO_34_GPIO34
#define DEVICE_GPIO_PIN_LED1 31U // GPIO number for LD2
#define DEVICE_GPIO_PIN_LED2 34U // GPIO number for LD3
#define DEVICE_GPIO_CFG_LED1 GPIO_31_GPIO31 // "pinConfig" for LD2
#define DEVICE_GPIO_CFG_LED2 GPIO_34_GPIO34 // "pinConfig" for LD3
//
// Globals, User can modify these parameters as per usecase
//
// Number of words per transfer may be from 1 -16
uint16_t nWords = 8;
// Transfer can be happen over single or double lane
FSI_DataWidth nLanes = FSI_DATA_WIDTH_1_LANE;
// FSI Clock used for transfer
uint32_t fsiClock = 50000000;
// Frame tag used with Data/Ping transfers
FSI_FrameTag txDataFrameTag = FSI_FRAME_TAG10, txPingFrameTag = FSI_FRAME_TAG15;
// Tx Ping timer and Rx Watchdog reference counter values
uint32_t txPingTimeRefCntr = 0x1000000, rxWdTimeoutRefCntr = 0x1400000;
// Boolean flag to enable/disable Rx Frame Watchdog
bool isRxFrameWdEnable = true;
//
// This value can be anything suitable to generate a single interrupt event,
// lower values may lead WD to trigger another event even before handler of 1st
// one is not completed
//
uint32_t rxFrameWdRefCntr = 0x1000000;
//
// Globals, these are not config parameters, user are not required to edit them
//
uint16_t txEventSts = 0, rxEventSts = 0;
uint16_t *txBufAddr = 0, *rxBufAddr = 0;
uint16_t txBufData[16] = {0};
uint16_t rxBufData[16] = {0};
volatile uint32_t fsiTxInt1Received = 0,fsiTxInt2Received = 0;
volatile uint32_t fsiRxInt1Received = 0,fsiRxInt2Received = 0;
uint32_t txTimeOutCntr = 0x100000, rxTimeOutCntr = 0x100000;
uint32_t txdataFrameCntr = 0;
uint32_t rxdataFrameCntr = 0;
uint32_t dmaIntr1 = 0, dmaIntr2 = 0;
uint32_t countDMAtransfers = 0U;
volatile uint16_t i = 0, *txTempData16 = 0, *rxTempData16 = 0;
uint32_t dmaTxIntCnt = 0, dmaRxIntCnt = 0; //TODO, may remove it, just for DEBUG
uint32_t error = 0;
uint32_t TX_FRAME_DONE=0;
uint32_t RX_DATA_FRAME_DONE=0;
//
// Function Prototypes
//
static inline void compare16(uint16_t val1, uint16_t val2);
void compareBufData(uint16_t txBufIndex, uint16_t rxBufIndex, uint16_t nWords);
void disableAllFSIInterrupts(void);
void checkReceivedFrameTypeTag(FSI_FrameType type, FSI_FrameTag tag);
void initFSI(void);
void prepareTxBufData(void);
void testGPIO(void);
__interrupt void fsiTxInt1ISR(void);
__interrupt void fsiTxInt2ISR(void);
__interrupt void fsiRxInt1ISR(void);
__interrupt void fsiRxInt2ISR(void);
__interrupt void fsitxdma_isr(void);
__interrupt void fsirxdma_isr(void);
void fsitx_dma_config();
void fsirx_dma_config();
void InitFrameTagAndData();
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();
testGPIO();
//
// 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();
// Initialize basic settings for FSI
//
initFSI();
//
// Interrupts that are used in this example are re-mapped to ISR functions
// found within this file. Total 4; FSI Tx/Rx :: INT1/INT2
//
Interrupt_register(INT_FSITXA_INT1, &fsiTxInt1ISR);
Interrupt_register(INT_FSITXA_INT2, &fsiTxInt2ISR);
Interrupt_register(INT_FSIRXA_INT1, &fsiRxInt1ISR);
Interrupt_register(INT_FSIRXA_INT2, &fsiRxInt2ISR);
//
// Interrupts that are used in this example are re-mapped to ISR functions
// found within this file.
//
Interrupt_register(INT_DMA_CH2, &fsitxdma_isr);
Interrupt_register(INT_DMA_CH4, &fsirxdma_isr);
//
// Enable FSI Tx/Rx interrupts
//
Interrupt_enable(INT_FSITXA_INT1);
Interrupt_enable(INT_FSITXA_INT2);
Interrupt_enable(INT_FSIRXA_INT1);
Interrupt_enable(INT_FSIRXA_INT2);
//
// Enable FSI Tx/Rx interrupts
//
Interrupt_enable(INT_DMA_CH2);
Interrupt_enable(INT_DMA_CH4);
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
FSI_enableTxInterrupt(FSITXA_BASE, FSI_INT1, FSI_TX_EVT_FRAME_DONE);
FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_PING_FRAME);
//start handshake
// 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
//11.24 remove sending tag1 ,no EOF error, DMA works
// FSI_setTxFrameTag(FSITXA_BASE, FSI_FRAME_TAG1);
// FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_PING);
// FSI_startTxTransmit(FSITXA_BASE);
// DEVICE_DELAY_US(100);
// RX setting part
//
// Enable transmit/receive error events to be sent over INT2 line
// Overrun and Underrun conditions in Rx are not enabled as buffer pointers
// are always overwritten to first location for sending data frames.
//
FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT2, FSI_RX_EVT_CRC_ERR |
FSI_RX_EVT_EOF_ERR |
FSI_RX_EVT_TYPE_ERR);
// FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT2, FSI_RX_EVT_CRC_ERR|FSI_RX_EVT_TYPE_ERR);
FSI_disableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_PING_FRAME);
FSI_disableTxInterrupt(FSITXA_BASE, FSI_INT1, FSI_TX_EVT_FRAME_DONE);
// FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_DATA_FRAME);
DEVICE_DELAY_US(10);
//DMA configuration
//
// Initialize the dma channels for both tx and rx buffers
//
DMA_initController();
fsirx_dma_config();
fsitx_dma_config();
FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_NWORD_DATA);
//
// Setting for requested nWords and nLanes with transfers
//
FSI_setTxSoftwareFrameSize(FSITXA_BASE, nWords);
FSI_setRxSoftwareFrameSize(FSIRXA_BASE, nWords);
FSI_setTxDataWidth(FSITXA_BASE, nLanes);
FSI_setRxDataWidth(FSIRXA_BASE, nLanes);
// Enable DMA event on both FSI Tx/Rx and
FSI_setTxStartMode(FSITXA_BASE, FSI_TX_START_FRAME_CTRL_OR_UDATA_TAG);
FSI_enableTxDMAEvent(FSITXA_BASE);
FSI_enableRxDMAEvent(FSIRXA_BASE);
InitFrameTagAndData();
//
// Now, start transmitting data frames
//
// Start TX RX channels
//
//
DMA_startChannel(DMA_CH1_BASE);
DMA_forceTrigger(DMA_CH1_BASE);
DMA_startChannel(DMA_CH2_BASE);
DMA_forceTrigger(DMA_CH2_BASE);
DMA_startChannel(DMA_CH3_BASE);
DMA_startChannel(DMA_CH4_BASE);
while(1)
{
// Wait for both TX and RX channels to complete a transfer
//
while(dmaIntr1 == 0U);
dmaIntr1 = 0;
while(dmaIntr2 == 0U);
dmaIntr2 = 0;
//
// Starting location is after one word as extra write to marker location
// will lead to 1st comparison fail
//
txTempData16 = (uint16_t *)(GS0_START_ADDR + 1);
rxTempData16 = (uint16_t *)(GS2_START_ADDR + 1);
//
// verify transfers
//
for(i = 1; i < TOTAL_WORDS_IN_TRANSFER; i++)
{
compare16(*txTempData16,*rxTempData16);
txTempData16++;
rxTempData16++;
}
countDMAtransfers++;
}
}
//
// initFSI - Initializes FSI Tx/Rx with internal loopback and also sends FLUSH
// sequence.
//
void initFSI(void)
{
FSI_disableRxInternalLoopback(FSIRXA_BASE);
//
// NOTE: External loopback, Modify GPIO settings as per setup
//
GPIO_setPinConfig(GPIO_7_FSI_TXCLK);
GPIO_setPinConfig(GPIO_6_FSI_TX0);
GPIO_setPinConfig(GPIO_5_FSI_TX1);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_RXCLK);
GPIO_setPinConfig(GPIO_12_FSI_RX0);
GPIO_setPinConfig(GPIO_11_FSI_RX1);
//
// Set GP11, 12, 13(on controlcard, 33 on launchpad) to be asynchronous
// (pass through without delay)
// Default setting is to have 2 SYS_CLK cycles delay
//
GPIO_setQualificationMode(11, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(12, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(DEVICE_GPIO_PIN_FSI_RXCLK, 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);
}
//
// prepareTxBufData - Update array which is used as source to Tx data buffer
//
void prepareTxBufData(void)
{
uint16_t i;
for(i = 0; i < nWords; i++)
{
txBufData[i] = txBufData[i] + 1;
}
}
//
// 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_GROUP7);
}
//
// 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_GROUP7);
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;
// Increment number of data frames received
if((rxEventSts & FSI_RX_EVT_DATA_FRAME) != 0)
{
rxdataFrameCntr++;
FSI_readRxBuffer(FSIRXA_BASE, rxBufData, nWords, 0);
}
//
// Clear the interrupt flag and issue ACK
//
FSI_clearRxEvents(FSIRXA_BASE,rxEventSts);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// 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_GROUP7);
disableAllFSIInterrupts();
//
// INT2 line is set to fire for error events, stop immediately. Error
// is captured in rxEventSts for debug
//11.24
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);
}
}
//TODO
void testGPIO(void)
{
GPIO_setDirectionMode(TX_FRAME_DONE_IO,GPIO_DIR_MODE_OUT);
GPIO_setQualificationMode(TX_FRAME_DONE_IO,GPIO_QUAL_ASYNC);
GPIO_setPinConfig(TX_FRAME_DONE_IO_CONF);
GPIO_setDirectionMode(RX_DATA_FRAME_IO,GPIO_DIR_MODE_OUT);
GPIO_setQualificationMode(RX_DATA_FRAME_IO,GPIO_QUAL_ASYNC);
GPIO_setPinConfig(RX_DATA_FRAME_IO_CONF);
GPIO_writePin(TX_FRAME_DONE_IO,1);
GPIO_writePin(RX_DATA_FRAME_IO,1);
// Turn on LED
//
// GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);
}
//
// fsitx_dma_config - Sets up DMA channels(Ch1 and Ch2) for FSI Tx operation
//
void fsitx_dma_config()
{
//
// For the data buffers
DMA_configAddresses(DMA_CH1_BASE, txBufAddr, (uint16_t *)GS0_START_ADDR); // GS0 RAM to store Tx frame data which DMA will read
DMA_configBurst(DMA_CH1_BASE, nWords, 1, 1);
DMA_configTransfer(DMA_CH1_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 1);
DMA_configWrap(DMA_CH1_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 0, nWords, 0);
// DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_FSITXA, DMA_CFG_ONESHOT_DISABLE|
// DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_FSITXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
DMA_disableInterrupt(DMA_CH1_BASE);
DMA_enableTrigger(DMA_CH1_BASE);
//
// For the tag and userdata fields
//
DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)FSI_TX_FRAME_TAG_UDATA_REGADDR,
(uint16_t *)GS1_START_ADDR);
DMA_configBurst(DMA_CH2_BASE, 0, 0, 0); // ??0
DMA_configTransfer(DMA_CH2_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 0);
DMA_configWrap(DMA_CH2_BASE, 16, 0, 16, 0);
DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_FSITXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE |DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH2_BASE);
DMA_enableTrigger(DMA_CH2_BASE);
}
//
// fsirx_dma_config - Sets up DMA channels(Ch3 and Ch4) for FSI Rx operation
//
void fsirx_dma_config()
{
DMA_configAddresses(DMA_CH3_BASE, (uint16_t *)GS2_START_ADDR, rxBufAddr); // GS2 RAM to save received Rx frame data
DMA_configBurst(DMA_CH3_BASE, nWords, 1, 1);
DMA_configTransfer(DMA_CH3_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 1);
DMA_configWrap(DMA_CH3_BASE, nWords, 0, DMA_TRANSFER_SIZE_IN_BURSTS, 0);
DMA_configMode(DMA_CH3_BASE, DMA_TRIGGER_FSIRXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE |DMA_CFG_SIZE_16BIT);
DMA_disableInterrupt(DMA_CH3_BASE);
DMA_enableTrigger(DMA_CH3_BASE);
//
// For the tag and userdata fields
//
DMA_configAddresses(DMA_CH4_BASE,(uint16_t *)GS3_START_ADDR,
(uint16_t *)FSI_RX_FRAME_TAG_UDATA_REGADDR);
DMA_configBurst(DMA_CH4_BASE, 0, 0, 0);
DMA_configTransfer(DMA_CH4_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 0, 1);
DMA_configWrap(DMA_CH4_BASE, 16, 0, 16, 0);
DMA_configMode(DMA_CH4_BASE, DMA_TRIGGER_FSIRXA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(DMA_CH4_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH4_BASE);
DMA_enableTrigger(DMA_CH4_BASE);
}
// InitFrameTagAndData - Initializes GS0/GS1 memories to populate tag and data
// for frame transfers
//
void InitFrameTagAndData(void)
{
unsigned int i;
uint16_t *temp;
temp = (uint16_t *)GS0_START_ADDR;
for(i = 0; i < TOTAL_WORDS_IN_TRANSFER; i++)
{
// *temp = (GS0_START_ADDR + i);
*temp = i+1;
temp++;
}
temp = (uint16_t *)GS1_START_ADDR;
for(i = FSI_FRAME_TAG0; i < FSI_FRAME_TAG15; i++)
{
//
//tag and user data
//
*temp = ((0x0 + i) | ((unsigned long)(0x0 + i) << 8));
temp++;
}
}
interrupt void fsitxdma_isr(void)
{
GPIO_togglePin(TX_FRAME_DONE_IO);
dmaIntr1 = 1;
dmaTxIntCnt++;
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// compare16 - Compares two 16 bit values and increments global error flag by 1
// for mismatch
//
//TODO
interrupt void fsirxdma_isr(void)
{
GPIO_togglePin(RX_DATA_FRAME_IO);
dmaIntr2 = 1;
dmaRxIntCnt++;
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// End of File
//
//#############################################################################
//
// FILE: fsi_ex8_ext_p2pconnection_rx.c
//
// TITLE: FSI Receive in Point to Point Connection
//
//! \addtogroup driver_example_list
//! <h1>FSI P2Point Connection:Rx Side</h1>
//!
//! Example sets up FSI receiving device in a point to point connection
//! to the FSI transmitting device. Example code to set up FSI transmit device
//! is implemented in a separate file.
//!
//! In a real scenario two separate devices may power up in arbitrary order and
//! there is a need to establish a clean communication link which ensures that
//! receiver side is flushed to properly interpret the start of a new valid
//! frame.
//!
//! There is no true concept of a master or a slave node in the FSI protocol,
//! but to simplify the data flow and connection we can consider transmitting
//! device as master and receiving side as slave. Transmitting side will be
//! driver of initialization sequence.
//!
//! Handshake mechanism which must take place before actual data transmission
//! can be usecase specific; points described below can be taken as an example
//! on how to implement the handshake from receiving side -
//!
//! - Setup the receiver interrupts to detect PING type frame reception
//! - Begin the first PING loop
//! + Wait for receiver interrupt
//! + If the FSI Rx has received a PING frame with \b FSI_FRAME_TAG0, come
//! out of loop. Otherwise iterate the loop again.
//! - Begin the second PING loop
//! + Send the Flush sequence
//! + Send the PING frame with tag \bFSI_FRAME_TAG1
//! + Wait for receiver interrupt
//! + If the FSI Rx has received a PING frame with \b FSI_FRAME_TAG1, come
//! out of loop. Otherwise iterate the loop again.
//! - Now, the receiver side has received the acknowledged PING frame(tag1), so
//! it is ready for normal operation further.
//!
//! After above synchronization steps, FSI Rx can be configured as per usecase
//! i.e. nWords, lane width, enabling events etc and start the infinite
//! transfers. More details on establishing the communication link can be found
//! in device TRM.
//!
//! User can edit some of configuration parameters as per usecase, similar to
//! other examples.
//!
//! \b nWords - Number of words per transfer may be from 1 -16
//! \b nLanes - Choice to select single or double lane for frame transfers
//! \b fsiClock - FSI Clock used for transfers
//! \b txUserData - User data to be sent with Data frame
//! \b txDataFrameTag - Frame tag used for Data transfers
//! \b txPingFrameTag - Frame tag used for Ping transfers
//! \b txPingTimeRefCntr - Tx Ping timer reference counter
//! \b rxWdTimeoutRefCntr - Rx Watchdog timeout reference counter
//!
//!\b External \b Connections \n
//! For FSI external P2P connection, make below GPIO settings in
//! example code.
//! - GPIO_7 -> FSITX_CLK
//! - GPIO_6 -> FSITX_TX0
//! - GPIO_5 -> FSITX_TX1
//! - GPIO_13 (GPIO_33 on LaunchPad) -> FSIRX_CLK
//! - GPIO_12 -> FSIRX_RX0
//! - GPIO_11 -> FSIRX_RX1
//!
//! \b Watch \b Variables \n
//! - \b txdataFrameCntr Number of Data frame transmitted
//! - \b rxdataFrameCntr Number of Data frame received
//! - \b error Non zero for transmit/receive data mismatch
//!
//
//#############################################################################
// $TI Release: F28004x Support Library v1.05.00.00 $
// $Release Date: Tue Jun 26 03:10:30 CDT 2018 $
// $Copyright:
// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#define PRESCALER_VAL 2U
#define DMA_TRANSFER_SIZE_IN_BURSTS 1U
#define TOTAL_WORDS_IN_TRANSFER (DMA_TRANSFER_SIZE_IN_BURSTS * nWords)
//TODO
#define TX_FRAME_DONE_IO 31
#define TX_FRAME_DONE_IO_CONF GPIO_34_GPIO34
#define RX_DATA_FRAME_IO 34
#define RX_DATA_FRAME_IO_CONF GPIO_34_GPIO34
//#define TX_FRAME_DONE_IO 15
//#define TX_FRAME_DONE_IO_CONF GPIO_15_GPIO15
//
//#define RX_DATA_FRAME_IO 16
//#define RX_DATA_FRAME_IO_CONF GPIO_16_GPIO16
// GS0 RAM to store Tx frame data which DMA will read
#define GS0_START_ADDR 0xC100
// GS1 RAM to store Tx frame tag and Userdata
#define GS1_START_ADDR 0xE000
// GS2 RAM to save received Rx frame data
#define GS2_START_ADDR 0x10000
// GS3 RAM to save received Rx frame tag and Userdata
#define GS3_START_ADDR 0x12000
// FSI Tx/Rx Frame tag User Data register address, used by DMA channel to
// write(and trigger transfer) read userdata respectively
//
#define FSI_TX_FRAME_TAG_UDATA_REGADDR (FSITXA_BASE + FSI_O_TX_FRAME_TAG_UDATA)
#define FSI_RX_FRAME_TAG_UDATA_REGADDR (FSIRXA_BASE + FSI_O_RX_FRAME_TAG_UDATA)
//
// Globals, User can modify these parameters as per usecase
//
// Number of words per transfer may be from 1 -16
uint16_t nWords = 8;
uint16_t flag =0;
// Transfer can be happen over single or double lane
FSI_DataWidth nLanes = FSI_DATA_WIDTH_1_LANE;
// FSI Clock used for transfer
uint32_t fsiClock = 50000000;
// Frame tag used with Data/Ping transfers
FSI_FrameTag txPingFrameTag = FSI_FRAME_TAG15;
// Tx Ping timer and Rx Watchdog reference counter values
uint32_t txPingTimeRefCntr = 0x1000000, rxWdTimeoutRefCntr = 0x1400000;
// Boolean flag to enable/disable Rx Frame Watchdog
bool isRxFrameWdEnable = true;
//
// This value can be anything suitable to generate a single interrupt event,
// lower values may lead WD to trigger another event even before handler of 1st
// one is not completed
//
uint32_t rxFrameWdRefCntr = 0x1000000;
//
// Globals, these are not config parameters, user are not required to edit them
//
uint16_t txEventSts = 0, rxEventSts = 0;
uint16_t *txBufAddr = 0, *rxBufAddr = 0;
uint16_t txBufData[16] = {0};
uint16_t rxBufData[16] = {0};
volatile uint32_t fsiTxInt1Received = 0,fsiTxInt2Received = 0;
volatile uint32_t fsiRxInt1Received = 0,fsiRxInt2Received = 0;
uint32_t txTimeOutCntr = 0x100000, rxTimeOutCntr = 0x100000;
uint32_t txdataFrameCntr = 0;
uint32_t rxdataFrameCntr = 0;
//uint32_t dataFrameCntr = 0;
uint32_t dmaIntr1 = 0, dmaIntr2 = 0;
uint32_t countDMAtransfers = 0U;
volatile uint16_t i = 0, *txTempData16 = 0, *rxTempData16 = 0;
uint32_t dmaTxIntCnt = 0, dmaRxIntCnt = 0; //TODO, may remove it, just for DEBUG
uint32_t error = 0;
uint32_t RX_DATA_FRAME_DONE=0;
uint32_t TX_DATA_FRAME_DONE=0;
//
// Function Prototypes
//
static inline void compare16(uint16_t val1, uint16_t val2);
void compareBufData(uint16_t txBufIndex, uint16_t rxBufIndex, uint16_t nWords);
void disableAllFSIInterrupts(void);
void checkReceivedFrameTypeTag(FSI_FrameType type, FSI_FrameTag tag);
void initFSI(void);
void prepareTxBufData(void);
void testGPIO(void);
__interrupt void fsiTxInt1ISR(void);
__interrupt void fsiTxInt2ISR(void);
__interrupt void fsiRxInt1ISR(void);
__interrupt void fsiRxInt2ISR(void);
__interrupt void fsitxdma_isr(void);
__interrupt void fsirxdma_isr(void);
void fsitx_dma_config();
void fsirx_dma_config();
void InitFrameTagAndData();
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();
testGPIO();
//
// 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();
//
// Initialize basic settings for FSI
//
initFSI();
//
// Interrupts that are used in this example are re-mapped to ISR functions
// found within this file. Total 4; FSI Tx/Rx :: INT1/INT2
//
Interrupt_register(INT_FSITXA_INT1, &fsiTxInt1ISR);
Interrupt_register(INT_FSITXA_INT2, &fsiTxInt2ISR);
Interrupt_register(INT_FSIRXA_INT1, &fsiRxInt1ISR);
Interrupt_register(INT_FSIRXA_INT2, &fsiRxInt2ISR);
Interrupt_register(INT_DMA_CH2, &fsitxdma_isr);
Interrupt_register(INT_DMA_CH4, &fsirxdma_isr);
//
// Enable FSI Tx/Rx interrupts
//
Interrupt_enable(INT_FSITXA_INT1);
Interrupt_enable(INT_FSITXA_INT2);
Interrupt_enable(INT_FSIRXA_INT1);
Interrupt_enable(INT_FSIRXA_INT2);
Interrupt_enable(INT_DMA_CH2);
Interrupt_enable(INT_DMA_CH4);
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
// 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)
{
while(fsiRxInt1Received != 1);
compare16(rxEventSts, (FSI_RX_EVT_PING_FRAME | FSI_RX_EVT_FRAME_DONE));
checkReceivedFrameTypeTag(FSI_FRAME_TYPE_PING, FSI_FRAME_TAG0);
//
// 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;
}
while(1)
{
//
// Send the flush sequence
//
FSI_executeTxFlushSequence(FSITXA_BASE, PRESCALER_VAL);
//
// 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);
// 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;
// }
break;
}
//
// Enable transmit/receive error events to be sent over INT2 line
// Overrun and Underrun conditions in Rx are not enabled as buffer pointers
// are always overwritten to first location for sending data frames.
//
FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT2, FSI_RX_EVT_CRC_ERR |
FSI_RX_EVT_EOF_ERR |
FSI_RX_EVT_TYPE_ERR);
FSI_disableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_PING_FRAME);
FSI_disableTxInterrupt(FSITXA_BASE, FSI_INT1, FSI_TX_EVT_FRAME_DONE);
// FSI_enableRxInterrupt(FSIRXA_BASE, FSI_INT1, FSI_RX_EVT_DATA_FRAME);
DEVICE_DELAY_US(10);
//
// Initialize the dma channels for both tx and rx buffers
//
DMA_initController();
fsirx_dma_config();
fsitx_dma_config();
FSI_setTxFrameType(FSITXA_BASE, FSI_FRAME_TYPE_NWORD_DATA);
//
// Setting for requested nWords and nLanes with transfers
//
FSI_setTxSoftwareFrameSize(FSITXA_BASE, nWords);
FSI_setRxSoftwareFrameSize(FSIRXA_BASE, nWords);
FSI_setTxDataWidth(FSITXA_BASE, nLanes);
FSI_setRxDataWidth(FSIRXA_BASE, nLanes);
//
// Enable DMA event on both FSI Tx/Rx and
FSI_setTxStartMode(FSITXA_BASE, FSI_TX_START_FRAME_CTRL_OR_UDATA_TAG);
FSI_enableTxDMAEvent(FSITXA_BASE);
FSI_enableRxDMAEvent(FSIRXA_BASE);
InitFrameTagAndData();
//
// Start RX channels
//
DMA_startChannel(DMA_CH1_BASE);
DMA_startChannel(DMA_CH2_BASE);
DMA_startChannel(DMA_CH3_BASE);
DMA_forceTrigger(DMA_CH3_BASE);
DMA_startChannel(DMA_CH4_BASE);
DMA_forceTrigger(DMA_CH4_BASE);
//
// Now, start transmitting data frames
//
while(1)
{
//
// Wait for both TX and RX channels to complete a transfer
//
while(dmaIntr2 == 0U);
dmaIntr2 = 0;
while(dmaIntr1 == 0U);
dmaIntr1 = 0;
//
// Starting location is after one word as extra write to marker location
// will lead to 1st comparison fail
//
txTempData16 = (uint16_t *)(GS0_START_ADDR + 1);
rxTempData16 = (uint16_t *)(GS2_START_ADDR + 1);
//
// verify transfers
//
for(i = 1; i < TOTAL_WORDS_IN_TRANSFER; i++)
{
compare16(*txTempData16,*rxTempData16);
txTempData16++;
rxTempData16++;
}
countDMAtransfers++;
//
// Just changing the 1st entry in Tx buffer Source GS0 location as a
// marker for observing change in received data in memory view of
// debugger with each transfer
//
// *(uint16_t *)GS0_START_ADDR = (uint16_t )countDMAtransfers;
}
}
//
// initFSI - Initializes FSI Tx/Rx with internal loopback and also sends FLUSH
// sequence.
//
void initFSI(void)
{
FSI_disableRxInternalLoopback(FSIRXA_BASE);
//
// NOTE: External loopback, Modify GPIO settings as per setup
//
GPIO_setPinConfig(GPIO_7_FSI_TXCLK);
GPIO_setPinConfig(GPIO_6_FSI_TX0);
GPIO_setPinConfig(GPIO_5_FSI_TX1);
GPIO_setPinConfig(DEVICE_GPIO_CFG_FSI_RXCLK);
GPIO_setPinConfig(GPIO_12_FSI_RX0);
GPIO_setPinConfig(GPIO_11_FSI_RX1);
//
// Set GP11, 12, 13(on controlcard, 33 on launchpad) to be asynchronous
// (pass through without delay)
// Default setting is to have 2 SYS_CLK cycles delay
//
GPIO_setQualificationMode(11, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(12, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(DEVICE_GPIO_PIN_FSI_RXCLK, GPIO_QUAL_ASYNC);
FSI_performTxInitialization(FSITXA_BASE, PRESCALER_VAL);
FSI_performRxInitialization(FSIRXA_BASE);
txBufAddr = (uint16_t *)FSI_getTxBufferAddress(FSITXA_BASE);
rxBufAddr = (uint16_t *)FSI_getRxBufferAddress(FSIRXA_BASE);
}
// prepareTxBufData - Update array which is used as source to Tx data buffer
//
void prepareTxBufData(void)
{
uint16_t i;
for(i = 0; i < nWords; i++)
{
txBufData[i] = txBufData[i] + 1;
}
}
//
// 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_GROUP7);
}
//
// 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_GROUP7);
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)
{
fsiRxInt1Received = 1U;
rxEventSts = FSI_getRxEventStatus(FSIRXA_BASE);
// Increment number of data frames received
if((rxEventSts & FSI_RX_EVT_DATA_FRAME) != 0)
{
rxdataFrameCntr++;
FSI_readRxBuffer(FSIRXA_BASE, rxBufData, nWords, 0);
}
// Clear the interrupt flag and issue ACK
//
FSI_clearRxEvents(FSIRXA_BASE,rxEventSts);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// 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_GROUP7);
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);
}
}
//TODO
void testGPIO(void)
{
GPIO_setDirectionMode(TX_FRAME_DONE_IO,GPIO_DIR_MODE_OUT);
GPIO_setQualificationMode(TX_FRAME_DONE_IO,GPIO_QUAL_ASYNC);
GPIO_setPinConfig(TX_FRAME_DONE_IO_CONF);
GPIO_setDirectionMode(RX_DATA_FRAME_IO,GPIO_DIR_MODE_OUT);
GPIO_setQualificationMode(RX_DATA_FRAME_IO,GPIO_QUAL_ASYNC);
GPIO_setPinConfig(RX_DATA_FRAME_IO_CONF);
GPIO_writePin(TX_FRAME_DONE_IO,1);
GPIO_writePin(RX_DATA_FRAME_IO,1);
}
//
// fsitx_dma_config - Sets up DMA channels(Ch1 and Ch2) for FSI Tx operation
//
void fsitx_dma_config()
{
//
// For the data buffers
DMA_configAddresses(DMA_CH3_BASE, txBufAddr, (uint16_t *)GS0_START_ADDR); // GS0 RAM to store Tx frame data which DMA will read
DMA_configBurst(DMA_CH3_BASE, nWords, 1, 1);
DMA_configTransfer(DMA_CH3_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 1);
DMA_configWrap(DMA_CH3_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 0, nWords, 0);
DMA_configMode(DMA_CH3_BASE, DMA_TRIGGER_FSITXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
DMA_disableInterrupt(DMA_CH3_BASE);
DMA_enableTrigger(DMA_CH3_BASE);
//
// For the tag and userdata fields
//
DMA_configAddresses(DMA_CH4_BASE, (uint16_t *)FSI_TX_FRAME_TAG_UDATA_REGADDR,
(uint16_t *)GS1_START_ADDR);
DMA_configBurst(DMA_CH4_BASE, 0, 0, 0);// ??0
DMA_configTransfer(DMA_CH4_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 0);
DMA_configWrap(DMA_CH4_BASE, 16, 0, 16, 0);
DMA_configMode(DMA_CH4_BASE, DMA_TRIGGER_FSITXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE|DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(DMA_CH4_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH4_BASE);
DMA_enableTrigger(DMA_CH4_BASE);
}
//
// fsirx_dma_config - Sets up DMA channels(Ch3 and Ch4) for FSI Rx operation
//
void fsirx_dma_config()
{
DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)GS2_START_ADDR, rxBufAddr); // GS2 RAM to save received Rx frame data
DMA_configBurst(DMA_CH1_BASE, nWords, 1, 1);
DMA_configTransfer(DMA_CH1_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 1, 1);
DMA_configWrap(DMA_CH1_BASE, nWords, 0, DMA_TRANSFER_SIZE_IN_BURSTS, 0);
// DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_FSIRXA, DMA_CFG_ONESHOT_DISABLE|
// DMA_CFG_CONTINUOUS_ENABLE|DMA_CFG_SIZE_16BIT);
DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_FSIRXA, DMA_CFG_ONESHOT_DISABLE|
DMA_CFG_CONTINUOUS_DISABLE|DMA_CFG_SIZE_16BIT);
DMA_disableInterrupt(DMA_CH1_BASE);
DMA_enableTrigger(DMA_CH1_BASE);
//
// For the tag and userdata fields
//
DMA_configAddresses(DMA_CH2_BASE,(uint16_t *)GS3_START_ADDR,
(uint16_t *)FSI_RX_FRAME_TAG_UDATA_REGADDR);
DMA_configBurst(DMA_CH2_BASE, 0, 0, 0);
DMA_configTransfer(DMA_CH2_BASE, DMA_TRANSFER_SIZE_IN_BURSTS, 0, 1);
DMA_configWrap(DMA_CH2_BASE, 16, 0, 16, 0);
DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_FSIRXA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH2_BASE);
DMA_enableTrigger(DMA_CH2_BASE);
}
interrupt void fsitxdma_isr(void)
{
GPIO_togglePin(TX_FRAME_DONE_IO);
dmaIntr1 = 1;
dmaTxIntCnt++;
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
interrupt void fsirxdma_isr(void)
{
GPIO_togglePin(RX_DATA_FRAME_IO);
dmaIntr2 = 1;
dmaRxIntCnt++;
// DMA_forceTrigger(DMA_CH3_BASE);
// DMA_forceTrigger(DMA_CH4_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// InitFrameTagAndData - Initializes GS0/GS1 memories to populate tag and data
// for frame transfers
//
void InitFrameTagAndData(void)
{
unsigned int i;
uint16_t *temp;
temp = (uint16_t *)GS0_START_ADDR;
for(i = 0; i < TOTAL_WORDS_IN_TRANSFER; i++)
{
*temp = i+1;
temp++;
}
temp = (uint16_t *)GS1_START_ADDR;
for(i = FSI_FRAME_TAG0; i < FSI_FRAME_TAG15; i++)
{
//
//tag and user data
//
*temp = ((0x0 + i) | ((unsigned long)(0x0 + i) << 8));
temp++;
}
}
//
// End of File
//