Part Number: MSP432P401R
I'm trying to use DMA to read and write to an SPI peripheral on the MSP432 launchpad. I'm able to write data just fine, but the read isn't coming in correctly. Below find a screenshot of the signals:
I'm writing two 32 bit variables which I've just set to dummy values {0xAABBCCDD, 0x11223344} for now. This correponds to 0xDDCCBBAA44332211 on the MOSI line, which you can see above
My slave (in this example) is returning 0xFF69D700FF69D7A0 on DOUT, but my read buffer returns {0x69FFD769, 0x000000D7}. It seems the read is out of sync with the write. Below please find my code, I'm not sure what the issue is. I took much of the code from this ticket: https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/547391?tisearch=e2e-sitesearch&keymatch=msp432
/*************************
* Libraries
*************************/
/* DriverLib Includes */
#include "driverlib.h"
/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>
#include "AIC23B.h"
/************************
* Peripherals
************************/
/* 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[32];
/************************************
* Global variables
************************************/
//Digital audio buffers, read/wrote by DMA
uint32_t AudioDataIn[2], AudioDataOut[2]={0xAABBCCDD, 0x11223344};
//Data ready flag, to start audio processing
bool AudioDataReady=false;
/***********************************
* Main program
***********************************/
int main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
//Initialize Slave
initAic23b();
//Initialize SPI
//P3.5 CLK, P3.6 SIMO, P3.7 SOMI
P3->SEL0 |= GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7;
P3->SEL1 &= ~(GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7);
EUSCI_B_CMSIS(EUSCI_B2_BASE)->CTLW0 |= EUSCI_B_CTLW0_SWRST; // Hold USCI in Reset state
// UCB Settings:
// Master
// 3 Pin SPI
// 8 data bits
// Clock Source: SMCLK
// Bit Rate Divider
// No Modulation
// MSB First
// Clock Phase - UCCKPL = 0, UCCKPH = 1
EUSCI_B_CMSIS(EUSCI_B2_BASE)->CTLW0 = EUSCI_B_CTLW0_CKPH | EUSCI_B_CTLW0_MSB |
EUSCI_B_CTLW0_MST | EUSCI_B_CTLW0_MODE_0 | EUSCI_B_CTLW0_SYNC | EUSCI_B_CTLW0_UCSSEL_2 | EUSCI_B_CTLW0_SWRST;
//Set speed to desired frequency
EUSCI_B_CMSIS(EUSCI_B2_BASE)->BRW = (uint16_t)(CS_getSMCLK()/1000000);
EUSCI_B_CMSIS(EUSCI_B2_BASE)->CTLW0 &= ~EUSCI_B_CTLW0_SWRST; // Release reset state
/****************************************************
* DMA (coupled with SPI to make I2S)
****************************************************/
__enable_irq();
//Enable DMA module
DMA_enableModule();
DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
//Assign channel 4 to EUSCI_B2_TX, channel 5 to EUSCI_B2_RX
DMA_assignChannel(DMA_CH4_EUSCIB2TX0);
DMA_assignChannel(DMA_CH5_EUSCIB2RX0);
//Set TX transfer
DMA_setChannelControl(DMA_CH4_EUSCIB2TX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
DMA_setChannelTransfer(DMA_CH4_EUSCIB2TX0 | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, AudioDataOut,
(void *) MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B2_BASE),
8);
//Set RX transfer
DMA_setChannelControl(DMA_CH5_EUSCIB2RX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);
DMA_setChannelTransfer(DMA_CH5_EUSCIB2RX0 | UDMA_PRI_SELECT,
UDMA_MODE_BASIC,
(void *) MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE),
AudioDataIn,
8);
//Assign DMA interrupt : INT1 to TX channel
DMA_assignInterrupt(INT_DMA_INT1, 4);
//Enable interrupt
Interrupt_enableInterrupt(INT_DMA_INT1);
DMA_enableInterrupt(INT_DMA_INT1);
//Everything is set up, we can enable the two DMA channels
DMA_enableChannel(5);
DMA_enableChannel(4);
/* Interrupts activation */
Interrupt_enableMaster();
/* Main program loop */
while(1)
{
if(AudioDataReady==true) {
//Reset flag
AudioDataReady=false;
//The data is not being used yet, I'm setting a breakpoint here to check the values
//Start another DMA transfer. This will eventually be done via timer
//Set TX transfer
DMA_setChannelControl(DMA_CH4_EUSCIB2TX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
DMA_setChannelTransfer(DMA_CH4_EUSCIB2TX0 | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, AudioDataOut,
(void *) MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B2_BASE),
8);
//Set RX transfer
DMA_setChannelControl(DMA_CH5_EUSCIB2RX0 | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);
DMA_setChannelTransfer(DMA_CH5_EUSCIB2RX0 | UDMA_PRI_SELECT,
UDMA_MODE_BASIC,
(void *) MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE),
AudioDataIn,
8);
//Enable interrupt
Interrupt_enableInterrupt(INT_DMA_INT1);
DMA_enableInterrupt(INT_DMA_INT1);
//Everything is set up, we can enable the two DMA channels
DMA_enableChannel(5);
DMA_enableChannel(4);
}
}
}
/** Interrupt routines */
/* Completion interrupt for DMA */
void DMA_INT1_IRQHandler(void)
{
//Clear interrupt flag
DMA_clearInterruptFlag(4);
//Set flag for audio processing
AudioDataReady=true;
}
