Tom,
Based off your example I2C program, I have been working on a demo to use the hardware SPI with and without EDMA.
My demo is working well - with the exception when my transmit and receive arrays are defined outside of my main() routine.
My example code is below.
- I have MISO and MOSI jumped together on JP12
- The DMA transfers using LocalTxBuff / LocalRxBuff defined in main() ARE reliable.
- The DMA transfers using TxBuff_global / RxBuff_global are NOT reliable.
- The DMA transfers using the gather_buffer[] are reliable.
I wish I could post a screen capture of the console window here, but I don't think I have permissions to add attachments.
Basically, when transferring with the Local and Gather buffers, the Rx Buffer always gets filled with a copy of the contents of the Tx Buffer.
When using the _global buffers, however, this is very hit and miss.
-Sometimes the Rx buffer gets filled.
-Sometimes it partially gets filled.
-Sometimes it doesn't get filled with anything.
Code: Select all
#include "KMotionDef.h"
#include "TI_SOC_Lib\hw_types.h"
#include "TI_SOC_Lib\soc_C6748.h"
#include "TI_SOC_Lib\Kogna_edma.c"
#define EDMA_BASE SOC_EDMA30CC_0_REGS
#define SPI_BASE_ADDR SOC_SPI_1_REGS
#define SPIGCR0 0x0
#define SPIGCR1 0x4
#define SPIINT0 0x8
#define SPIFLG 0x10
#define SPIPC0 0x14
#define SPIPC1 0x18
#define SPIDAT0 0x38
#define SPIDAT1 0x3C
#define SPIBUF 0x40
#define SPIEMU 0x44
#define SPIDELAY 0x48
#define SPIFMT0 0x50
void Init_SPI_Hardware();
void Print_SPI_Registers();
void SendSpiChar(unsigned char char2tx);
void SPI_Txfer(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes);
void SPI_Txfer_DMA(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes);
void EdmaConfigTxSpi(unsigned char *Addr, int nBytes);
void EdmaConfigRxSPI(unsigned char *Addr, int nBytes);
void fill_buffs(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes);
void print_buffs(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes);
#define NUM_TEST_BYTES 32
unsigned char TxBuff_global[NUM_TEST_BYTES];
unsigned char RxBuff_global[NUM_TEST_BYTES];
int main(void)
{
int i;
unsigned char LocalTxBuff[NUM_TEST_BYTES];
unsigned char LocalRxBuff[NUM_TEST_BYTES];
SPI_SetMode(0, 0);
SPI_SetMode(1, 0);
SPI_SetMode(3, 0);
Init_SPI_Hardware();
printf("SPI/DMA Test with LOCAL Buffer...\n");
fill_buffs(LocalTxBuff, LocalRxBuff, NUM_TEST_BYTES);
SPI_Txfer_DMA(LocalTxBuff, LocalRxBuff, NUM_TEST_BYTES);
print_buffs(LocalTxBuff, LocalRxBuff, NUM_TEST_BYTES);
printf("SPI/DMA Test with GLOBAL Buffer...\n");
fill_buffs(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
SPI_Txfer_DMA(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
print_buffs(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
printf("SPI/DMA Test with GATHER Buffer...\n");
fill_buffs(&gather_buffer[0], &gather_buffer[NUM_TEST_BYTES], NUM_TEST_BYTES);
SPI_Txfer_DMA(&gather_buffer[0], &gather_buffer[NUM_TEST_BYTES], NUM_TEST_BYTES);
print_buffs(&gather_buffer[0], &gather_buffer[NUM_TEST_BYTES], NUM_TEST_BYTES);
Delay_sec(0.15);
printf("Testing Non DMA SPI Transfers...\n");
fill_buffs(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
SPI_Txfer(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
print_buffs(TxBuff_global, RxBuff_global, NUM_TEST_BYTES);
}
void fill_buffs(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes)
{
int i;
for(i=0; i<nBytes; i++)
{
tx_buff[i] = i;
rx_buff[i] = 0xFF;
}
}
void SPI_Txfer(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes)
{
HWREG(SPI_BASE_ADDR + SPIINT0) &= (0xFFFFFFFF & 0<<16);
int i=0;
for(i=0; i<nBytes; i++)
{
SendSpiChar(tx_buff[i]);
while( (HWREG(SPI_BASE_ADDR + SPIFLG) & 1<<8)==0);
rx_buff[i]=HWREG(SPI_BASE_ADDR + SPIBUF);
}
}
void SPI_Txfer_DMA(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes)
{
EDMA3CCPaRAMEntry *p2RxPaRAM;
EdmaConfigTxSpi(tx_buff, nBytes);
EdmaConfigRxSPI(rx_buff, nBytes);
p2RxPaRAM = (EDMA3CCPaRAMEntry *)(EDMA_BASE + EDMA3CC_OPT(EDMA3_CHA_SPI1_RX));
printf("SPI Rx DMA Source[0x%x] Dest[0x%x] ", p2RxPaRAM->srcAddr, p2RxPaRAM->destAddr);
printf("Counts: A[%d] B[%d] C[%d]\n", p2RxPaRAM->aCnt, p2RxPaRAM->bCnt, p2RxPaRAM->cCnt);
HWREG(SPI_BASE_ADDR + SPIINT0) |= 1<<16;
while (p2RxPaRAM->cCnt){}
HWREG(SPI_BASE_ADDR + SPIINT0) &= (0xFFFFFFFF & 0<<16);
}
void print_buffs(unsigned char *tx_buff, unsigned char *rx_buff, int nBytes)
{
int i;
for(i=0; i<nBytes; i++)
{
if(i%16==0 && i!=0) printf("\n");
printf("%02x[%02x] ", tx_buff[i], rx_buff[i]);
}
printf("\n\n");
}
void SendSpiChar(unsigned char char2tx)
{
HWREG(SPI_BASE_ADDR + SPIDAT0) = char2tx;
}
void Init_SPI_Hardware()
{
HWREG(SPI_BASE_ADDR + SPIGCR0) = 0;
HWREG(SPI_BASE_ADDR + SPIGCR0) = 1;
HWREG(SPI_BASE_ADDR + SPIGCR1) = 3;
HWREG(SPI_BASE_ADDR + SPIPC0) = 1<<11 | 1<<10 | 1<<9;
HWREG(SPI_BASE_ADDR + SPIDAT1) = 0<<24;
HWREG(SPI_BASE_ADDR + SPIFMT0) = 0
| 0<<20
| 0<<17
| 0<<16
| 20<<8
| 8<<0;
HWREG(SPI_BASE_ADDR + SPIDELAY) = 0;
HWREG(SPI_BASE_ADDR + SPIGCR1) |= 1<<24;
}
void Print_SPI_Registers()
{
printf("Config Reg => %x\n", HWREG(SPI_BASE_ADDR + SPIGCR1));
printf("SPIPC0 => %x\n", HWREG(SPI_BASE_ADDR + SPIPC0));
printf("SPIDAT1 => %x\n", HWREG(SPI_BASE_ADDR + SPIDAT1));
printf("SPIFMT0 => %x\n", HWREG(SPI_BASE_ADDR + SPIFMT0));
printf("FLAGS => %x\n", HWREG(SPI_BASE_ADDR + SPIFLG));
printf("RX Buffer => %x\n", HWREG(SPI_BASE_ADDR + SPIBUF));
}
void EdmaConfigTxSpi(unsigned char *Addr, int nBytes)
{
volatile unsigned int evtQ = 0;
EDMA3CCPaRAMEntry paramSet;
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
EDMA3Init(EDMA_BASE, evtQ);
EDMA3RequestChannel(EDMA_BASE, EDMA3_CHANNEL_TYPE_DMA, EDMA3_CHA_SPI1_TX, EDMA3_CHA_SPI1_TX, evtQ);
EDMA3EnableTransfer(EDMA_BASE, EDMA3_CHA_SPI1_TX, EDMA3_TRIG_MODE_EVENT);
paramSet.srcAddr = Addr;
paramSet.destAddr = (SPI_BASE_ADDR + SPIDAT0);
paramSet.srcBIdx = 0x01;
paramSet.srcCIdx = 0x00;
paramSet.destBIdx = 0x00;
paramSet.destCIdx = 0x00;
paramSet.aCnt = 0x01;
paramSet.bCnt = nBytes;
paramSet.cCnt = 0x01;
paramSet.bCntReload = 0x00;
paramSet.linkAddr = 0xffff;
paramSet.opt = 0;
paramSet.opt |= ((EDMA3_CHA_SPI1_TX << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
EDMA3SetPaRAM(EDMA_BASE, EDMA3_CHA_SPI1_TX, ¶mSet);
}
static void EdmaConfigRxSPI(unsigned char *Addr, int nBytes)
{
volatile unsigned int evtQ = 0;
EDMA3CCPaRAMEntry paramSet;
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
EDMA3Init(EDMA_BASE, evtQ);
EDMA3RequestChannel(EDMA_BASE, EDMA3_CHANNEL_TYPE_DMA, EDMA3_CHA_SPI1_RX, EDMA3_CHA_SPI1_RX, evtQ);
EDMA3EnableTransfer(EDMA_BASE, EDMA3_CHA_SPI1_RX, EDMA3_TRIG_MODE_EVENT);
paramSet.srcAddr = (SPI_BASE_ADDR + SPIBUF);
paramSet.destAddr = Addr;
paramSet.srcBIdx = 0x00;
paramSet.srcCIdx = 0x00;
paramSet.destBIdx = 0x01;
paramSet.destCIdx = 0x00;
paramSet.aCnt = 0x01;
paramSet.bCnt = nBytes;
paramSet.cCnt = 0x01;
paramSet.bCntReload = 0x00;
paramSet.linkAddr = 0xffff;
paramSet.opt = 0;
paramSet.opt |= ((EDMA3_CHA_SPI1_RX << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
EDMA3SetPaRAM(EDMA_BASE, EDMA3_CHA_SPI1_RX, ¶mSet);
}