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 found this thread.
In this thread it says that i can't use DMA with SPI with DMAE0 and send more than 1 byte. If I understood correctly, if I put the source DMA_CH0_EUSCIB0TX0 then the SPI generates the DMA request when the TX_SPI is ready. On the other hand, if I but the source to be DMAE0 then the DMA doesn't know if the SPI is ready and just copies the memory from one address to another without check the SPI ready signal.
I found on the internet that many systems have this feature that can use and combine both, so I first wanted to check here.
Thanks in advanced.
jasaleja
Hi Chris,
I am trying to make DMA help me with the CC1200 RF chip in infinite mode. I'll simplify the problem. The transfer or receive buffer in CC1200 is only 128 k and to make my packets longer I need to use infinite mode which demands that I refill the transfer buffer in real time or to read in realm time from the receive buffer while receiving. There are some GPIOs that tell me when the buffers are ready to be written to or read from and I wanted to use those GPIOs to singal the DMA when to transfer to the SPI. This would help me because in the other case I would have to wake up the MCU and start DMA manually(which is going to be the case). I hope the explanation was clear.
On the other hand I looked into your example(thanks for that) but there were a few things I could not figure out.
1) In you code you made a list with tasks. In the Techincal reference manual it says that the DMA jumps from primary to alternate data structure. Does that mean that every other data structure in the task list automatically alternate?
2) Nowhere, really nowhere could I find what UDMA_MODE_ALT_SELECT was and why do you combine it with other UDMA modes?
3) No matter how much i tried to look I could not understand what was the difference between MEM and PER SCATTER_GATHER?
4) The last thing is that I wanted to try and write here a simplified task list what my DMA needs to do. Could you write the real task list how it should look like?
1. Task: Send command to CC1200 that tell it I want to read receive buffer. Source would be commandBuffer and destination would be EUSCI_B0_TX. Command is 1 byte.
2. Task: Send 32 dummy bytes so that the CC1200 returns 32 bytes from receive buffer. Sourcew is dummyByte, and destination is EUSCI_B0_TX.
At the same time I want the DMA to transfer from EUSCI_B0_RX to my receiveBuffer during the second task.
I have no idea how to create this. Please give me some guidelines and additional examples.
Thank you Chris for a very detailed answer.
One more question that came up is, can I setup different request for different tasks?
After looking at the examples it doesn't seem it can be set, but it doesn't hurt to ask.
For example the first task uses DMAE0 and the second and all after use EUSCIB0_TX.
Best wishes,
jasaleja
I tried doing the first thing that you suggested but mu DMA_INT1 keeps triggering even though I didn't use the DMA yet. I don't understand what could be the source of the problem.
//***************************************************************************** // // MSP432 main.c template - Empty main // //**************************************************************************** #include "driverlib.h" #include "IQmathLib.h" #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32]; void InitMCU(); void main(void) { InitMCU(); uint8_t buffer = 0x55; // Clear interrupt status SPI_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT); // Activate DMA SPI transfer with external pin DMA_setChannelControl(DMA_CH6_EXTERNALPIN | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1); DMA_setChannelTransfer(DMA_CH6_EXTERNALPIN | UDMA_PRI_SELECT, UDMA_MODE_BASIC, &buffer, (void *) SPI_getTransmitBufferAddressForDMA(EUSCI_B0_BASE), 1); // Setup the TX transfer characteristics & buffers DMA_setChannelControl(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1); DMA_setChannelTransfer(DMA_CH0_EUSCIB0TX0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, &buffer, (void *) SPI_getTransmitBufferAddressForDMA(EUSCI_B0_BASE), 1); DMA_clearInterruptFlag(0); MAP_DMA_enableChannel(0); MAP_DMA_enableChannel(6); GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN6); while(1); } // DMA INT1 ISR void DMA_INT1_IRQHandler(void) { return; } // SPI Master Configuration Parameter for CC1200 const eUSCI_SPI_MasterConfig spiMasterConfig = { EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 6000000, // SMCLK = HFXT/8 = 6MHz 6000000, // SPICLK = 6MHz EUSCI_B_SPI_MSB_FIRST, // MSB First EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT, // Phase EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // Low polarity EUSCI_B_SPI_3PIN // 3Wire SPI Mode }; // Initialize the MCU void InitMCU() { // Halting the Watchdog WDT_A_holdTimer(); // Enabling MASTER interrupts Interrupt_disableMaster(); // Set power state of MCU PCM_setPowerState(PCM_AM_LDO_VCORE1); // Configuring pins for peripheral/crystal usage and LED for output GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION); // Just in case the user wants to use the getACLK, getMCLK, etc. functions, // let's set the clock frequency in the code CS_setExternalClockSourceFrequency(32000,48000000); // Starting HFXT in non-bypass mode without a timeout. Before we start // we have to change VCORE to 1 to support the 48MHz frequency //PCM_setCoreVoltageLevel(PCM_VCORE1); FlashCtl_setWaitState(FLASH_BANK0, 2); FlashCtl_setWaitState(FLASH_BANK1, 2); CS_startHFXT(false); // Initializing MCLK to HFXT (effectively 48MHz) CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1); // Initializing SMCLK to HFXT (effectively 6MHz) CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_8); // Selecting pins P1.5, P1.6 and P1.7 in SPI mode GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN7 | GPIO_PIN6 | GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION); GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN6); GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN6); // Selecting pin 7.0 in DMAE0 GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0, GPIO_PRIMARY_MODULE_FUNCTION); // Configuring SPI in 3wire master mode for CC1200 SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig); // Enable SPI module for CC1200 SPI_enableModule(EUSCI_B0_BASE); // Configuring DMA module DMA_enableModule(); DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); // Assign DMA channel 0 to EUSCI_B0_TX0, channel 1 to EUSCI_B0_RX0 DMA_assignChannel(DMA_CH0_EUSCIB0TX0); DMA_assignChannel(DMA_CH1_EUSCIB0RX0); DMA_assignChannel(DMA_CH6_EXTERNALPIN); // Enable DMA interrupt MAP_DMA_assignInterrupt(INT_DMA_INT1, 0); MAP_DMA_clearInterruptFlag(0); /* Assigning/Enabling Interrupts */ MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_enableInterrupt(INT_DMA_INT1); // Enabling MASTER interrupts Interrupt_enableMaster(); }
The TIFG is set automatically when the eUSCI module is released from reset (www.ti.com/.../slau356d.pdf ). The SPI_enableModule API clears the reset in the eUSCI peripheral, so either before or after but definitely before you configure the DMA you can clear the TXIFG, SPI_clearInterruptFlag(), There is another issue with the order of operation where you are assigning channels, enabling interrupts, and then configuring the DMA.
Chris
I knew that but for some reason I thought the the interrupt won't occur until the DMA did a transfer.
I am sorry for asking so many questions, but it is my first time making an embedded application on my own.
So I should keep interrupt disabled until I setup the channel controls and channel transfers and I should(as I did) clear the transmit interrupt in the SPI.
I did these things in this example and It worked. But it won't work when I put it in the whole project, but that is probably some other problem.
Thanks for all the help.
**Attention** This is a public forum