Hi all,
I'm using the SSI0 like SPI Slave port with uDMA in order to have an SPI channel.
I'm not able to have an interrupt after the DMA Trasfer is completed, could you help me with the DMA and SSI0 register settings?
Regards
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.
Hi all,
I'm using the SSI0 like SPI Slave port with uDMA in order to have an SPI channel.
I'm not able to have an interrupt after the DMA Trasfer is completed, could you help me with the DMA and SSI0 register settings?
Regards
Hi,
Provide more info on your setup, and post your code.
Information to provide when asking for help
-kel
Markel,
yesterday we were able to fix the problem with the IRQ, was our mistake on register settings of the TM4C1231H6PGEI.
Now seem that we have another problem with the bit BSY on the status register SSISR. This bit (BSY) stays all the time to 0, also when we are transmitting data.
I've attached an example code that we have developed in order to test the SSI0 port cin SPI Slave mode with uDMA.
Thanks for your support
FE
//***************************************************************************** // // timers.c - Timers example. // // Copyright (c) 2011-2012 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 9453 of the EK-LM4F232 Firmware Package. // //***************************************************************************** #include <stdint.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ssi.h" #include "driverlib/debug.h" #include "driverlib/fpu.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/pin_map.h" #include "driverlib/gpio.h" #include "driverlib/ssi.h" #include "driverlib/rom.h" #include "driverlib/udma.h" //***************************************************************************** // //! \addtogroup example_list //! <h1>Timer (timers)</h1> //! //! This example application demonstrates the use of the timers to generate //! periodic interrupts. One timer is set up to interrupt once per second and //! the other to interrupt twice per second; each interrupt handler will toggle //! its own indicator on the display. // //***************************************************************************** //***************************************************************************** // // Flags that contain the current value of the interrupt indicator as displayed // on the CSTN display. // //***************************************************************************** unsigned long g_ulFlags; //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, unsigned long ulLine) { } #endif #pragma DATA_ALIGN(ucControlTable, 1024) unsigned char ucControlTable[512]; static unsigned long uDMAErrCount = 0; static volatile unsigned long RxBufCount = 0; static char data[50]; static char SomTxBuf[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x57,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E } ; void SSI0IntHandler(void); void SSI0IntHandler(void) { volatile unsigned long i; unsigned long v; v = ROM_uDMAIntStatus(); ROM_uDMAIntClear(v); if((v&(1<<UDMA_CHANNEL_SSI0RX))!=0) { // ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0); for(i=0;i<100;i++); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(SSI0_BASE + SSI_O_DR), data, 15); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, SomTxBuf, (void *)(SSI0_BASE + SSI_O_DR), 10); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); // ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); } } void uDMAErrorHandler(void); void uDMAErrorHandler(void) { unsigned long ulStatus; // // Check for uDMA error bit // ulStatus = ROM_uDMAErrorStatusGet(); // // If there is a uDMA error, then clear the error and increment // the error counter. // if(ulStatus) { ROM_uDMAErrorStatusClear(); uDMAErrCount++; } } //***************************************************************************** // // This example application demonstrates the use of the timers to generate // periodic interrupts. // //***************************************************************************** int main(void) { volatile int i; uint32_t d; // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); // // Enable processor interrupts. // ROM_IntMasterEnable(); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK); ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX); ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX); ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS); ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); ROM_SSIConfigSetExpClk(SSI0_BASE, 24576000UL, SSI_FRF_MOTO_MODE_3, SSI_MODE_SLAVE, 4096000, 8); while(ROM_SSIDataGetNonBlocking(SSI0_BASE, &d)); ROM_SSIEnable(SSI0_BASE); #if 1 // Enable the uDMA controller. ROM_SysCtlPeripheralEnable(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); ROM_uDMAEnable(); ROM_uDMAControlBaseSet(ucControlTable); ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX); ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_USEBURST); ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(SSI0_BASE + SSI_O_DR), data, 15); 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, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, SomTxBuf, (void *)(SSI0_BASE + SSI_O_DR), 10); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); #endif ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1); ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1, 0); ROM_SSIIntClear(SSI0_BASE, 0x3); // volatile unsigned long prima, dopo; ROM_IntEnable(INT_SSI0); // HWREG(SSI0_BASE + SSI_O_IM) = 0; // prima = HWREG(SSI0_BASE + SSI_O_IM); ROM_SSIIntDisable(SSI0_BASE, SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR); // ROM_SSIIntEnable(SSI0_BASE, SSI_RXFF | SSI_RXTO); // HWREG(SSI0_BASE + SSI_O_IM) = ~(SSI_RXFF | SSI_RXTO); // dopo = HWREG(SSI0_BASE + SSI_O_IM); // // Loop forever while the timers run. // while(1) { ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0); if(ROM_SSIBusy(INT_SSI0)) ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1); else ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0); ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); } }