Other Parts Discussed in Thread: SYSCONFIG, C2000WARE
I have configured SPIA as a slave device and want to use it with DMA for sending and receiving data. All the settings have been done using the SysConfig tool (version 1.12.1). The C2000Ware version is 4.1.0.00. The following codes have been generated by SysConfig for SPI and DMA initializations:
SPI initialization code:
void SPI_init()
{
//CM4_SPI initialization
SPI_disableModule(CM4_SPI_BASE);
SPI_setConfig(CM4_SPI_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1,
SPI_MODE_SLAVE, 1000000, 16);
SPI_enableFIFO(CM4_SPI_BASE);
SPI_setFIFOInterruptLevel(CM4_SPI_BASE, SPI_FIFO_TX8, SPI_FIFO_RX8);
SPI_clearInterruptStatus(CM4_SPI_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
SPI_enableInterrupt(CM4_SPI_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
SPI_disableLoopback(CM4_SPI_BASE);
SPI_setEmulationMode(CM4_SPI_BASE, SPI_EMULATION_FREE_RUN);
SPI_enableModule(CM4_SPI_BASE);
}
DMA initialization code:
void DMA_init(){
DMA_initController();
//CM4_SPI_RX_DMA initialization
DMA_setEmulationMode(DMA_EMULATION_STOP);
DMA_configAddresses(CM4_SPI_RX_DMA_BASE, rx_Data, CM4_SPI_RX_DMA_ADDRESS);
DMA_configBurst(CM4_SPI_RX_DMA_BASE, 8U, 0, 1);
DMA_configTransfer(CM4_SPI_RX_DMA_BASE, 14U, 0, 1);
DMA_configWrap(CM4_SPI_RX_DMA_BASE, 65535U, 0, 14U, 0);
DMA_configMode(CM4_SPI_RX_DMA_BASE, CM4_SPI_RX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(CM4_SPI_RX_DMA_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(CM4_SPI_RX_DMA_BASE);
DMA_disableOverrunInterrupt(CM4_SPI_RX_DMA_BASE);
DMA_enableTrigger(CM4_SPI_RX_DMA_BASE);
DMA_startChannel(CM4_SPI_RX_DMA_BASE);
//CM4_SPI_TX_DMA initialization
DMA_setEmulationMode(DMA_EMULATION_STOP);
DMA_configAddresses(CM4_SPI_TX_DMA_BASE, CM4_SPI_TX_DMA_ADDRESS, tx_Data);
DMA_configBurst(CM4_SPI_TX_DMA_BASE, 8U, 1, 0);
DMA_configTransfer(CM4_SPI_TX_DMA_BASE, 14U, 1, 0);
DMA_configWrap(CM4_SPI_TX_DMA_BASE, 14U, 0, 65535U, 0);
DMA_configMode(CM4_SPI_TX_DMA_BASE, CM4_SPI_TX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(CM4_SPI_TX_DMA_BASE, DMA_INT_AT_END);
DMA_disableInterrupt(CM4_SPI_TX_DMA_BASE);
DMA_disableOverrunInterrupt(CM4_SPI_TX_DMA_BASE);
DMA_enableTrigger(CM4_SPI_TX_DMA_BASE);
DMA_startChannel(CM4_SPI_TX_DMA_BASE);
}
Basically I want to transfer 112 words to and from SPI buffers. The burst size is set to 8 and transfer size to 14 such that 14 X 8= 112 words transfer. The pointers rx_Data and tx_Data have been defined in my main.c file and are pointing to buffers rData and sData allocated in globally shared RAM. each 112 words in length. sData is initialize with values 0 through 111 whereas rData is all initialized to zeros. Following is the code segment for declaring the arrays:
//buffers for SPI and DMA transfer // Send data buffer for DMA transmission int16_t sData[NWORDS]; // Receive data buffer for DMA reception int16_t rData[NWORDS]; // Place buffers in GSRAM so that DMA can access these #pragma DATA_SECTION(sData, "GSRAM"); #pragma DATA_SECTION(rData, "GSRAM"); //pointers to receive buffers and transmit buffers const void *rx_Data= rData; const void *tx_Data= sData;
GSRAM section is defined in the linker command file to be residing in globally shared ram. Below is the linker command file for reference.
//CPU1 PROGRAM GSRAM is allocated to GS7 & GS8
#define CPU1_RAMGS_PROG_START 0x013000
#define CPU1_RAMGS_PROG_LENGTH 0x002000
//CPU1 DATA GSRAM is allocated from GS2 RAM to GS6 RAM
#define CPU1_RAMGS_DATA_START 0x00E000
#define CPU1_RAMGS_DATA_LENGTH 0x005000
//required for MemCfgRegs settings
#define RAMGS_START 0x00000C
#ifdef CLA_BLOCK_INCLUDED
// Define a size for the CLA scratchpad area that will be used
// by the CLA compiler for local symbols and temps
// Also force references to the special symbols that mark the
// scratchpad are.
CLA_SCRATCHPAD_SIZE = 0x100;
--undef_sym=__cla_scratchpad_end
--undef_sym=__cla_scratchpad_start
#endif //CLA_BLOCK_INCLUDED
MEMORY
{
PAGE 0 :
/* BEGIN is used for the "boot to SARAM" bootloader mode */
BEGIN : origin = 0x000000, length = 0x000002
BEGIN_FLASH : origin = 0x080000, length = 0x000002
/*Defining CLA program and data memory*/
#if (CPU_RAMLS_PROG_LENGTH > 0)
RAMLS_PROG : origin = CPU_RAMLS_PROG_START, length = CPU_RAMLS_PROG_LENGTH
#endif //CPU_RAMLS_PROG_LENGTH
RAMLS_CLA_PROG : origin = CLA_RAMLS_PROG_START, length = CLA_RAMLS_PROG_LENGTH
RAMLS_CLA_DATA : origin = CLA_RAMLS_DATA_START, length = CLA_RAMLS_DATA_LENGTH
/*Defining CPU1 program memory in GSRAM*/
#if (CPU1_RAMGS_PROG_LENGTH > 0)
RAMGS_PROG : origin = CPU1_RAMGS_PROG_START, length = CPU1_RAMGS_PROG_LENGTH
#endif //(CPU1_RAMGS_PROG_LENGTH > 0)
RESET : origin = 0x3FFFC0, length = 0x000002
/* Flash sectors */
FLASHA_N : origin = 0x080002, length = 0x03FFFE /* on-chip Flash 256 K Words */
PAGE 1 :
BOOT_RSVD : origin = 0x000002, length = 0x000120 /* Part of M0, BOOT rom will use this for stack */
RAMM0M1 : origin = 0x000122, length = 0x0006DE
RAMD0D1 : origin = 0x00B000, length = 0x001000
RAMGS_DATA : origin = CPU1_RAMGS_DATA_START, length = CPU1_RAMGS_DATA_LENGTH
CLA1_MSGRAMLOW : origin = 0x001480, length = 0x000080
CLA1_MSGRAMHIGH : origin = 0x001500, length = 0x000080
CPU2TOCPU1RAM : origin = 0x03F800, length = 0x000400
CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400
}
SECTIONS
{
#if BOOT_FROM_FLASH
/* Allocate program areas: */
.init_array : > FLASHA_N PAGE = 0, ALIGN(8)
.cinit : > FLASHA_N PAGE = 0, ALIGN(8)
.pinit : > FLASHA_N, PAGE = 0, ALIGN(8)
.text : > FLASHA_N PAGE = 0, ALIGN(8)
codestart : > BEGIN_FLASH PAGE = 0, ALIGN(8)
.switch : > FLASHA_N PAGE = 0, ALIGN(8)
.const : > FLASHA_N PAGE = 0, ALIGN(8)
.data : > RAMLS_PROG, PAGE = 0
.bss : > RAMGS_DATA , PAGE = 1
#if defined(__TI_EABI__)
.TI.ramfunc : {} LOAD = FLASHA_N,
#if CPU_RAMLS_PROG_LENGTH>0
RUN = RAMLS_PROG,
#else // Applicable when CLA BLOCK is included and CPULSRAM is zero
RUN = RAMGS_PROG,
#endif
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
LOAD_END(RamfuncsLoadEnd),
RUN_START(RamfuncsRunStart),
RUN_SIZE(RamfuncsRunSize),
RUN_END(RamfuncsRunEnd),
PAGE = 0, ALIGN(8)
#else
.TI.ramfunc : {} LOAD = FLASHA_N,
#if CPU_RAMLS_PROG_LENGTH>0
RUN = RAMLS_PROG,
#else // Applicable when CLA BLOCK is included and CPULSRAM is zero
RUN = RAMGS_PROG,
#endif
LOAD_START(_RamfuncsLoadStart),
LOAD_SIZE(_RamfuncsLoadSize),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
RUN_SIZE(_RamfuncsRunSize),
RUN_END(_RamfuncsRunEnd),
PAGE = 0, ALIGN(8)
#endif
/* Initalized sections go in Flash */
/* Allocate IQmath areas: */
IQmath : > FLASHA_N, PAGE = 0, ALIGN(8) /* Math Code */
IQmathTables : > FLASHA_N, PAGE = 0, ALIGN(8)
/* CLA specific sections */
Cla1Prog : LOAD = FLASHA_N,
RUN = RAMLS_CLA_PROG,
LOAD_START(Cla1ProgLoadStart),
LOAD_END(Cla1ProgLoadEnd),
RUN_START(Cla1ProgRunStart),
LOAD_SIZE(Cla1ProgLoadSize),
PAGE = 0, ALIGN(8)
.const_cla : LOAD = FLASHA_N,
RUN = RAMLS_CLA_DATA,
RUN_START(Cla1ConstRunStart),
LOAD_START(Cla1ConstLoadStart),
LOAD_SIZE(Cla1ConstLoadSize),
PAGE = 0
#else
codestart : > BEGIN, PAGE = 0
#if (CPU_RAMLS_PROG_LENGTH > 0)
.cinit : > RAMLS_PROG, PAGE = 0
#else
.cinit : > RAMGS_PROG, PAGE = 0
#endif
ramfuncs : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
.TI.ramfunc : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
.pinit : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
.switch : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
.econst : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
/* Allocate IQ math areas: */
IQmath : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0 /* Math Code */
IQmathTables : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
/* CLA specific sections */
Cla1Prog : > RAMLS_CLA_PROG, PAGE = 0
.text : >> RAMLS_PROG | RAMGS_PROG, PAGE = 0
.const_cla : > RAMLS_CLA_DATA, PAGE = 0
.ebss : > RAMGS_DATA , PAGE = 1
#endif //BOOT_FROM_FLASH
.stack : > RAMM0M1, PAGE = 1
.reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */
.sysmem : > RAMD0D1, PAGE = 1
#ifdef CLA_BLOCK_INCLUDED
.cio : > RAMLS_PROG | RAMGS_PROG, PAGE = 0
#else
.cio : > RAMLS_PROG PAGE = 0
#endif //CLA_BLOCK_INCLUDED
/* CLA C compiler sections */
//
// Must be allocated to memory the CLA has write access to
//
Cla1DataRam0 : > RAMLS_CLA_DATA, PAGE=0
Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1
CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1
CLAscratch :
{ *.obj(CLAscratch)
. += CLA_SCRATCHPAD_SIZE;
*.obj(CLAscratch_end) } > RAMLS_CLA_DATA, PAGE = 0
.scratchpad : > RAMLS_CLA_DATA, PAGE = 0
.bss_cla : > RAMLS_CLA_DATA, PAGE = 0
/*Allocate area for SPI DMA transfer buffers*/
GSRAM : > RAMGS_DATA, PAGE=1
/* Allocate twiddle factors area: */
twiddleFactors : > FLASHA_N, PAGE = 0
/*Allocate areas for 32 points RFFT input and output buffers*/
buffer1 : > RAMLS_PROG, ALIGN = 64, PAGE = 0
buffer2 : > RAMLS_PROG, ALIGN = 64, PAGE = 0
}
/*
//===========================================================================
// End of file.
//===========================================================================
*/
I am getting a very strange behavior with the above mentioned setup. The SPI master device (Arduino Due for testing purpose) is getting the echoed version of its transmitted data with one word delay. In the debug mode I can verify that sData[] array contains valid data and rData[] array remains initialized to all zeros. It appears that DMA is not doing any transfers with these two arrays and SPI is some how sending back the previously received word against each word transfer. Kindly guide in fixing the issue