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.

Tiva TM4C1294XL DMA unclear behaviour: please help me to understand more

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]);
	}
}

  • Hello Carlo

    What do you mean by partially disabled interrupt?
  • Hi Amit

    Sorry , i meant isr partially executed (there is a return inside the interrupt service routine)

    Hope this is clear now

    Thank you for your help

    Carlo
  • Hello Carlo

    Why is there a return in the interrupt handler? The Interrupt handler will anyways return back to the main code execution.
  • yes

    I wanted to avoid the execution of some parts of the isr code (it's a dirty way of doing it i know)
  • Hello Carlo

    Then please use flags. What may be happening is that the interrupt handler is continuously firing as the TX DMA is requesting for data while the code is skipping the re-initialization of the DMA channel structure. The better way to handle it would be to disable the TX DMA channel.
  • I will try that

    Thank you Amit

    regards

    Carlo
  • Hello Carlo

    OK. Please do post an update.
  • Will do

    Tnx Amit

    regards

    Carlo
  • Hallo again

    I disabled DMA_TX interrupt and commented out the inizialization parts in the isr

    (My objective is to use data_transfer() function in the main to trigger the transfer)

    Now it works, i can see the buffers updated

    I copy the source code  :

    //*****************************************************************************
    //
    // 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 );
    		//g_ui8TxBuf[0]++;//added from tutorial
    		data_transfer();//my function
    		UARTprintf(" tx %i \n",g_ui8TxBuf[0]);
    		UARTprintf(" rx %i \n",g_ui8RxBufA[0]);
    	}
    }
    
    
    

  • Hello Carlos

    Glad that you got it working. And getting a forum post updated with the code.
  • Thank you Amit

    regards

    Carlo