Hallo
I am a beginner with dma working on tm4c1294XL
I ahve modified the lab14 project so i can get a "one-shot" transfer in the main loop , so i can change the frequency and so on....it works
Code is below
// Lab14a - DMA #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_uart.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "driverlib/udma.h" uint32_t ui32SysClkFreq; // Define source and destination buffers #define MEM_BUFFER_SIZE 1024 static uint32_t g_ui32SrcBuf[MEM_BUFFER_SIZE]; static uint32_t g_ui32DstBuf[MEM_BUFFER_SIZE]; // Define errors counters static uint32_t g_ui32DMAErrCount = 0; static uint32_t g_ui32BadISR = 0; // Define transfer counter static uint32_t g_ui32MemXferCount = 0; // The control table used by the uDMA controller. This table must be aligned to a 1024 byte boundary. #pragma DATA_ALIGN(pui8ControlTable, 1024) uint8_t pui8ControlTable[1024]; // uDMA transfer error handler void uDMAErrorHandler(void) { uint32_t ui32Status; // Check for uDMA error bit ui32Status = uDMAErrorStatusGet(); // If there is a uDMA error, then clear the error and increment the error counter. if (ui32Status) { uDMAErrorStatusClear(); g_ui32DMAErrCount++; } } // uDMA interrupt handler. Run when transfer is complete. void uDMAIntHandler(void) { uint32_t ui32Mode; // Check for the primary control structure to indicate complete. ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SW); if (ui32Mode == UDMA_MODE_STOP) { // Increment the count of completed transfers. g_ui32MemXferCount++; //trasferisci(); } // If the channel is not stopped, then something is wrong. else { g_ui32BadISR++; } } // Initialize the uDMA software channel to perform a memory to memory uDMA transfer. void InitSWTransfer(void) { uint32_t ui32Idx; // Fill the source memory buffer with a simple incrementing pattern. for (ui32Idx = 0; ui32Idx < MEM_BUFFER_SIZE; ui32Idx++) { g_ui32SrcBuf[ui32Idx] = ui32Idx; } // Enable interrupts from the uDMA software channel. IntEnable(INT_UDMA); // Place the uDMA channel attributes in a known state. These should already be disabled by default. uDMAChannelAttributeDisable(UDMA_CHANNEL_SW, UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)); // Configure the control parameters for the SW channel. The SW channel // will be used to transfer between two memory buffers, 32 bits at a time, // and the address increment is 32 bits for both source and destination. // The arbitration size will be set to 8, which causes the uDMA controller // to rearbitrate after 8 items are transferred. This keeps this channel from // hogging the uDMA controller once the transfer is started, and allows other // channels to get serviced if they are higher priority. uDMAChannelControlSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_8); //trasferisci(); } void transfer(){ // Set up the transfer parameters for the software channel. This will // configure the transfer buffers and the transfer size. Auto mode must be // used for software transfers. uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT, UDMA_MODE_AUTO, g_ui32SrcBuf, g_ui32DstBuf, MEM_BUFFER_SIZE); // Now the software channel is primed to start a transfer. The channel // must be enabled. For software based transfers, a request must be // issued. After this, the uDMA memory transfer begins. uDMAChannelEnable(UDMA_CHANNEL_SW); uDMAChannelRequest(UDMA_CHANNEL_SW); } int main(void) { FPULazyStackingEnable(); ui32SysClkFreq = SysCtlClockFreqSet( (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); IntEnable(INT_UDMAERR); uDMAEnable(); uDMAControlBaseSet(pui8ControlTable); InitSWTransfer(); while (1) { transfer(); SysCtlDelay(ui32SysClkFreq); } }
So i applied the same "strategy " to udma_demo project
First of all i changed the project to work with SPI instead of UART and it works
Then i arranged it as i did for lab14 (partially disabled interrupt) but it seems it does not do anything; can you please help on that ?
Code is below:
/* * udma_spi.c * * Created on: 05 nov 2016 * Author: Carlo * * * * * * * * */ //***************************************************************************** // // from udma_demo.c - uDMA example. // // Copyright (c) 2013-2016 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 2.1.3.156 of the EK-TM4C1294XL Firmware Package. // //***************************************************************************** #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_uart.h" #include "inc/hw_ssi.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/systick.h" #include "driverlib/uart.h" #include "driverlib/ssi.h" #include "driverlib/udma.h" #include "utils/cpu_usage.h" #include "utils/uartstdio.h" #include "utils/ustdlib.h" //***************************************************************************** // //! \addtogroup example_list //! <h1>uDMA (udma_demo)</h1> //! //! This example application demonstrates the use of the uDMA controller to //! transfer data between memory buffers, and to transfer data to and from a //! UART. The test runs for 10 seconds before exiting. //! //! UART0, connected to the ICDI virtual COM port and running at 115,200, //! 8-N-1, is used to display messages from this application. // //***************************************************************************** #define CLOCH 1000000 //**************************************************************************** // // System clock rate in Hz. // //**************************************************************************** uint32_t g_ui32SysClock; //***************************************************************************** // // The number of SysTick ticks per second used for the SysTick interrupt. // //***************************************************************************** #define SYSTICKS_PER_SECOND 100 //***************************************************************************** // // The size of the memory transfer source and destination buffers (in words). // //***************************************************************************** #define MEM_BUFFER_SIZE 1024 //***************************************************************************** // // The size of the UART transmit and receive buffers. They do not need to be // the same size. // //***************************************************************************** #define UART_TXBUF_SIZE 128 #define UART_RXBUF_SIZE 128 //***************************************************************************** // // The source and destination buffers used for memory transfers. // //***************************************************************************** static uint32_t g_ui32SrcBuf[MEM_BUFFER_SIZE]; static uint32_t g_ui32DstBuf[MEM_BUFFER_SIZE]; //***************************************************************************** // // The transmit and receive buffers used for the UART transfers. There is one // transmit buffer and a pair of recieve ping-pong buffers. // //***************************************************************************** static uint16_t g_ui8TxBuf[UART_TXBUF_SIZE];//CSB era uint8_t static uint16_t g_ui8RxBufA[UART_RXBUF_SIZE]; static uint16_t g_ui8RxBufB[UART_RXBUF_SIZE]; //***************************************************************************** // // The count of uDMA errors. This value is incremented by the uDMA error // handler. // //***************************************************************************** static uint32_t g_ui32uDMAErrCount = 0; //***************************************************************************** // // The count of times the uDMA interrupt occurred but the uDMA transfer was not // complete. This should remain 0. // //***************************************************************************** static uint32_t g_ui32BadISR = 0; //***************************************************************************** // // The count of UART buffers filled, one for each ping-pong buffer. // //***************************************************************************** static uint32_t g_ui32RxBufACount = 0; static uint32_t g_ui32RxBufBCount = 0; //***************************************************************************** // // The count of memory uDMA transfer blocks. This value is incremented by the // uDMA interrupt handler whenever a memory block transfer is completed. // //***************************************************************************** static uint32_t g_ui32MemXferCount = 0; //***************************************************************************** // // The CPU usage in percent, in 16.16 fixed point format. // //***************************************************************************** static uint32_t g_ui32CPUUsage; //***************************************************************************** // // The number of seconds elapsed since the start of the program. This value is // maintained by the SysTick interrupt handler. // //***************************************************************************** static uint32_t g_ui32Seconds = 0; //***************************************************************************** // // The control table used by the uDMA controller. This table must be aligned // to a 1024 byte boundary. // //***************************************************************************** #if defined(ewarm) #pragma data_alignment=1024 uint8_t pui8ControlTable[1024]; #elif defined(ccs) #pragma DATA_ALIGN(pui8ControlTable, 1024) uint8_t pui8ControlTable[1024]; #else uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024))); #endif //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, uint32_t ui32Line) { } #endif //***************************************************************************** // // The interrupt handler for the SysTick timer. This handler will increment a // seconds counter whenever the appropriate number of ticks has occurred. It // will also call the CPU usage tick function to find the CPU usage percent. // //***************************************************************************** void SysTickHandler(void) { static uint32_t ui32TickCount = 0; // // Increment the tick counter. // ui32TickCount++; // // If the number of ticks per second has occurred, then increment the // seconds counter. // if (!(ui32TickCount % SYSTICKS_PER_SECOND)) { g_ui32Seconds++; } } void uDMAErrorHandler(void) { uint32_t ui32Status; // // Check for uDMA error bit // ui32Status = ROM_uDMAErrorStatusGet(); // // If there is a uDMA error, then clear the error and increment // the error counter. // if (ui32Status) { ROM_uDMAErrorStatusClear(); g_ui32uDMAErrCount++; } } void uDMAIntHandler(void) {} void SPI0IntHandler(void){ uint32_t ui32Status; uint32_t ui32Mode; // // Read the interrupt status of the SPI. // ui32Status = ROM_SSIIntStatus(SSI0_BASE, 1);//eval board // // Clear any pending status, even though there should be none since no SPI // interrupts were enabled. If SPI error interrupts were enabled, then // those interrupts could occur here and should be handled. Since uDMA is // used for both the RX and TX, then neither of those interrupts should be // enabled. solo DMA-Int è enabled // ROM_SSIIntClear(SSI0_BASE, ui32Status); // // ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); // // if (ui32Mode == UDMA_MODE_STOP) { // // Increment a counter to indicate data was received into buffer A. In // a real application this would be used to signal the main thread that // data was received so the main thread can process the data. // g_ui32RxBufACount++; return; // // Set up the next transfer for the "A" buffer, using the primary // control structure. When the ongoing receive into the "B" buffer is // done, the uDMA controller will switch back to this one. This // example re-uses buffer A, but a more sophisticated application could // use a rotating set of buffers to increase the amount of time that // the main thread has to process the data in the buffer before it is // reused. // ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) (SSI0_BASE + SSI_O_DR), g_ui8RxBufA,//CSB was UDMA_MODE_PINGPONG UART_RXBUF_SIZE); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX);//added } // // If the SPI0 DMA TX channel is disabled, that means the TX DMA transfer // is done. // if (!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_SSI0TX)) { // // Start another DMA transfer to SPI0 TX. // g_ui8TxBuf[0]++;//added from tutorial ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, g_ui8TxBuf, (void *) (SSI0_BASE + SSI_O_DR), UART_TXBUF_SIZE);//was sizeof(g_ui8TxBuf) // // The uDMA TX channel must be re-enabled. // ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); } } void UART1IntHandler(void){}; void InitSPI0Transfer(void) { uint_fast16_t ui16Idx; // // Fill the TX buffer with a simple data pattern. // for (ui16Idx = 0; ui16Idx < (UART_TXBUF_SIZE); ui16Idx++) {//in realtà è un array a 16 bit ora g_ui8TxBuf[ui16Idx] = 32000+ui16Idx;//e inizia a 32000 } // // Enable the SPI peripheral // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); //ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_SSI0); // // Configure the SPI communication parameters. // GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2); ROM_SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, CLOCH, 16); // // Enable the SPI for operation, and enable the uDMA interface for both TX // and RX channels. // ROM_SSIEnable(SSI0_BASE); while (SSIDataGetNonBlocking(SSI0_BASE, &g_ui32CPUUsage)) { } ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_TX | SSI_DMA_RX); // //HWREG(SSI0_BASE + SSI_O_CR1) |= SSI_CR1_LBM;// loopback // ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX,//CSB UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);//check ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_4); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) (SSI0_BASE + SSI_O_DR), g_ui8RxBufA,//CSB change mode basic era UDMA_MODE_PINGPONG UART_RXBUF_SIZE); // // Put the attributes in a known state for the uDMA SPI0TX channel. These // should already be disabled by default. // ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); // ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_USEBURST); // // ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,//CSB change size 16, inc 16;erano a 8 UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_4);//check // // ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, g_ui8TxBuf, (void *) (SSI0_BASE + SSI_O_DR), UART_TXBUF_SIZE); // // ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); // // Enable the SPI DMA TX/RX interrupts. // ROM_SSIIntEnable(SSI0_BASE, SSI_DMATX |SSI_DMARX); UARTprintf("start Init\n"); // // Enable the SPI peripheral interrupts. // ROM_IntEnable(INT_SSI0); UARTprintf("end Init\n"); } //***************************************************************************** // // Initializes the uDMA software channel to perform a memory to memory uDMA // transfer. // //***************************************************************************** void InitSWTransfer(void) {} //***************************************************************************** // // Configure the UART and its pins. This must be called before UARTprintf(). // //***************************************************************************** void ConfigureUART(void) { // // Enable the GPIO Peripheral used by the UART. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Enable UART0 // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0); // // Configure GPIO Pins for UART mode. // ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Initialize the UART for console I/O. // UARTStdioConfig(0, 115200, g_ui32SysClock); } void data_transfer(){ ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) (SSI0_BASE + SSI_O_DR), g_ui8RxBufA, UART_RXBUF_SIZE); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, g_ui8TxBuf, (void *) (SSI0_BASE + SSI_O_DR), UART_TXBUF_SIZE); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); } int main(void) { static uint32_t ui32PrevSeconds; static uint32_t ui32PrevXferCount; static uint32_t ui32PrevUARTCount = 0; uint32_t ui32XfersCompleted; uint32_t ui32BytesTransferred; // // Set the clocking to run directly from the crystal at 120MHz. // g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // Enable peripherals to operate when CPU is in sleep. // //ROM_SysCtlPeripheralClockGating(true); // // Enable the GPIO port that is used for the on-board LED. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); // // Enable the GPIO pins for the LED (PN0). // ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0); // // Initialize the UART. // ConfigureUART(); UARTprintf("\033[2J\033[H"); UARTprintf("uDMA Example\n"); // // Show the clock frequency on the display. // UARTprintf("Tiva C Series @ %u MHz\n\n", g_ui32SysClock / 1000000); // // Configure SysTick to occur 100 times per second, to use as a time // reference. Enable SysTick to generate interrupts. // ROM_SysTickPeriodSet(g_ui32SysClock / SYSTICKS_PER_SECOND); ROM_SysTickIntEnable(); ROM_SysTickEnable(); // // Initialize the CPU usage measurement routine. // //CPUUsageInit(g_ui32SysClock, SYSTICKS_PER_SECOND, 2); // // Enable the uDMA controller at the system level. Enable it to continue // to run while the processor is in sleep. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); // // Enable the uDMA controller error interrupt. This interrupt will occur // if there is a bus error during a transfer. // ROM_IntEnable(INT_UDMAERR); // // Enable the uDMA controller. // ROM_uDMAEnable(); // // Point at the control table to use for channel control structures. // ROM_uDMAControlBaseSet(pui8ControlTable); // // Initialize the uDMA UART transfers. UARTprintf("SPI0transfer\n"); // InitSPI0Transfer(); // // Indicate on the display that the example is stopped. // UARTprintf("\nStopped\n"); // // Disable uDMA and UART interrupts now that the test is complete. // //ROM_IntDisable(INT_SSI0);//multitasking //ROM_IntDisable(INT_UDMA); // // Loop forever with the CPU not sleeping, so the debugger can connect. // while (1) { // // Turn on the LED. // GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0); // // Delay for a bit. // SysCtlDelay(g_ui32SysClock ); // // Turn off the LED. // GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); // // Delay for a bit. // SysCtlDelay(g_ui32SysClock ); data_transfer();//my function UARTprintf(" tx %i \n",g_ui8TxBuf[0]); UARTprintf(" rx %i \n",g_ui8RxBufA[0]); } }