Tool/software: TI-RTOS
Hi,
I am working on SPI DMA in TI RTOS, I cant find any sample code to develop. So developed a function to work with.
I have created for ping pong mode. But the code is not working, once the SPI dma receives a data the task is terminated from its state.
I have attached you the source code.
Question:
1. Will the DMA_request call is used for pheripheral to DMA transfer or only to memory to memory transfer?
/* * Copyright (c) 2015, Texas Instruments Incorporated * All rights reserved. * * 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. */ /* * ======== empty.c ======== */ /* XDCtools Header files */ #include <xdc/std.h> #include <xdc/runtime/System.h> /* BIOS Header files */ #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> /* TI-RTOS Header files */ // #include <ti/drivers/EMAC.h> #include <ti/drivers/GPIO.h> // #include <ti/drivers/I2C.h> // #include <ti/drivers/SDSPI.h> #include <ti/drivers/SPI.h> // #include <ti/drivers/UART.h> // #include <ti/drivers/USBMSCHFatFs.h> // #include <ti/drivers/Watchdog.h> // #include <ti/drivers/WiFi.h> #include <ti/sysbios/knl/Semaphore.h> /* Board Header file */ #include "Board.h" #include <ti/sysbios/knl/Swi.h> #include <xdc/runtime/Error.h> #include <ti/sysbios/family/arm/m3/Hwi.h> #include <stdbool.h> #include "driverlib/sysctl.h" #include "driverlib/ssi.h" #include "driverlib/udma.h" #include <inc/hw_memmap.h> #include <inc/hw_ints.h> #include <stdbool.h> #define TASKSTACKSIZE 512 #define BUFFER_PAGES 2 #define BUFFER_PAGE_SZ_WORDS 8 #define CONTROL_WORD 0x00008043 #define SSI_O_DR 0x00000001 #define DMA_CLEAR_FLAG 0x00000400 Task_Struct task0Struct; uint32_t DMABuffer[BUFFER_PAGES][BUFFER_PAGE_SZ_WORDS]; Char task0Stack[TASKSTACKSIZE]; bool SPI_Master; uint8_t ActivePage; uint8_t BgPage; tDMAControlTable dmaControlTable; uint32_t destEndAddress = 0x20002004; uint32_t srcEndAddress= 0x20001004; /* * ======== heartBeatFxn ======== * Toggle the Board_LED0. The Task_sleep is determined by arg0 which * is configured for the heartBeat Task instance. */ uint32_t DMAtransferCount; void SSI0_dma_int(void) { uint32_t ulMode; //check primary channel ulMode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 1; BgPage = 0; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[0][0], BUFFER_PAGE_SZ_WORDS); uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); DMAtransferCount++; } //check alt channel ulMode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 0; BgPage = 1; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[1][0], BUFFER_PAGE_SZ_WORDS); uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); DMAtransferCount++; } System_printf(" i am in dma init\n"); System_flush(); } void UserCallbackFxn(SPI_Handle handle, SPI_Transaction * transaction) { /* I have a brekpoint at below printf statement, Immediately after initiating transfer from MASTER, control comes to this statment and stops. */ System_printf(" i am in callback function\n"); System_flush(); GPIO_toggle(Board_LED1); /* If I enable this SSI0_dma_int(), system crashes. */ SSI0_dma_int(); } /* Function to configure the ping pong mode and initiate DMA transfer. */ void Dma_Init() { bool DMA_initialized = FALSE; dmaControlTable.pvDstEndAddr = &destEndAddress; dmaControlTable.pvSrcEndAddr = &srcEndAddress; dmaControlTable.ui32Control = CONTROL_WORD; if(!DMA_initialized){ SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(&dmaControlTable); DMA_initialized = TRUE; } } void initDMA_control_table(void) { dmaControlTable.pvDstEndAddr = &destEndAddress; dmaControlTable.pvSrcEndAddr = &srcEndAddress; dmaControlTable.ui32Control = CONTROL_WORD; SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(&dmaControlTable); uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_HIGH_PRIORITY); //uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_ALTSELECT); // Primary Channel uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_8); uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[0][0], BUFFER_PAGE_SZ_WORDS); // Alternate Channel uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_8); uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[1][0], BUFFER_PAGE_SZ_WORDS); uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); } void ssiInterrupt(void) { uDMAIntClear(DMA_CLEAR_FLAG); } void run_time() { SPI_Params params; SPI_Handle spiHandles; SPI_init(); SPI_Params_init(¶ms); params.mode = SPI_SLAVE; params.transferMode = SPI_MODE_CALLBACK; params.bitRate = 5000000; params.transferCallbackFxn = UserCallbackFxn; spiHandles = SPI_open(Board_SPI0, ¶ms); if (spiHandles == NULL) { System_abort("Error initializing SPI\n"); } else { System_printf("SPI 0 initialized\n"); } SSIEnable(SSI0_BASE); SSIDMAEnable(SSI0_BASE, SSI_DMA_RX); SSIIntEnable(SSI0_BASE, SSI_DMARX); uDMAIntRegister(UDMA_INT_SW, &ssiInterrupt); initDMA_control_table(); } Void heartBeatFxn(UArg arg0, UArg arg1) { uint8_t count = 0; Dma_Init(); run_time(); while (1) { Task_sleep((unsigned int)arg0); GPIO_toggle(Board_LED0); count++; if(count == 5) { uDMAChannelRequest(UDMA_CHANNEL_SSI0RX); } } } /* * ======== main ======== */ int main(void) { Task_Params taskParams; /* Call board init functions */ Board_initGeneral(); // Board_initEMAC(); Board_initGPIO(); // Board_initI2C(); // Board_initSDSPI(); Board_initSPI(); // Board_initUART(); // Board_initUSB(Board_USBDEVICE); // Board_initUSBMSCHFatFs(); // Board_initWatchdog(); // Board_initWiFi(); /* Construct heartBeat Task thread */ Task_Params_init(&taskParams); taskParams.arg0 = 1000; taskParams.stackSize = TASKSTACKSIZE; taskParams.stack = &task0Stack; Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL); /* Turn on user LED */ GPIO_write(Board_LED0, Board_LED_ON); System_printf("Starting the example\nSystem provider is set to SysMin. " "Halt the target to view any SysMin contents in ROV.\n"); /* SysMin will only print to the console when you call flush or exit */ System_flush(); /* Start BIOS */ BIOS_start(); return (0); }
Regards,
Manohar.