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.