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.
I am using SPI DMA to read 18 bytes from an external IC. The IC generates a negative edge interrupt that is connected to a port IRQ.
In the PORT IRQ handler, I assert Chip Select ( CS ) low and then enable the DMA.
In the DMA handler, I de-assert the CS high and then clear flags and copy the received data.
The main symptom is that SPI DMA gets triggered only once successfully... and then when the next port IRQ interrupt arrives, SPI-DMA does not get started: no SPI transactions occur.
I know that the PORT IRQ was executed (because the CS line goes low), however the DMA did not start the SPI transactions.
While debugging, I noticed that the UCTXIFG bit in the UCBxIFG register is 1 when the SPI successfully completes and UCTXIFG is set to 0, when the SPI DMA fails to start.
I looked at UCTXIFG after the execution of the following lines of code in the PORT IRQ handler
MAP_DMA_enableChannel(DMA_CHANNEL_1);
MAP_DMA_enableChannel(DMA_CHANNEL_0);
So it looks like the DMA did write to the eUSCI_B peripheral's TUCxxTXBUF, but for some reason the SPI peripheral did not start the transmission of the 18 bytes.
Also after reading the TRM, I know that the DMA_INT0 is a master interrupt and is different from the DMA_INT1/2/3 interrupts.
The problem is that the DMA_INT1/2/3 are mapped to other channels and I cannot use them, so I am left with DMA_INT0.
I also observed that when the SPI DMA fails and the DMA_INT0_IRQHandler gets called, then the value of INT0_SRCFLG is zeros. This is puzzling: how could the DMA_INT0_IRQHandler be called and yet have all the bits in the source flag be reset to 0 ? I would think that at least 1 channel caused the interrupt handler to be called.
Another observation regarding DMA_INT0 is that if I do not disable the DMA_INT0 interrupt in the DMA_INT0_IRQHandler then the IRQ gets called again *even if I clear the DMA interrupt flags* . This reminds me of the DMA12 bug in the Rev B. silicon. But I think that was fixed in the production Rev C. silicon.
Also there is no way to assign DMA_INT0 to any specific trigger like a SPI RX or TX channel...
basically it is illegal to do this MAP_DMA_assignInterrupt(DMA_INT0, DMA_CHANNEL_1) because DMA_INT0 maps to all completion sources except those mapped to DMA_INT1/2/3
Ideally I would just want to map a SPI recieve (RX) DMA completion to DMA_INT0, but I guess that is not allowed.
(1) any suggestions to why the SPI DMA freezes
(2) Why am I seeing spurious interrupts on DMA_INT0 where none of the source bits are set?
here is a screen shot showing that the first DMA runs successfully , but the second one fails.
SPI CLK = 6MHz
SMCLK = 12MHz,
Clock is set to DCO = 12MHz
Here are the relevant code pieces :DMA configuration routine and Port and DMA IRQ handlers
const eUSCI_SPI_MasterConfig spiMasterConfig =
{
EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
6000000, // SMCLK = DCO/2 = 12MHz/2 = 6MHz
6000000, // SPICLK = 6MHz
EUSCI_B_SPI_MSB_FIRST, // MSB First
EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, // Phase
EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity
EUSCI_B_SPI_3PIN // 3Wire SPI Mode
};
/* DMA Control Table */
#pragma DATA_ALIGN(1024)
static DMA_ControlTable controlTableInertialSensor[32];
----------------------------------------------------------------------------------------------------------------------------------------------
void Sensor::ConfigureDMA(void)
{
/* Configuring DMA module */
MAP_DMA_enableModule();
MAP_DMA_setControlBase(controlTableInertialSensor);
/* Assign DMA channel 0 to EUSCI_B0_TX0, channel 1 to EUSCI_B0_RX0 */
MAP_DMA_assignChannel(DMA_CH0_EUSCIB0TX0);
MAP_DMA_assignChannel(DMA_CH1_EUSCIB0RX0);
/* Setup the TX transfer characteristics & buffers */
MAP_DMA_setChannelControl(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
mTXData, (void *) MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B0_BASE),
INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE);
/* Setup the RX transfer characteristics & buffers */
MAP_DMA_setChannelControl(DMA_CH1_EUSCIB0RX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);
MAP_DMA_setChannelTransfer(DMA_CH1_EUSCIB0RX0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
(void *) MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B0_BASE), mRXData,
INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE);
// Enable DMA interrupt and clear any previously set completion flags
MAP_DMA_enableInterrupt(INT_DMA_INT0);
MAP_Interrupt_enableInterrupt(INT_DMA_INT0);
MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0);
MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0);
}
----------------------------------------------------------------------------------------------------------------------------------------------
void InertialSensor::PORT2_IRQHandler(void)
{
/*
* disable the interrupt on the I2C DRDY port
* DMA operation on SPI and I2C should be atomic.
* Disable the other interrupts so that the current operation
* completes atomically before starting the other peripheral
*/
MAP_Interrupt_disableInterrupt(INT_PORT3);
uint32_t status;
status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P2);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P2, 0xFF);
/*
* LSM6DS3 is signaling data is ready.
* Trigger the SPI read operation using DMA
*/
// reset the DMA transfer complete flag
mDMAXferComplete = false;
/* first assert the Chip Select (CS) to signal the start of the SPI transmission */
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN4);
// Enabling DMA interrupts
MAP_DMA_enableInterrupt(INT_DMA_INT0);
MAP_Interrupt_enableInterrupt(INT_DMA_INT0);
//enable DMA RX and TX channel
MAP_DMA_enableChannel(DMA_CHANNEL_1);
MAP_DMA_enableChannel(DMA_CHANNEL_0);
/*
* at this point DMA will take over and complete reception of rest of the data from the
* inertial sensor
*/
}
----------------------------------------------------------------------------------------------------------------------------------------------
void InertialSensor::DMA_INT0_IRQHandler(void)
{
uint32_t int0_srcflg_dma = DMA_Channel->INT0_SRCFLG;
if ( !(DMA_Channel->INT0_SRCFLG & (DMA_INT0_SRCFLG_CH0 | DMA_INT0_SRCFLG_CH1)) )
{
return;
}
// clear all the interrupt flag bits in the "DMA_INT0_SRCFLG" register
// that correspond to the DMA channels 0 and 1
MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0);
MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0);
// Disable the DMA interrupts
MAP_Interrupt_disableInterrupt(INT_DMA_INT0);
MAP_DMA_disableInterrupt(INT_DMA_INT0);
}
----------------------------------------------------------------------------------------------------------------------------------------------
Details of tool chain:
MSPWARE is version 3.50.0.2
Driverlib is version 3_21_00_05
Code Composer Studio Version: 6.1.3.00033
Compiler Version is V15.12.3 LTS
----------------------------------------------------------------------------------------------------------------------------------------------
Hi Chris, Thank you for your reply and help.
I tried a few things based on your reply.
I too was thinking that the second time the DMA IRQ handler executed was probably because of the DMA RX completing...However, when I read the DMA_INT0_SRCFLG register just after entering the DMA_INT0_IRQHandler (the 2nd time), I noticed all bits were zero. Perhaps this happened because I had already cleared the DMA RX interrupt flag in the DMA_INT0_IRQHandler so when the handler ran because of the TX DMA completion, my code cleared both the TX and RX interrupt flags.
Regarding your comment about disabling the interrupt before the receive DMA is finished: this seems unlikely because when I read the DMA_INT0_SRCFLG register right after the DMA_INT0_IRQHandler was entered, I read a value of 0x3 : which means that both the DMA RX and TX channels are signaling that they are done (am I correct in this assumption?)
So now to my 2 modifications based on your suggestions. (see code below)
First, I added a while loop in the Port IRQ to wait for the TXIFG flag. I saw this line of code in a previous post in the forums, but I think it slightly defeats the purpose of DMA : I do not think one should have to poll the eUSCI to check if the TXIFG bit is ready, shouldn't the DMA just handle that on its own: I should just enable the DMA channels and exit the ISR and be able to enter a LPM instead of polling the eUSCI to check if the TX Buffer was ready.
In any case I added the while loop, just in case I was not waiting long enough for the eUSCI module to be ready.
Secondly, I modified the DMA_INT0_IRQHandler code to just clear the individual TX , RX DMA interrupt flags and also disable the channels based on which DMA channel (RX , TX) caused the DMA_INT0_IRQHandler to execute.
The problem still exists and the symptom is exactly the same as I had shown in my previous post.
Since you are going to re-create the test on your setup I am also adding some additional defines to help you. I am also including the code I used to setup the SPI peripheral
Again , thanks a lot for your help.
-----------------------------------------------------------------------------------------
// number of bytes in the register file
#define INERTIAL_REG_FILE_SIZE_BYTES (46U)
#define INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE (18U)
/*
* The receive buffer will store the reply from the sensor IC
* 1 additional byte is required to store the reply on the MISO
* line for the address byte transmitted on the MOSI line.
* This additional byte stored at mRXData[0] is discarded
*/
#define INERTIAL_NUM_BYTES_RX_BUFFER (INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE + 1U)
// define and clear receive and transmit buffers
uint8_t InertialSensor::mRXData[INERTIAL_NUM_BYTES_RX_BUFFER] = {0x00};
uint8_t InertialSensor::mTXData[INERTIAL_REG_FILE_SIZE_BYTES] = {0x00};
-----------------------------------------------------------------------------------------------------------------------------
void InertialSensor::PORT2_IRQHandler(void)
{
/*
* disable the interrupt on the I2C DRDY port
* DMA operation on SPI and I2C should be atomic.
* Disable the other interrupts so that the current operation
* completes atomically before starting the other peripheral
*/
MAP_Interrupt_disableInterrupt(INT_PORT3);
uint32_t status;
status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P2);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P2, 0xFF);
/*
* LSM6DS3 is signaling data is ready.
* Trigger the SPI read operation using DMA
*/
// reset the DMA transfer complete flag
mDMAXferComplete = false;
/* first assert the Chip Select (CS) to signal the start of the SPI transmission */
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN4);
// Enabling DMA interrupts
MAP_DMA_enableInterrupt(INT_DMA_INT0);
MAP_Interrupt_enableInterrupt(INT_DMA_INT0);
MAP_DMA_enableChannel(DMA_CHANNEL_1);
MAP_DMA_enableChannel(DMA_CHANNEL_0);
/* Polling to see if the TX buffer is ready */
while (!(MAP_SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
/
* at this point DMA will take over and complete reception of rest of the data from the
* inertial sensor
*/
}
---------------------------------------------------------------------------------------------------------------------------------
void InertialSensor::DMA_INT0_IRQHandler(void)
{
uint32_t int0_srcflg_dma = DMA_Channel->INT0_SRCFLG;
if (int0_srcflg_dma & DMA_INT0_SRCFLG_CH0) // Transmit DMA completed
{
MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0); // clear the TX DMA interrupt flag
MAP_DMA_disableChannel(DMA_CHANNEL_0); // disable the TX channel
}
else if (int0_srcflg_dma & DMA_INT0_SRCFLG_CH1) // Recieve DMA completed
{
MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0); // clear the RX DMA interrupt flag
MAP_DMA_disableChannel(DMA_CHANNEL_1); // disable the RX channel
}
else
{
__nop();
return;
}
//deassert the chip select line to indicate end of SPI transmission
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN4);
// set the DMA transfer complete flag
mDMAXferComplete = true;
}
-----------------------------------------------------------------------------
void InertialSensor::ConfigureSPI()
{
/* Configure P1.4 is CS */
MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN4);
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN4);
/* Selecting P1.5 (SCLK) P1.6 (MOSI) in SPI mode */
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1,
GPIO_PIN5 | GPIO_PIN6 , GPIO_PRIMARY_MODULE_FUNCTION);
/* Selecting P1.7 (MISO) in SPI mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
/* Configuring SPI in 3wire master mode */
MAP_SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig);
/* Enable SPI module */
MAP_SPI_enableModule(EUSCI_B0_BASE);
/*
* if the mode for SPI is set to read samples :
* DMA is used and therefore SPI TX and RX interrupts are not used so disable them
*/
MAP_SPI_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);
MAP_SPI_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT);
MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
}
/* * ------------------------------------------- * MSP432 DriverLib - v3_21_00_05 * ------------------------------------------- * * --COPYRIGHT--,BSD,BSD * Copyright (c) 2016, 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. * --/COPYRIGHT--*/ /******************************************************************************* * MSP432 DMA - eUSCI SPI Transfer Using DMA * * Description: In this code example, the MSP432 's DMA controller is used in * conjunction with an SPI loopback configuration to demonstrate how to use * hardware triggered DMA transfers. Four DMA transfers are setup using four * separate DMA channels. For each SPI instance, a DMA channel is setup to * receive and transfer from the SIMO and SOMI ports respectively. After an * arbitrary string is sent through SPI via the loopback configuration, an * ISR counter is incremented and triggers a NOP condition in the main loop * where the user can set a breakpoint to examine memory contents. * * * MSP432P401 * --------------------------- * /|\| | * | | | * --|RST P1.5 (CLK) |--------- * | P1.7 (SIMO) |---------- * | P1.6 (SOMI) |-------- * | | * | | * * Author: Timothy Logan ******************************************************************************/ /* DriverLib Includes */ #include "driverlib.h" /* Standard Includes */ #include <stdint.h> #include <string.h> #include <stdbool.h> #define INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE 18 /* SPI Configuration Parameter */ const eUSCI_SPI_MasterConfig spiMasterConfig = { EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 6000000, // SMCLK = DCO/2 = 12MHz/2 = 6MHz 6000000, // SPICLK = 6MHz EUSCI_B_SPI_MSB_FIRST, // MSB First EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, // Phase EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity EUSCI_B_SPI_3PIN // 3Wire SPI Mode }; /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16]; uint8_t mRXData[INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE]; uint8_t mTXData[INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE]; int main(void) { volatile uint32_t ii; /* Halting Watchdog */ MAP_WDT_A_holdTimer(); MAP_Interrupt_enableSleepOnIsrExit(); for(ii=0;ii<INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE;ii++) { mTXData[ii] = ii; } /* * Revision C silicon supports wait states of 0 at 12Mhz */ MAP_PCM_setCoreVoltageLevel(PCM_VCORE0); MAP_FlashCtl_setWaitState(FLASH_BANK0, 0); MAP_FlashCtl_setWaitState(FLASH_BANK1, 0); /* * Setting up clocks * MCLK = DCO = 12MHz * SMCLK = DCO/2 = 6Mhz * ACLK = REFO = 32Khz */ MAP_CS_setDCOFrequency(12000000); MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2); MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); /* Configure CLK, MOSI & MISO for SPI0 (EUSCI_B0) */ MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN5 | GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION); MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION); /* * Configuring P1.1 as an input and enabling interrupt, the timer is started from * GPIO ISR. */ MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1); MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P1,GPIO_PIN1,GPIO_HIGH_TO_LOW_TRANSITION); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1); MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1); MAP_Interrupt_enableInterrupt(INT_PORT1); MAP_GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN4); MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN4); /* Configuring SPI module */ MAP_SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig); /* Enable the SPI module */ MAP_SPI_enableModule(EUSCI_B0_BASE); /* Configuring DMA module */ MAP_DMA_enableModule(); MAP_DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); /* Assign DMA channel 0 to EUSCI_B0_TX0, channel 1 to EUSCI_B0_RX0 */ MAP_DMA_assignChannel(DMA_CH0_EUSCIB0TX0); MAP_DMA_assignChannel(DMA_CH1_EUSCIB0RX0); /* Setup the TX transfer characteristics & buffers */ MAP_DMA_setChannelControl(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1); MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, mTXData, (void *) MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B0_BASE), INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE); /* Setup the RX transfer characteristics & buffers */ MAP_DMA_setChannelControl(DMA_CH1_EUSCIB0RX0 | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(DMA_CH1_EUSCIB0RX0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B0_BASE), mRXData, INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE); // Enable DMA interrupt and clear any previously set completion flags MAP_DMA_enableInterrupt(INT_DMA_INT0); MAP_Interrupt_enableInterrupt(INT_DMA_INT0); MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0); MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0); /* Polling to see if the master receive is finished */ while(1); } void DMA_INT0_IRQHandler(void) { uint32_t int0_srcflg_dma = DMA_Channel->INT0_SRCFLG; // if (int0_srcflg_dma & DMA_INT0_SRCFLG_CH0) // Transmit DMA completed // { // MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0); // clear the TX DMA interrupt flag // MAP_DMA_disableChannel(DMA_CHANNEL_0); // disable the TX channel // } // else if (int0_srcflg_dma & DMA_INT0_SRCFLG_CH1) // Recieve DMA completed // { // MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0); // clear the RX DMA interrupt flag // MAP_DMA_disableChannel(DMA_CHANNEL_1); // disable the RX channel // } // else // { // __nop(); // return; // } if (int0_srcflg_dma & DMA_INT0_SRCFLG_CH1) // Recieve DMA completed { MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN4); MAP_DMA_clearInterruptFlag(DMA_CH0_EUSCIB0TX0); // clear the TX DMA interrupt flag MAP_DMA_disableChannel(DMA_CHANNEL_0); // disable the TX channel MAP_DMA_clearInterruptFlag(DMA_CH1_EUSCIB0RX0); // clear the RX DMA interrupt flag MAP_DMA_disableChannel(DMA_CHANNEL_1); // disable the RX channel //deassert the chip select line to indicate end of SPI transmission /* * Reset DMA channels 0 and 1, size and mode see SLAU356 page 466, at * the end of cycle the count is 0 and the cycle_ctrl is automatically. * Alternatively you can re-use the setChannelControl and Transfer APIs. */ MSP_EXP432P401RLP_DMAControlTable[0].control = (MSP_EXP432P401RLP_DMAControlTable[0].control & 0xff000000 ) | (((INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE)-1)<<4) | 0x01; MSP_EXP432P401RLP_DMAControlTable[1].control = (MSP_EXP432P401RLP_DMAControlTable[1].control & 0xff000000 ) | (((INERTIAL_NUM_BYTES_TO_READ_PER_SAMPLE)-1)<<4) | 0x01; // set the DMA transfer complete flag //mDMAXferComplete = true; } } void PORT1_IRQHandler(void) { if(P1->IV == 4) { P1OUT |= BIT0; while(P1->IFG & BIT1) { P1->IFG &= ~BIT1; } /* first assert the Chip Select (CS) to signal the start of the SPI transmission */ MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN4); MAP_DMA_enableChannel(DMA_CHANNEL_0); MAP_DMA_enableChannel(DMA_CHANNEL_1); P1OUT &= ~BIT0; } }
Thank you for providing the additional code. I failed to notice that the the DMA is not 'reinitialized' in the DMA isr. Specifically the DMA decrements the size and also changes the control congifuration upon completion from basic mode to stop. I have gone ahead and attached an example. Regrettfully, I have not been able (due to time) to confirm the recieve data array is being filled properly. Please let me know if you have any issues or questions.
Chris
**Attention** This is a public forum