Part Number: TMS320F280039C
Hello,
I've used the SPI DMA ex5 and ex7 to create a SPI slave configuration that uses DMA to receive and transfer data to the master. I have a couple of questions, then I will share my SPI setup code at the bottom for you to see if maybe I did something to cause these issues.
1) I am sending 47 bytes of 0xFF from slave to master and as you can see I have some noise, and some of the bytes are changing as can seen below on the scope trace. Could anything in my configuration cause this? I changed from sending the data I want to 47 bytes of all 0xFF because I suspected I had some noise changing my data. Both transfer and receive are working but on both sides, I have noise changing bytes of data.

This is my buffer being sent linked to TxDMA - as you can see it is 0xFF - so the data being sent is what I expect


2) A setup question - Why does the slave need a baud rate in SPI_setConfig()? Should it not just transmit data on the rising edge of the clock?
Init / Setup Code -
void SPISlave_Init(GE_Primary_Container_t *pContainer)
{
// Init Control Variables
pContainer->mpSpiSlave->mRepaCommsUp = false;
pContainer->mpSpiSlave->mRepaSlaveRxTimeout = 0;
pContainer->mpSpiSlave->mRepaLostCommsCnt = 0;
pContainer->mpSpiSlave->mNextMux = 1;
pContainer->mpSpiSlave->mGoodData = 0;
pContainer->mpSpiSlave->mBadData = 0;
pContainer->isTransferCompleted = false;
pContainer->isBufferCompleted = false;
// Init buffers
memset(&DMATXbuff, 0U, sizeof(DMATXbuff));
memset(&DMARXbuff, 0U, sizeof(DMARXbuff));
SPI_disableModule(REPA_DSPI_SLAVE_BASEADDR);
SPI_setConfig(REPA_DSPI_SLAVE_BASEADDR, DEVICE_LSPCLK_FREQ, SPI_PROT_POL1PHA0,
SPI_MODE_SLAVE, 1562500U, 8U);
SPI_disableFIFO(REPA_DSPI_SLAVE_BASEADDR);
SPI_disableLoopback(REPA_DSPI_SLAVE_BASEADDR);
SPI_setEmulationMode(REPA_DSPI_SLAVE_BASEADDR, SPI_EMULATION_FREE_RUN);
SPI_setSTESignalPolarity(REPA_DSPI_SLAVE_BASEADDR, SPI_STE_ACTIVE_LOW);
SPI_enableModule(REPA_DSPI_SLAVE_BASEADDR);
setupSPI_DMA_Handler(REPA_DSPI_SLAVE_BASEADDR, 8U, DMA_CH5_BASE, DMA_CH6_BASE);
SPISlave_TransferEDMA(pContainer);
}
When I start a transfer I call this function:
void SPISlave_ResetSPIDMA()
{
//Disabling DMA transmission channel trigger
DMA_disableTrigger(REPA_DSPI_SLAVE_BASEADDR);
//Disabling DMA reception channel trigger
DMA_disableTrigger(REPA_DSPI_SLAVE_BASEADDR);
//Disabling SPI FIFOs
SPI_disableFIFO(REPA_DSPI_SLAVE_BASEADDR);
//Re-enabling SPI FIFO
SPI_enableFIFO(REPA_DSPI_SLAVE_BASEADDR);
SPI_setFIFOInterruptLevel(REPA_DSPI_SLAVE_BASEADDR, SPI_FIFO_TXEMPTY, SPI_FIFO_RXFULL);
// DMA channel softreset
EALLOW;
HWREGH(DMA_CH5_BASE + DMA_O_CONTROL) |= DMA_CONTROL_SOFTRESET;
NOP; //One cycle mandatory delay required to access any other DMA register
HWREGH(DMA_CH6_BASE + DMA_O_CONTROL) |= DMA_CONTROL_SOFTRESET;
NOP; //One cycle mandatory delay required to access any other DMA register
EDIS;
SPI_DMA_Handle.pSPITXDMA->currentpointer = 0;
SPI_DMA_Handle.pSPIRXDMA->currentpointer = 0;
//Disabling DMA transmission channel trigger
DMA_enableTrigger(DMA_CH5_BASE);
//Disabling DMA reception channel trigger
DMA_enableTrigger(DMA_CH6_BASE);
}
int32_t SPISlave_TransferEDMA(GE_Primary_Container_t *pContainer)
{
SPI_DMA_Handle.TransactionStatus = SPI_DMA_TRANSACTION_STARTED;
SPI_DMA_Handle.TransactionType = SPI_DMA_READ_TRANSACTION;
// Reset SPI
SPISlave_ResetSPIDMA();
// Clear sData
memset(&sData, 0U, sizeof(sData));
// Clear receive buffer
hal.mpMemset(&pContainer->mpSpiBuffer->mSlaveReceiveBuffer, 0U, sizeof(pContainer->mpSpiBuffer->mSlaveReceiveBuffer));
// DMA write
// Copy SendBuffer
int i = 0;
for(i = 0; i < TRANSFER_SIZE; i++)
{
sData[i] = pContainer->mpSpiBuffer->mSlaveSendBuffer[i];
}
// Send data to be programmed
SPI_DMA_Transmit_NBytes(&sData, TRANSFER_SIZE, &SPI_DMA_Handle);
// Configure SPI / DMA and initiate SPI transaction
SPI_DMA_StartTransaction(&SPI_DMA_Handle, SPI_DMA_Handle.charlength, NO_DELAY);
return 1;
}
Then I have 2 DMA interrupt ISRs
//
// DMA Channel 5 ISR
//
__interrupt void dmaTXISR(void)
{
dmaTXISRRoutine(&gContainer);
return;
}
//
// DMA Channel 6 ISR
//
__interrupt void dmaRXISR(void)
{
dmaRXISRRoutine(&gContainer);
}
And I am using spi_DMA.c/.h libraries very similar to the SPI DMA EEPROM example
//#############################################################################
//
// FILE: spi_DMA.c
//
// TITLE: C28x-SPI source file when using DMA with SPI
//
//#############################################################################
//
//
// $Copyright:
// Copyright (C) 2021 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 "spi_slave.h"
#include "spi_DMA.h"
//Global variables
uint16_t DMATXbuff[BUFFER_SIZE];
uint16_t DMARXbuff[BUFFER_SIZE];
#pragma DATA_SECTION(DMATXbuff, "ramgs0"); // map the TX data to memory
#pragma DATA_SECTION(DMARXbuff, "ramgs0"); // map the RX data to memory
struct SPI_DMA_handle SPI_DMA_Handle;
struct DMA_CH SPITXDMA;
struct DMA_CH SPIRXDMA;
void SPI_DMA_ByteTransaction(uint16_t data, struct SPI_DMA_handle *pSPI_DMA_Handle)
{
//wordSize for a byte is 8 (because 1 byte = 8 bits)
uint16_t wordSize = 8U;
ASSERT(data < (1<<wordSize));
//Fill the TXbuffer with data to be transmitted
uint16_t *pbuffer = pSPI_DMA_Handle->pSPITXDMA->pbuffer;
uint16_t currentpointer = pSPI_DMA_Handle->pSPITXDMA->currentpointer;
pbuffer[currentpointer++] = data;
pSPI_DMA_Handle->pSPITXDMA->currentpointer = currentpointer;
}
void SPI_DMA_NBytesTransaction(uint16_t *pTXbuffer, uint16_t numOfbytes, struct SPI_DMA_handle *pSPI_DMA_Handle)
{
uint16_t *pbuffer = pSPI_DMA_Handle->pSPITXDMA->pbuffer;
uint16_t currentpointer = pSPI_DMA_Handle->pSPITXDMA->currentpointer;
uint16_t i=0;
for(i=0;i<numOfbytes;i++)
{
if(pTXbuffer == NULL)
{
//Fill the TXbuffer with dummy data to be transmitted
//Here the dummy data is 0xFFFF
pbuffer[currentpointer++] = 0xFFFF;
}
else
{
//Fill the TXbuffer
pbuffer[currentpointer++] = 0xFFFF;
//pbuffer[currentpointer++] = pTXbuffer[i];
}
}
pSPI_DMA_Handle->pSPITXDMA->currentpointer = currentpointer;
}
void SPI_DMA_16bitWordTransaction(uint16_t data, struct SPI_DMA_handle *pSPI_DMA_Handle)
{
//wordSize is 16
uint16_t wordSize = 16U;
ASSERT(data < ((uint32_t)1<<wordSize));
//Fill the TXbuffer with data to be transmitted
uint16_t *pbuffer = pSPI_DMA_Handle->pSPITXDMA->pbuffer;
uint16_t currentpointer = pSPI_DMA_Handle->pSPITXDMA->currentpointer;
pbuffer[currentpointer++] = (data & 0xFF00) >> 8;
pbuffer[currentpointer++] = (data & 0xFF);
pSPI_DMA_Handle->pSPITXDMA->currentpointer = currentpointer;
}
void SPI_DMA_24bitWordTransaction(uint32_t data, struct SPI_DMA_handle *pSPI_DMA_Handle)
{
//wordSize is 24
uint16_t wordSize = 24U;
ASSERT(data < ((uint32_t)1<<wordSize));
//Fill the TXbuffer with data to be transmitted
uint16_t *pbuffer = pSPI_DMA_Handle->pSPITXDMA->pbuffer;
uint16_t currentpointer = pSPI_DMA_Handle->pSPITXDMA->currentpointer;
pbuffer[currentpointer++] = (data & 0xFF0000) >> 16U;
pbuffer[currentpointer++] = (data & 0x00FF00) >> 8U;
pbuffer[currentpointer++] = (data & 0x0000FF);
pSPI_DMA_Handle->pSPITXDMA->currentpointer = currentpointer;
}
void SPI_DMA_StartTransaction(struct SPI_DMA_handle *pSPI_DMA_Handle, uint16_t charlength, uint16_t txdly)
{
uint16_t i = 0;
ASSERT((charlength >= 1U) && (charlength <= 16U));
pSPI_DMA_Handle->TransactionStatus = SPI_DMA_TRANSACTION_STARTED;
uint32_t spibase = pSPI_DMA_Handle->spibase;
uint32_t dmaTXbase = pSPI_DMA_Handle->pSPITXDMA->dmach;
uint32_t dmaRXbase = pSPI_DMA_Handle->pSPIRXDMA->dmach;
uint16_t *pTXbuffer = pSPI_DMA_Handle->pSPITXDMA->pbuffer;
uint16_t *pRXbuffer = pSPI_DMA_Handle->pSPIRXDMA->pbuffer;
uint16_t currentpointer = pSPI_DMA_Handle->pSPITXDMA->currentpointer;
ASSERT(SPI_isBaseValid(spibase));
uint16_t maxTransactionSize = currentpointer;
pSPI_DMA_Handle->pSPITXDMA->maxTransactionSize = maxTransactionSize;
/********************************************************************************/
// SPI configuration
/********************************************************************************/
SPI_setcharLength(spibase, charlength);
uint16_t TXbuff_pos = 0;
for(i=1;i<=maxTransactionSize;i++)
{
pTXbuffer[TXbuff_pos] = pTXbuffer[TXbuff_pos] << (16 - charlength);
TXbuff_pos++;
}
//Reset the TX / RX FIFO buffers to default state
SPI_disableFIFO(spibase); //Disable FIFO register
SPI_enableFIFO(spibase); //Enable FIFO register
//Configure the FIFO Transmit Delay
SPI_setTxFifoTransmitDelay(spibase, txdly);
uint16_t burst_size = 0;
uint16_t transfer_size = 1;
//Determine the number of 16-level words from number of words to be transmitted / received
uint16_t numofSixteenWords = maxTransactionSize / SPI_FIFO_TXFULL;
//Determine the number of remaining words from number of words to be transmitted / received
uint16_t remainingWords = maxTransactionSize % SPI_FIFO_TXFULL;
if(numofSixteenWords)
{
SPI_setFIFOInterruptLevel(spibase, SPI_FIFO_TXEMPTY, SPI_FIFO_RXFULL);
burst_size = 16U;
transfer_size = numofSixteenWords;
}
else
{
SPI_setFIFOInterruptLevel(spibase, SPI_FIFO_TXEMPTY, (SPI_RxFIFOLevel)remainingWords);
burst_size = remainingWords;
transfer_size = 1;
}
SPI_enableInterrupt(spibase, SPI_INT_RXFF);
// Initialize DMA
DMA_initController();
/********************************************************************************/
// DMA TX Channel configuration
/********************************************************************************/
ASSERT(DMA_isBaseValid(dmaTXbase));
uint32_t dmaTX_IntNum = selectDMA_PIE_Interrupt(dmaTXbase);
Interrupt_register(dmaTX_IntNum, &dmaTXISR);
uint16_t *psrcAddr = pTXbuffer;
uint16_t *pdestAddr = (uint16_t *)(spibase + SPI_O_TXBUF);
DMA_configAddresses(dmaTXbase, pdestAddr, psrcAddr);
DMA_configBurst(dmaTXbase, burst_size, 1, 0);
DMA_configTransfer(dmaTXbase, transfer_size, 1, 0);
DMA_configMode(dmaTXbase, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
DMA_CFG_SIZE_16BIT);
DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);
// DMA SW trigger to start SPI transaction using DMA
DMA_enableTrigger(dmaTXbase);
/********************************************************************************/
// DMA RX Channel configuration
/********************************************************************************/
ASSERT(DMA_isBaseValid(dmaRXbase));
uint32_t dmaRX_IntNum = selectDMA_PIE_Interrupt(dmaRXbase);
Interrupt_register(dmaRX_IntNum, &dmaRXISR);
psrcAddr = (uint16_t *)(spibase + SPI_O_RXBUF);
pdestAddr = pRXbuffer;
//Enable RXFIFO interrupt to ensure DMA RX channel is triggered
SPI_enableInterrupt(spibase, SPI_INT_RXFF);
DMA_configAddresses(dmaRXbase, pdestAddr, psrcAddr);
DMA_configBurst(dmaRXbase, BURST, 0, 1);
DMA_configTransfer(dmaRXbase, TRANSFER, 0, 1);
DMA_configMode(dmaRXbase, DMA_TRIGGER_SPIARX, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
//
// Configure DMA RX interrupts
//
DMA_setInterruptMode(dmaRXbase, DMA_INT_AT_END);
DMA_enableInterrupt(dmaRXbase);
DMA_enableTrigger(dmaRXbase);
pSPI_DMA_Handle->pSPITXDMA->currentpointer = burst_size;
pSPI_DMA_Handle->pSPIRXDMA->currentpointer = burst_size;
//DMA SW trigger to initiate SPI transaction
DMA_forceTrigger(dmaTXbase);
}
//
// Function used to select correct dma channel based base address provided
//
uint32_t selectDMA_PIE_Interrupt(uint32_t dmachbase)
{
uint32_t DMA_Channel = 0;
switch(dmachbase)
{
case DMA_CH1_BASE:
DMA_startChannel(DMA_CH1_BASE);
DMA_Channel = INT_DMA_CH1;
Interrupt_enable(DMA_Channel);
break;
case DMA_CH2_BASE:
DMA_startChannel(DMA_CH2_BASE);
DMA_Channel = INT_DMA_CH2;
Interrupt_enable(DMA_Channel);
break;
case DMA_CH3_BASE:
DMA_startChannel(DMA_CH3_BASE);
DMA_Channel = INT_DMA_CH3;
Interrupt_enable(DMA_Channel);
break;
case DMA_CH4_BASE:
DMA_startChannel(DMA_CH4_BASE);
DMA_Channel = INT_DMA_CH4;
Interrupt_enable(DMA_Channel);
break;
case DMA_CH5_BASE:
DMA_startChannel(DMA_CH5_BASE);
DMA_Channel = INT_DMA_CH5;
Interrupt_enable(DMA_Channel);
break;
case DMA_CH6_BASE:
DMA_startChannel(DMA_CH6_BASE);
DMA_Channel = INT_DMA_CH6;
Interrupt_enable(DMA_Channel);
break;
}
return(DMA_Channel);
}
//
// Function used to update SPI_DMA_Handle parameters
//
void setupSPI_DMA_Handler(uint32_t spibase, uint16_t charlength, uint32_t dmaTXbase, uint32_t dmaRXbase)
{
///////////////////////////////////////////
// SPI configuration //
///////////////////////////////////////////
SPI_DMA_Handle.spibase = spibase;
SPI_DMA_Handle.charlength = charlength;
SPI_DMA_Handle.pSPITXDMA = &SPITXDMA;
SPI_DMA_Handle.pSPIRXDMA = &SPIRXDMA;
///////////////////////////////////////////
// DMA Transmit channel configuration //
///////////////////////////////////////////
SPITXDMA.dmach = dmaTXbase;
SPITXDMA.pbuffer = &DMATXbuff[0];
SPITXDMA.currentpointer = 0;
///////////////////////////////////////////
// DMA Receive channel configuration //
///////////////////////////////////////////
SPIRXDMA.dmach = dmaRXbase;
SPIRXDMA.pbuffer = &DMARXbuff[0];
SPIRXDMA.currentpointer = 0;
}
void dmaTXISRRoutine(GE_Primary_Container_t *pContainer)
{
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
return;
}
void dmaRXISRRoutine(GE_Primary_Container_t *pContainer)
{
uint32_t spibase = SPI_DMA_Handle.spibase;
uint32_t dmaTXbase = SPI_DMA_Handle.pSPITXDMA->dmach;
uint32_t dmaRXbase = SPI_DMA_Handle.pSPIRXDMA->dmach;
uint16_t remainingWords = SPI_DMA_Handle.pSPITXDMA->maxTransactionSize - SPI_DMA_Handle.pSPITXDMA->currentpointer;
uint16_t burst_size = 0;
uint16_t srcAddr = HWREGH(dmaTXbase + DMA_O_SRC_ADDR_ACTIVE);
uint16_t destAddr = HWREGH(dmaRXbase + DMA_O_DST_ADDR_ACTIVE);
DMA_configSourceAddress(dmaTXbase, (const void *)srcAddr);
DMA_configDestAddress(dmaRXbase, (const void *)destAddr);
//If the remainingWords is non-zero and less than FIFO level (16U), then reconfigure
//DMA burst and RX FIFO level
if(remainingWords > 0 && remainingWords < 16)
{
burst_size = remainingWords;
SPI_DMA_Handle.pSPITXDMA->currentpointer += remainingWords;
SPI_setFIFOInterruptLevel(spibase, SPI_FIFO_TXEMPTY, (SPI_RxFIFOLevel)remainingWords);
DMA_configBurst(dmaTXbase, burst_size, 1, 0);
DMA_configBurst(dmaRXbase, burst_size, 0, 1);
}
if(remainingWords >= 16)
{
SPI_DMA_Handle.pSPITXDMA->currentpointer += 16U;
}
//If no remainingWords, pull chip select high and stop DMA CH6
if(remainingWords == 0)
{
//Reset currentpointer for both TX / RX
SPI_DMA_Handle.pSPITXDMA->currentpointer = 0;
SPI_DMA_Handle.pSPIRXDMA->currentpointer = 0;
//Stop both TX / RX DMA channels
DMA_stopChannel(dmaTXbase);
DMA_stopChannel(dmaRXbase);
if(SPI_DMA_Handle.TransactionType == SPI_DMA_READ_TRANSACTION)
{
uint16_t numRXbytes = SPI_DMA_Handle.pSPITXDMA->maxTransactionSize - SPI_DMA_Handle.offsetRXbuff;
int16_t i = numRXbytes-1;
uint16_t *pReceiveBuffer = SPI_DMA_Handle.pSPIRXDMA->pbuffer + SPI_DMA_Handle.offsetRXbuff;
SPI_DMA_Handle.pSPIRXDMA->pbuffer = pReceiveBuffer;
//When the number of RXbytes is less than 4
//package data into RX data based on endianess
while(i>=0 && numRXbytes<=4)
{
if(SPI_DMA_Handle.endianess == SPI_DATA_BIG_ENDIAN)
{
SPI_DMA_Handle.RXdata |= (uint32_t)pReceiveBuffer[i] << (i * SPI_DMA_Handle.charlength);
}
else
{
SPI_DMA_Handle.RXdata |= (uint32_t)pReceiveBuffer[numRXbytes-i-1] << (i * SPI_DMA_Handle.charlength);
}
i--;
}
// Fill receive buffer
for(i = 0; i < TRANSFER_SIZE; i++)
{
pContainer->mpSpiBuffer->mSlaveReceiveBuffer[i] = (DMARXbuff[i] & 0x00FF); // Upper 8 bits of 8 bit SPI are garbage and can be discarded
}
pContainer->isBufferCompleted = true;
}
//If function pointer in not equal to NULL.
//Execute next function
SPI_DMA_Handle.TransactionStatus = SPI_DMA_TRANSACTION_COMPLETE;
// Mark transfer complete
pContainer->isTransferCompleted = true;
}
else
{ //We still have remaining transactions
DMA_forceTrigger(dmaTXbase);
}
//Acknowledge CPU interrupt flag
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
return;
}
//#############################################################################
//
// FILE: spi_DMA.h
//
// TITLE: C28x-SPI header file when using DMA with SPI
//
//#############################################################################
//
//
// $Copyright:
// Copyright (C) 2021 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 "spi.h"
#include "dma.h"
#include "container.h"
#include "repa_spi.h"
#ifndef SPI_DMA_H
#define SPI_DMA_H
//
// Defines
//
#define FIFO_LVL 16 // FIFO interrupt level
#define BURST 16 // 16 words / burst
#define TRANSFER 1 // 4 burts / transfer
#define NULL ((void *)0x0)
typedef enum
{
SPI_DMA_TRANSACTION_IDLE = 0x0000,
SPI_DMA_TRANSACTION_STARTED = 0x0BAD,
SPI_DMA_TRANSACTION_COMPLETE = 0x55AA,
}SPI_TransactionStatus;
typedef enum
{
SPI_DMA_WRITE_ENABLE = 0x0000,
SPI_DMA_READ_STATUS_REGISTER = 0x0001,
SPI_DMA_WRITE_TRANSACTION = 0x0002,
SPI_DMA_READ_TRANSACTION = 0x0003,
}SPI_TransactionType;
#define BUFFER_SIZE 47
#define DUMMY_DATA 0xFF
#define NO_DELAY 0
extern uint16_t DMATXbuff[BUFFER_SIZE];
extern uint16_t DMARXbuff[BUFFER_SIZE];
extern struct DMA_CH SPITXDMA;
extern struct DMA_CH SPIRXDMA;
struct DMA_CH
{
uint32_t dmach;
uint16_t *pbuffer;
uint16_t currentpointer;
uint16_t maxTransactionSize;
};
typedef void (*functionPointer)(void);
typedef struct SPI_DMA_handle
{
uint32_t spibase; //Specifies SPI base address
uint16_t charlength; //Specifies SPI character length
struct DMA_CH *pSPITXDMA; //Pointer to SPITXDMA
struct DMA_CH *pSPIRXDMA; //Pointer to SPIRXDMA
functionPointer pFunction[5U]; //Array of function pointer which executes
//different command sequence
uint16_t FunctionCount; //Counter which specifies which function
//command sequence
SPI_TransactionType TransactionType; //Stores the type of EEPROM transaction
SPI_TransactionStatus TransactionStatus;//Stores the status of SPI transaction
uint16_t expectedOutput; //Output expected from EEPROM
uint16_t offsetRXbuff; //Offset pointer for RXbuffer
uint32_t RXdata; //Stores received data
SPI_endianess endianess; //Stores endianess of transaction
}SPI_DMA_handle;
extern struct SPI_DMA_handle SPI_DMA_Handle;
//*****************************************************************************
//! This macro can be used to fill up the transmit buffer to transmit a byte.
//!
//! \param data specifies the data to be transmitted
//! \param pSPI_DMA_Handle specifies SPI / DMA transaction parameters
//!
//! \return None.
//
//*****************************************************************************
#define SPI_DMA_TransmitByte(data, pSPI_DMA_Handle) SPI_DMA_ByteTransaction(data, pSPI_DMA_Handle)
//*****************************************************************************
//! This macro can be used to fill up the transmit buffer to transmit 16-bits
//!
//! \param data specifies the data to be transmitted
//! \param pSPI_DMA_Handle specifies SPI / DMA transaction parameters
//!
//! \return None.
//
//*****************************************************************************
#define SPI_DMA_Transmit16bitWord(data, pSPI_DMA_Handle) SPI_DMA_16bitWordTransaction(data, pSPI_DMA_Handle)
//*****************************************************************************
//! This macro can be used toa fill up the transmit buffer to transmit N-bytes
//!
//! \param pTXbuffer specifies the start address of transmit buffer
//! \param numOfbytes specifies the number of bytes to be transmitted
//! \param pSPI_DMA_Handle specifies SPI / DMA transaction parameters
//!
//! \return None.
//
//*****************************************************************************
#define SPI_DMA_Transmit_NBytes(pTXbuffer, numOfbytes, pSPI_DMA_Handle) SPI_DMA_NBytesTransaction(pTXbuffer, numOfbytes, pSPI_DMA_Handle)
#define SPI_DMA_ReceiveByte(dummyData, pSPI_DMA_Handle) SPI_DMA_ByteTransaction(dummyData, pSPI_DMA_Handle)
#define SPI_DMA_Receive16bitWord(dummydata, pSPI_DMA_Handle) SPI_DMA_16bitWordTransaction(dummydata, pSPI_DMA_Handle)
//*****************************************************************************
//! This macro can be used to receive N-bytes
//!
//! \param numOfbytes specifies the number of bytes to be transmitted
//! \param pSPI_DMA_Handle specifies SPI / DMA transaction parameters
//!
//! \return None.
//
//*****************************************************************************
#define SPI_DMA_Receive_NBytes(numOfbytes, pSPI_DMA_Handle) SPI_DMA_NBytesTransaction(NULL, numOfbytes, pSPI_DMA_Handle)
extern void SPI_DMA_ByteTransaction(uint16_t data, struct SPI_DMA_handle *pSPI_DMA_Handle);
extern void SPI_DMA_16bitWordTransaction(uint16_t data, struct SPI_DMA_handle *pSPI_DMA_Handle);
//*****************************************************************************
//! This function can be used to configure SPI_DMA_Handle structure
//!
//! \param spibase specifies the SPI module base address.
//! \param endianess specifies whether endianess of received data
//! \param charlength specifies character length of SPI transaction
//! \param dmaTXbase specifies the DMA base address to act DMA TX channel
//! \param dmaRXbase specifies the DMA base address to act DMA RX channel
//!
//! SPI_DMA_Handle configuration made by this function are:
//! 1) SPI module, DMA TX / RX channel
//! 2) Reset current pointer for TX / RX transaction
//! 3) Configure TXbuff and RXbuff
//!
//! \return None.
//
//*****************************************************************************
void setupSPI_DMA_Handler(uint32_t spibase, uint16_t charlength, uint32_t dmaTXbase, uint32_t dmaRXbase);
//*****************************************************************************
//! This function configures DMA / SPI based on pSPI_DMA_Handle and starts
//! SPI transaction using DMA
//!
//! \param pSPI_DMA_Handle specifies the SPI module base address.
//! \param charLength specifies the SPI character length
//! \param txDelay specifies the number of serial clock cycles delay time after
//! completion of perious word
//!
//! \return None.
//
//*****************************************************************************
extern void SPI_DMA_StartTransaction(struct SPI_DMA_handle *pSPI_DMA_Handle, uint16_t charlength, uint16_t txdly);
extern void SPI_DMA_NBytesTransaction(uint16_t *pTXbuffer, uint16_t numOfbytes, struct SPI_DMA_handle *pSPI_DMA_Handle);
extern uint32_t selectDMA_PIE_Interrupt(uint32_t dmabase);
__interrupt void dmaTXISR(void);
__interrupt void dmaRXISR(void);
void dmaTXISRRoutine(GE_Primary_Container_t *pContainer);
void dmaRXISRRoutine(GE_Primary_Container_t *pContainer);
#endif









































