This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
I have a question closely related to my last two questions:
e2e.ti.com/.../1404676
e2e.ti.com/.../1406834
I try to transfer two uint8_t buffers from one CC3200 to another (both are Rev 4.1) via SPI and DMA.
The normal SPI transfer works fine, but is too slow - thus I want to improve it with DMA. I read the past threads on SPI and DMA:
e2e.ti.com/.../353790
e2e.ti.com/.../381940
and tried to follow the code given there as closely as possible.
My problem is, that I will receive an (possible) infinite number of SPI_INT_DMATX interrupts. The output on the slave side looks like this:
Enabled SPI Interface in Slave Mode!
Starting while...
Count: 1
SPI_INT_DMATX
Count: 2
SPI_INT_DMATX
Count: 3
SPI_INT_DMATX
...
(without the printf's it will also loop forever).
For reference here is my code:
slave.c (similar to the main.c given in the thread mentioned above):
http://pastebin.com/imbPFGuC
master.c (no DMA, this one works fine with non-DMA SPI code):
http://pastebin.com/aJ0fsjz2
common.h:
http://pastebin.com/mKUmcWvU
common.c:
http://pastebin.com/tYdbcynk
pinmux.{c|h} are just like in the SDK examples.
On the boards the following jumpers are set:
J2,J3,J4,J6,J7,J8,J9,J10,J11,J12,J13
The pins are connected with short 10cm wires and the transfer works fine when a DMA-less slave.c is used.
Does anyone maybe have any idea where the problem might be?
Thank you for your time,
Severin
Hello,
I want to configure an SPI connection between two CC3200 boards. Currently the master uses a normal SPI setup, while the slave should use DMA. I plan on changing the master to DMA as soon as I have it working on the slave. My current setup, only works for one transfer. So I can transfer data from the master to the slave and at the same time read data from the slave (although the first byte is missing). However, SPI_INT_DMATX and SPI_INT_DMARX seem to never be triggered and consecutive transfers only yield the last byte of the slave over and over again. I attached the master and slave files.
Here is a sample out put:
Master:
Start the slave and press any key to transmit data....
Filling Tx Buffer
Sum in the Tx Buffer is: 0
Checksum in the Tx Buffer is: 0x655e
Filled Tx Buffer
Sending...The sum in the Rx buffer is: 1395, tx was : 0
Checksum in the Rx buffer is: 0x5d6e
TX-Buffer:
/33/34/35/36/37/38/39/3a/3b/3c/3d/3e/3f/40/41/42/
Last: 66
RX-Buffer:
/0/56/57/58/59/5a/5b/5c/5d/5e/5f/60/61/62/63/64/
Last: 100
Press any key to transmit again
Sending...The sum in the Rx buffer is: 1600, tx was : 0
Checksum in the Rx buffer is: 0x60cc
TX-Buffer:
/0/1/2/3/4/5/6/7/8/9/a/b/c/d/e/f/
Last: 15
RX-Buffer:
/64/64/64/64/64/64/64/64/64/64/64/64/64/64/64/64/
Slave:
TX-Buffer:
/55/56/57/58/59/5a/5b/5c/5d/5e/5f/60/61/62/63/64/
Last: 100
RX-Buffer:
/33/34/35/36/37/38/39/3a/3b/3c/3d/3e/3f/40/41/42/
Last: 66
interrupt: 0
The sum in the Rx buffer is: 936
TX-Buffer:
/55/56/57/58/59/5a/5b/5c/5d/5e/5f/60/61/62/63/64/
Last: 100
RX-Buffer:
/33/34/35/36/37/38/39/3a/3b/3c/3d/3e/3f/40/41/42/
Last: 66
interrupt: 0
Here is the relevant part of how I set up DMA/SPI on my slave:
MAP_SPIReset(GSPI_BASE);
// DMA
// setup
//-----------
//This block is UDMAInit()
MAP_PRCMPeripheralClkEnable(PRCM_UDMA,PRCM_RUN_MODE_CLK);
MAP_PRCMPeripheralReset(PRCM_UDMA);
MAP_uDMAIntRegister(UDMA_INT_ERR, dma_error_handler);
MAP_uDMAEnable();
memset(dma_control_table,0,sizeof(tDMAControlTable)*CTL_TBL_SIZE);
MAP_uDMAControlBaseSet(dma_control_table);
for(uint32_t i = 0; i < MAX_NUM_CH; i++)
{
dma_callback_handler[i] = NULL;
}
//UDMAInit();
//-----------
MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),
SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0,
(SPI_HW_CTRL_CS |
SPI_4PIN_MODE |
SPI_TURBO_OFF |
SPI_CS_ACTIVEHIGH |
SPI_WL_8));
MAP_SPIIntRegister(GSPI_BASE,interrupt_handler);
// same calls as SetupTransfer
// channel
// RX
MAP_uDMAChannelControlSet(UDMA_CH30_GSPI_RX,UDMA_SIZE_8 |
UDMA_SRC_INC_NONE |
UDMA_DST_INC_8 |
UDMA_ARB_1);
MAP_uDMAChannelAttributeEnable(UDMA_CH30_GSPI_RX,UDMA_ATTR_USEBURST);
MAP_uDMAChannelTransferSet(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,
(void *)(GSPI_BASE + MCSPI_O_RX0),
(void *) &rx_buffer,
TR_BUFF_SIZE);
MAP_uDMAChannelEnable(UDMA_CH30_GSPI_RX);
// TX
MAP_uDMAChannelControlSet(UDMA_CH31_GSPI_TX,UDMA_SIZE_8 |
UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE |
UDMA_ARB_1);
MAP_uDMAChannelAttributeEnable(UDMA_CH31_GSPI_TX,UDMA_ATTR_USEBURST);
MAP_uDMAChannelTransferSet(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,
(void *)&tx_buffer,
(void *)(GSPI_BASE + MCSPI_O_TX0),
TR_BUFF_SIZE );
MAP_uDMAChannelEnable(UDMA_CH31_GSPI_TX);
//--------------
SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA);
MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX );
MAP_SPIEnable(GSPI_BASE);
If you have any idea why interrupt_handler is never called, I am grateful for any help :)
Thank you for your time,
Severin
#include "common.h" static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; int main() { uint32_t rx_sum = 0; uint32_t tx_sum = 0; uint8_t tmp; init(); // initialize buffers with some known value memset(tx_buffer,0x33,sizeof(tx_buffer)); memset(rx_buffer,0x44,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x33 + i; } // wait for keystroke: this gives the user time to start the slave Report("Start the slave and press any key to transmit data....\n\r"); MAP_UARTCharGet(UARTA0_BASE); // configure SPI channel MAP_SPIReset(GSPI_BASE); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_MASTER,SPI_SUB_MODE_0, (SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIEnable(GSPI_BASE); // fill buffer with random numbers Message("Filling Tx Buffer\n\r"); /* for(int i = 0; i < TR_BUFF_SIZE; i++) { tmp = xorshift128(); tx_buffer[i] = tmp; tx_sum += tmp; }*/ Report("Sum in the Tx Buffer is: %d\n\r", tx_sum); Report("Checksum in the Tx Buffer is: 0x%02x\n\r", crc(tx_buffer)); Message("Filled Tx Buffer\n\r"); int count = 0; while(1) { Message("Sending..."); MAP_SPITransfer(GSPI_BASE,tx_buffer,rx_buffer, TR_BUFF_SIZE, SPI_CS_ENABLE|SPI_CS_DISABLE); rx_sum = 0; for(int i = 0; i < TR_BUFF_SIZE; i++) { rx_sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d, tx was : %d\n\r",rx_sum,tx_sum); Report("Checksum in the Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); Report("Press any key to transmit again\n\r"); MAP_UARTCharGet(UARTA0_BASE); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = count++; } } return 0; }
// Standard includes #include <string.h> #include <stdint.h> // Driverlib includes #include "hw_types.h" #include "hw_memmap.h" #include "hw_common_reg.h" #include "hw_ints.h" #include "spi.h" #include "rom.h" #include "rom_map.h" #include "utils.h" #include "prcm.h" #include "uart.h" #include "interrupt.h" //for CRC #include "crc.h" #define CCM0_BASE DTHE_BASE // Common interface includes #include "uart_if.h" //for DMA #include "udma.h" //#include "udma_if.h" #include "hw_mcspi.h" #include "pin.h" #define MAX_NUM_CH 64 //32*2 entries #define CTL_TBL_SIZE 64 //32*2 entrie typedef void (*tAppCallbackHndl)(void); #define SPI_IF_BIT_RATE 800000 #define TR_BUFF_SIZE 16 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; /* used for DMA */ tDMAControlTable dma_control_table[CTL_TBL_SIZE] __attribute__(( aligned(1024))); tAppCallbackHndl dma_callback_handler[MAX_NUM_CH]; void dma_error_handler(void) { MAP_uDMAIntClear(MAP_uDMAIntStatus()); Message("DMA Error\n\r"); } void interrupt_handler() { Message("int\n\r"); MAP_SPIIntStatus(GSPI_BASE,true); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX|SPI_INT_DMATX); interrupt_count++; } void display_buffer(uint8_t* buffer, int len) { if(len > 16) { Message("Buffer is too big, printing only the first 16 elements!\n\r"); len = 16; } Report("Buffer:\n\r"); for(int i = 0;i < len;i++) { Report("/%x",buffer[i]); } Report("/\n\r"); Report("Last: %d\n\r",buffer[len-1]); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; //-- init() MAP_IntMasterEnable(); MAP_IntEnable(FAULT_SYSTICK); PRCMCC3200MCUInit(); // PinMuxConfig(); MAP_PRCMPeripheralClkEnable(PRCM_UARTA0, PRCM_RUN_MODE_CLK); MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK); MAP_PinTypeUART(PIN_55, PIN_MODE_3); MAP_PinTypeUART(PIN_57, PIN_MODE_3); MAP_PinTypeSPI(PIN_05, PIN_MODE_7); MAP_PinTypeSPI(PIN_06, PIN_MODE_7); MAP_PinTypeSPI(PIN_07, PIN_MODE_7); MAP_PinTypeSPI(PIN_08, PIN_MODE_7); //MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK); InitTerm(); ClearTerm(); Message("\n\n\n\r"); Message("\t\t ********************************************\n\r"); Message("\t\t CC3200 SPI Demo Application! \n\r"); Report("\t\t Birate: %d \n\r", SPI_IF_BIT_RATE); Report("\t\t Buffsize:%d \n\r", TR_BUFF_SIZE ); Message("\t\t ********************************************\n\r"); Message("\n\n\n\r"); MAP_PRCMPeripheralReset(PRCM_GSPI); // for CRC MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK); //-- MAP_SPIReset(GSPI_BASE); // DMA // setup //----------- //This block is UDMAInit() MAP_PRCMPeripheralClkEnable(PRCM_UDMA,PRCM_RUN_MODE_CLK); MAP_PRCMPeripheralReset(PRCM_UDMA); MAP_uDMAIntRegister(UDMA_INT_ERR, dma_error_handler); MAP_uDMAEnable(); memset(dma_control_table,0,sizeof(tDMAControlTable)*CTL_TBL_SIZE); MAP_uDMAControlBaseSet(dma_control_table); for(uint32_t i = 0; i < MAX_NUM_CH; i++) { dma_callback_handler[i] = NULL; } //UDMAInit(); //----------- MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); /* //FIFO MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX); MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX ); MAP_uDMAChannelAttributeDisable(UDMA_CH30_GSPI_RX , UDMA_ATTR_ALTSELECT ); MAP_uDMAChannelAttributeDisable( UDMA_CH31_GSPI_TX, UDMA_ATTR_ALTSELECT ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); MAP_SPIDmaEnable( GSPI_BASE, SPI_RX_DMA ); MAP_SPIDmaEnable( GSPI_BASE, SPI_TX_DMA ); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_IntRegister( INT_GSPI, (void(*)(void))interrupt_handler ); MAP_IntPrioritySet( INT_GSPI, INT_PRIORITY_LVL_0 ); MAP_IntEnable( INT_GSPI ); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); */ // same calls as SetupTransfer // channel // RX MAP_uDMAChannelControlSet(UDMA_CH30_GSPI_RX,UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1); MAP_uDMAChannelAttributeEnable(UDMA_CH30_GSPI_RX,UDMA_ATTR_USEBURST); MAP_uDMAChannelTransferSet(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC, (void *)(GSPI_BASE + MCSPI_O_RX0), (void *) &rx_buffer, TR_BUFF_SIZE); MAP_uDMAChannelEnable(UDMA_CH30_GSPI_RX); // TX MAP_uDMAChannelControlSet(UDMA_CH31_GSPI_TX,UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1); MAP_uDMAChannelAttributeEnable(UDMA_CH31_GSPI_TX,UDMA_ATTR_USEBURST); MAP_uDMAChannelTransferSet(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC, (void *)&tx_buffer, (void *)(GSPI_BASE + MCSPI_O_TX0), TR_BUFF_SIZE ); MAP_uDMAChannelEnable(UDMA_CH31_GSPI_TX); //-------------- /* SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, &rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, &tx_buffer,UDMA_SRC_INC_8,(void *)(GSPI_BASE + MCSPI_O_TX0), UDMA_DST_INC_NONE); */ SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); MAP_SPIEnable(GSPI_BASE); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x55 + i; } Message("Enabled SPI Interface in Slave Mode!\n\r"); Message("Starting while\n\r"); while(1) { // memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); sum = 0; // if(output_count < interrupt_count) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); //Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Message("TX-"); display_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); display_buffer(rx_buffer,TR_BUFF_SIZE); Report("interrupt: %d\n\r",interrupt_count); output_count++; } MAP_UtilsDelay(800000*20); } return 0; }
Hi Severin,
There is a similar thread on CC3200 SPI + DMA : http://e2e.ti.com/support/wireless_connectivity/f/968/t/353790
Pls check it out and let me know if that helps.
Thanks and Regards,
Praveen
Hello Praveen,
sorry I forgot to mention that I read the thread you mentioned (and your main.c example) as well as http://e2e.ti.com/support/wireless_connectivity/f/968/p/381940/1347971. . To my eyes my code to setup SPI and DMA is exactly like your main.c. And the code sort of works: I can complete one SPI DMA transfer, however the interrupt are never called.
Thank you and best regards,
Severin
Hello Praveen,
thank you for your reply. I did not know, that you could not access the files on pastebin, I will add them to this post. I was not using FIFO at this point, because I first wanted to get SPI with DMA working.
Cheers
Severin
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); interrupt_count++; Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { Message("Reached 100 interrupts...\n\r"); SPIIntUnregister(GSPI_BASE); // while(1){} } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); SPIIntDisable(GSPI_BASE, SPI_INT_DMATX ); return; } if(status & SPI_INT_DMARX) { Message("SPI_INT_DMARX \n\r"); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); SPIIntDisable(GSPI_BASE, SPI_INT_DMARX ); return; } Message("Unkown Interrupt\n\r"); // Message("int\n\r"); } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); //MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIEnable(GSPI_BASE); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } setup(); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); SPIDisable(GSPI_BASE); uDMADisable(); setup(); output_count++; } if(timer > TIMER_TICK) { timer = 0; } timer++; } return 0; }
#include "common.h" static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; int main() { uint32_t rx_sum = 0; uint32_t tx_sum = 0; uint8_t tmp; uint32_t tx_crc = 0; uint32_t tx_crc_old = 0; uint32_t a = 364; uint32_t b = 53457; uint32_t c = 976; uint32_t d = 66; init(); // initialize buffers with some known value memset(tx_buffer,0x33,sizeof(tx_buffer)); memset(rx_buffer,0x44,sizeof(rx_buffer)); // wait for keystroke: this gives the user time to start the slave Report("Start the slave and press any key to transmit data....\n\r"); MAP_UARTCharGet(UARTA0_BASE); // configure SPI channel MAP_SPIReset(GSPI_BASE); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_MASTER,SPI_SUB_MODE_0, (SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIEnable(GSPI_BASE); tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); while(1) { tx_crc_old = tx_crc; change_seed(a++,b++,c++,d++); tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Sending..."); //MAP_SPITransfer(GSPI_BASE,tx_buffer,rx_buffer, TR_BUFF_SIZE, // SPI_CS_ENABLE|SPI_CS_DISABLE); SPICSEnable(GSPI_BASE); for(int i = 0; i < TR_BUFF_SIZE; i++) { SPIDataPut(GSPI_BASE,tx_buffer[i]); //Message("x"); SPIDataGet(GSPI_BASE,&rx_buffer[i]); } Message("Transfer complete!\n\r"); SPICSDisable(GSPI_BASE); rx_sum = 0; for(int i = 0; i < TR_BUFF_SIZE; i++) { rx_sum += rx_buffer[i]; } Report("\n\rChecksum in the RX buffer was: 0x%02x, we send 0x%02x\n\r\n\r",crc(rx_buffer),tx_crc_old); //Report("The sum in the Rx buffer is: %d, tx was : %d\n\r",rx_sum,tx_sum); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); Report("Press any key to transmit again\n\r"); MAP_UARTCharGet(UARTA0_BASE); } return 0; }
#include "common.h" /* variables used for xorshift128 */ static uint32_t x = 5; static uint32_t y = 8; static uint32_t z = 32; static uint32_t w = 8978; void init() { MAP_IntMasterEnable(); MAP_IntEnable(FAULT_SYSTICK); PRCMCC3200MCUInit(); PinMuxConfig(); // for CRC MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK); MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK); InitTerm(); ClearTerm(); Message("\n\n\n\r"); Message("\t\t ********************************************\n\r"); Message("\t\t CC3200 SPI Demo Application! \n\r"); Report("\t\t Birate: %d \n\r", SPI_IF_BIT_RATE); Report("\t\t Buffsize:%d \n\r", TR_BUFF_SIZE ); Message("\t\t ********************************************\n\r"); Message("\n\n\n\r"); MAP_PRCMPeripheralReset(PRCM_GSPI); } /* * Prints a buffer * if the buffer is bigger than 1 elements, * only the first 16 will be printed. */ void print_buffer(uint8_t* buffer, int len) { Report("Buffer"); if(len > 16) { Message(" (16 first elements)"); len = 16; } Message(":\n\r"); for(int i = 0;i < len;i++) { Report("/%x",buffer[i]); } Report("/\n\r"); Report("Last: %x\n\r",buffer[len-1]); } /* * Perform CRC calculation * See the crc example in the SDK for more details */ uint32_t crc(uint8_t* buffer) { uint32_t config = CRC_CFG_INIT_SEED | CRC_CFG_TYPE_P8005 | CRC_CFG_SIZE_8BIT; MAP_PRCMPeripheralReset(PRCM_DTHE); MAP_CRCConfigSet(CCM0_BASE, config); MAP_CRCSeedSet(CCM0_BASE, 0x0000ffff); return MAP_CRCDataProcess(CCM0_BASE, buffer, TR_BUFF_SIZE, config); } /* * xorshift is a fast, but not too strong * random number generator * http://en.wikipedia.org/wiki/Xorshift */ uint32_t xorshift128(void) { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ t ^ (t >> 8); } void change_seed(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { x = a; y = b; z = c; w = d; } uint32_t fill_buffer(uint8_t* buffer, uint32_t len, char* name) { uint32_t tx_crc = 0; uint8_t tmp; uint32_t tx_sum; Message("----------------------------------\n\r"); Report("Filling %s Buffer...\n\r",name); for(uint32_t i = 0; i < len; i++) { tmp = xorshift128(); buffer[i] = tmp; tx_sum += tmp; } Report("Sum in the buffer is: %d\n\r", tx_sum); tx_crc = crc(buffer); Report("Buffer's checksum is: 0x%02x\n\r", tx_crc); Report("Filled %s Buffer!\n\r",name); Message("----------------------------------\n\r"); return tx_crc; }
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); interrupt_count++; Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { Message("Reached 100 interrupts...\n\r"); while(1){} } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); return; } if(status & SPI_INT_DMARX) { Message("SPI_INT_DMARX \n\r"); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); return; } Message("Unkown Interrupt\n\r"); // Message("int\n\r"); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); //MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIEnable(GSPI_BASE); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { // memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); output_count++; } if(timer > TIMER_TICK) { timer = 0; } timer++; } return 0; }
Dear Praveen,
I tried to implement FIFO (see attached file), but still have these runaway interrupts. I get one 'working' transfer in which the master gets data from the slave (I cannot verify the slave side, because it gets stuck in the interrupt loop).
However, after this one transfer I receive endless numbers of SPI_INT_DMARX interrupts (Not TX anymore!) .
I also experimented with manually calling SPIDataPut/Get in the interrupt handler, but this did not really solve my problem. I could however get rid of the interrupt flood in some cases.
Do you maybe know of any SPI/DMA examples or projects out there?
Thank you and kind regards,
Severin
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); uint32_t tmp = 0; interrupt_count++; // Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { // Message("Reached 100 interrupts...\n\r"); // SPIIntUnregister(GSPI_BASE); // while(1){} } if(status & SPI_INT_DMATX) { MAP_SPIIntClear(GSPI_BASE,SPI_INT_EOW); Report("EOW\n\r"); } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); // SPIDataPut(GSPI_BASE,5); //HWREG(GSPI_BASE + MCSPI_O_TX0) = 5; MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMATX ); return; } if(status & SPI_INT_DMARX) { Message("SPI_INT_DMARX \n\r"); // SPIDataGet(GSPI_BASE,&tmp); //tmp = HWREG(GSPI_BASE + MCSPI_O_RX0); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMARX ); return; } // Message("int\n\r"); } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); //MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIEnable(GSPI_BASE); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } setup(); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { // memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); // SPIDisable(GSPI_BASE); // uDMADisable(); // setup(); output_count++; } if(timer > TIMER_TICK) { timer = 0; } timer++; } return 0; }
Dear Praveen,
here is some example output. When I use slave.c as given above output will look like this:
EOW
SPI_INT_DMATX
SPI_INT_DMARX
SPI_INT_DMARX
(SPI_INT_DMARX repeated ad infinitum)
If I add SPIDataGet(GSPI_BASE,&tmp); to the SPI_INT_DMARX interrupt handler part the output is no longer infinite, but still strange:
EOW
SPI_INT_DMATX
SPI_INT_DMARX 2
SPI_INT_DMARX 5
...
SPI_INT_DMARX 38
(why 38 interrupts when my buffer is only of size 64?)
And gets stranger still: When I initiate another transfer at the master, interrupt_count is absurdly high:
SPI_INT_DMARX 59642849
SPI_INT_DMARX 59642850
...
SPI_INT_DMARX 59642882
When starting another transfer:
SPI_INT_DMARX 97171869
SPI_INT_DMARX 9717187
...
SPI_INT_DMARX 97171902
So it is always 33 interrupts for 64 SPI words. However.. I cannot explain why (and how) interrupt_count is incremented.
Cheers,
Severin
PS: Here is the modified slave.c:
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); uint32_t tmp = 0; interrupt_count++; // Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { // Message("Reached 100 interrupts...\n\r"); // SPIIntUnregister(GSPI_BASE); // while(1){} } if(status & SPI_INT_DMATX) { MAP_SPIIntClear(GSPI_BASE,SPI_INT_EOW); Report("EOW\n\r"); } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); // SPIDataPut(GSPI_BASE,5); //HWREG(GSPI_BASE + MCSPI_O_TX0) = 5; MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMATX ); return; } if(status & SPI_INT_DMARX) { Report("SPI_INT_DMARX %d\n\r",interrupt_count); SPIDataGet(GSPI_BASE,&tmp); //tmp = HWREG(GSPI_BASE + MCSPI_O_RX0); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMARX ); return; } // Message("int\n\r"); } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); //MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIEnable(GSPI_BASE); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } setup(); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { // memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); // SPIDisable(GSPI_BASE); // uDMADisable(); // setup(); output_count++; } if(timer > TIMER_TICK) { timer = 0; } timer++; } return 0; }
Dear Praveen,
thank you. I was experimenting a bit more with FIFO and now I seem to be able to get I correct SPI/DMA request. The problem is, that no follow-up interrupts are raised.
I attached you my latest slave.c
Thank you so much for your time and help!
Cheers,
Severin
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX | SPI_INT_DMATX | SPI_INT_EOW); uint32_t tmp = 0; interrupt_count++; // Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { // Message("Reached 100 interrupts...\n\r"); // SPIIntUnregister(GSPI_BASE); // while(1){} } if(status & SPI_INT_EOW) { // MAP_SPIIntClear(GSPI_BASE,SPI_INT_EOW); // SPIIntDisable(GSPI_BASE, SPI_INT_EOW ); Report("EOW\n\r"); } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); // SPIDataPut(GSPI_BASE,5); //HWREG(GSPI_BASE + MCSPI_O_TX0) = 5; // MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMATX ); // return; } if(status & SPI_INT_DMARX) { Report("SPI_INT_DMARX %d\n\r",interrupt_count); // SPIDataGet(GSPI_BASE,&tmp); //tmp = HWREG(GSPI_BASE + MCSPI_O_RX0); // MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMARX ); // return; } // Message("int\n\r"); } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); MAP_SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); // MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); // MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIEnable(GSPI_BASE); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } setup(); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { // memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); // SPIDisable(GSPI_BASE); // uDMADisable(); // setup(); output_count++; } if(timer > TIMER_TICK) { timer = 0; } // timer++; } return 0; }
Here is another observation:
Attached code will again restart SPI/DMA after a successful transfer. This works up to buffer sizes of 1024. As soon as the buffer size becomes 1025 or greater, the transfer will not longer work The slave will no longer receive any data from the master.
Here is again the tested slave.c:
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" #define TIMER_TICK 5000000 static uint32_t interrupt_count; static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX | SPI_INT_DMATX | SPI_INT_EOW); uint32_t tmp = 0; interrupt_count++; // Report("Count: %d\n\r",interrupt_count); if(interrupt_count > 100) { // Message("Reached 100 interrupts...\n\r"); // SPIIntUnregister(GSPI_BASE); // while(1){} } if(status & SPI_INT_EOW) { // MAP_SPIIntClear(GSPI_BASE,SPI_INT_EOW); // SPIIntDisable(GSPI_BASE, SPI_INT_EOW ); Report("EOW\n\r"); // SPIDisable(GSPI_BASE); // uDMADisable(); // setup(); } if(status & SPI_INT_DMATX) { Message(" SPI_INT_DMATX\n\r"); // SPIDataPut(GSPI_BASE,5); //HWREG(GSPI_BASE + MCSPI_O_TX0) = 5; // MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMATX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMATX ); // return; } if(status & SPI_INT_DMARX) { Report("SPI_INT_DMARX %d\n\r",interrupt_count); // SPIDataGet(GSPI_BASE,&tmp); //tmp = HWREG(GSPI_BASE + MCSPI_O_RX0); // MAP_SPIIntClear(GSPI_BASE,SPI_INT_DMARX); // SPIIntDisable(GSPI_BASE, SPI_INT_DMARX ); // return; } // Message("int\n\r"); } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0, (SPI_HW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); MAP_SPIDmaEnable(GSPI_BASE,SPI_RX_DMA|SPI_TX_DMA); // MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMATX | SPI_INT_DMARX ); // MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX | SPI_INT_DMATX ); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIEnable(GSPI_BASE); } int main() { interrupt_count = 0; uint32_t output_count = 0; uint32_t sum = 0; uint32_t tick_count = 0; uint32_t tx_crc = 0; init(); // initialize buffers with some known value memset(tx_buffer,0x55,sizeof(tx_buffer)); memset(rx_buffer,0x22,sizeof(rx_buffer)); for(int i = 0; i < TR_BUFF_SIZE; i++) { tx_buffer[i] = 0x20+i; } setup(); // MAP_uDMAIntClear(0xffffffff); // MAP_uDMAChannelAssign( UDMA_CH30_GSPI_RX ); // MAP_uDMAChannelAssign( UDMA_CH31_GSPI_TX); // MAP_uDMAChannelRequest(UDMA_CH30_GSPI_RX); // MAP_uDMAChannelRequest(UDMA_CH31_GSPI_TX); Message("Enabled SPI Interface in Slave Mode!\n\r"); // change_seed(456546,35345,345346,3463); // tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Starting while...\n\r"); uint32_t timer = 0; while(1) { memcpy(tx_buffer,rx_buffer,TR_BUFF_SIZE); // here we could also change the tx_buffer // tx_buffer[TR_BUFF_SIZE - 1] = 18; // we want to print out the buffer // on the slave side after each transfer. // As each transfer will cause // TR_BUFF_SIZE interrupts, we check if our // local counter is less than interrupt_count // which is incremeted in the interrupt handler sum = 0; if(timer > TIMER_TICK) { Report("Timer Tick %d!\n\r",tick_count); tick_count++; } if((output_count < interrupt_count) || timer > TIMER_TICK) { for(int i = 0; i < TR_BUFF_SIZE; i++) { sum += rx_buffer[i]; } Report("The sum in the Rx buffer is: %d\n\r",sum); Report("Checksum Rx buffer is: 0x%02x\n\r",crc(rx_buffer)); Report("interrupt: %d\n\r",interrupt_count); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); SPIDisable(GSPI_BASE); uDMADisable(); setup(); output_count++; } if(timer > TIMER_TICK) { timer = 0; } // timer++; } return 0; }
Hello Praveen,
today I tried to tackle the problem from the other side and use SPI/DMA on the master side. Again I run into the limit of 1024 bytes. Attached code works perfectly fine for buffers up to 1024 bytes, and breaks as soon as the buffer size is greater than that.
Do you know why this is so, if that can be changed and if not, how to work around that issue?
Thank you for all your help,
Severin
#include "common.h" #include "udma.h" #include "udma_if.h" #include "hw_mcspi.h" static uint8_t tx_buffer[TR_BUFF_SIZE]; static uint8_t rx_buffer[TR_BUFF_SIZE]; int transfer_complete = 0; static void interrupt_handler() { uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true); MAP_SPIIntClear(GSPI_BASE,SPI_INT_EOW); Message("Transfer complete!\n\r"); SPICSDisable(GSPI_BASE); transfer_complete = 1; } void setup() { // configure SPI MAP_SPIReset(GSPI_BASE); UDMAInit(); MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI), SPI_IF_BIT_RATE,SPI_MODE_MASTER,SPI_SUB_MODE_0, (SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_8)); MAP_SPIIntRegister(GSPI_BASE,interrupt_handler); MAP_SPIFIFOLevelSet( GSPI_BASE, 1, 1 ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_RX_FIFO ); MAP_SPIFIFOEnable( GSPI_BASE, SPI_TX_FIFO ); MAP_SPIDmaEnable(GSPI_BASE,SPI_RX_DMA); MAP_SPIDmaEnable(GSPI_BASE,SPI_TX_DMA); MAP_SPIIntEnable( GSPI_BASE, SPI_INT_EOW ); MAP_SPIEnable(GSPI_BASE); } void spi_transfer() { transfer_complete = 0; SetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE, rx_buffer,UDMA_DST_INC_8); SetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,TR_BUFF_SIZE, UDMA_SIZE_8,UDMA_ARB_1, tx_buffer,UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE); MAP_SPIWordCountSet( GSPI_BASE, TR_BUFF_SIZE ); SPICSEnable(GSPI_BASE); } int main() { uint32_t rx_sum = 0; uint32_t tx_sum = 0; uint8_t tmp; uint32_t tx_crc = 0; uint32_t tx_crc_old = 0; uint32_t a = 364; uint32_t b = 53457; uint32_t c = 976; uint32_t d = 66; init(); // initialize buffers with some known value memset(tx_buffer,0x33,sizeof(tx_buffer)); memset(rx_buffer,0x44,sizeof(rx_buffer)); // wait for keystroke: this gives the user time to start the slave Report("Start the slave and press any key to transmit data....\n\r"); MAP_UARTCharGet(UARTA0_BASE); setup(); tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); while(1) { tx_crc_old = tx_crc; change_seed(a++,b++,c++,d++); tx_crc = fill_buffer(tx_buffer,TR_BUFF_SIZE,"TX"); Message("Sending..."); spi_transfer(); while(!transfer_complete) {} rx_sum = 0; for(int i = 0; i < TR_BUFF_SIZE; i++) { rx_sum += rx_buffer[i]; } Report("\n\rChecksum in the RX buffer was: 0x%02x, we send 0x%02x\n\r\n\r",crc(rx_buffer),tx_crc_old); //Report("The sum in the Rx buffer is: %d, tx was : %d\n\r",rx_sum,tx_sum); Message("TX-"); print_buffer(tx_buffer,TR_BUFF_SIZE); Message("RX-"); print_buffer(rx_buffer,TR_BUFF_SIZE); Report("Press any key to transmit again\n\r"); MAP_UARTCharGet(UARTA0_BASE); } return 0; }