I'm running my program on a MSP430F5347 processor with the TI FET430UIF, and IAR Embedded Workbench
The version of msp430.dll found inside the IAR folder is 2.4.2.0, the version of hil.dll is 1.2.6.0
The problem I'm experience is that when a breakpoint is used during a DMA transfer the processor simply resets.
If I load the msp430.dll version 2.4.1.0, I don't see this issue.
Below is the code i was running and the setup I have.
- One SPI port is configured to always run as master (UCA0), and one SPI port is configured to always run as slave (UCA1).
- DMA channel 0 is used to send messages out UCA0, and DMA channel 1 is used to read messages from UCA1.
- The hardware on the other end of the SPI is configured similarly (1 master SPI port, and 1 slave SPI port). That hardwares master is connected to the MSP slave, and slave is connected to the MSP master. When that hardware gets data from the MSP430, it will then send back data to the MSP430.
If I place a breakpoint at the while (1) {} code in main, and single step, the whole thing just resets.
#include "msp430f5437.h"
//==== Port Data======
#define PIN_OUTPUT_DIRECTION (0xff)
#define PIN_INPUT_DIRECTION (0x00)
//Port 3 bit locations
#define UCx_SPIX_SCK BIT0 //output pin
#define UCx_SPIX_CS_N BIT3 //output pin, active low
#define UCx_SPIX_MOSI BIT4 //output pin
#define UCx_SPIX_MISO BIT5 //not used
#define UCx_SPIS_SCK BIT6
//Port 5 bit locations
#define UCx_XT2IN BIT2
#define UCx_XT2OUt BIT3
#define UCx_SPIS_CS_N BIT5 //active low
#define UCx_SPIS_MOSI BIT6
#define UCx_SPIS_MISO BIT7 //un-used
// Port 7 bit locations
#define UCx_XIN BIT0
#define UCx_XOUT BIT1
// global variable flags used to see if a transfer was finished
unsigned int dma0done;
unsigned int dma1done;
#pragma vector = DMA_VECTOR
__interrupt void dmaIntHdlr (void)
{
unsigned int interrReg = DMAIV;
switch (interrReg)
{
case DMAIV_DMA0IFG: //if master finished, turn off chip select
{
dma0done ++;
//clear chip select
P3OUT |= UCx_SPIX_CS_N;
//clear interrupt and disable channel
DMA0CTL &= (~DMAEN | ~DMAIFG);
break;
}
case DMAIV_DMA1IFG:
{
dma1done ++;
//clear interrupt and disable channel
DMA1CTL &= (~DMAEN | ~DMAIFG);
break;
}
};
}
static void setupClock ()
{
//configure port 5 (16 MHz) and port 7 (32kHz)
//set as peripherals
P5SEL |= UCx_XT2IN | UCx_XT2OUT;
P7SEL |= UCx_XIN | UCx_XOUT;
//ACLK src = XT1, sclk src = XT2, mclk src = XT2
UCSCTL4 = SELA__XT1CLK + SELS__XT2CLK + SELM_XT2CLK;
//turn on the oscillators
UCSCTL6 &= ~(XT1OFF + XT2OFF);
//load cap 12 pF
UCSCTL6 |= XCAP_3;
UCSCTL6 &= ~SMCLKOFF;
//clear oscillator faults
while (SFPIFG1 & OFIFG)
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HOFFG + DCOFFI);
//attempt to clear fault flag
SFRIFG1 &= ~OFIFG;
}
//assign the clocks
UCSCTL6 &= ~(XT1DRIVE_0);
UCSCTL6 &= ~(XT2DRIVE_2);
}
static void configDma ()
{
DMA0CTL &= ~DMAEN;
DMA1CTL &= ~DMAEN;
//DMA 0 is for TX, so set trigger to master SPI TX buffer empty
//DMA 1 is for RX, so set trigger to salve SPI RX buffer full
DMACTL0 = DMA0TSEL__USCIA0TX | DMA1TSEL__USCIA1RX;
//single xfer, dest const, src incremening, byte, interrupt enable, edge
DMA0CTL = DMADT_0 | DMADSTINCR_0 | DMASRCINCR_3 | DMASBDB | DMAIE;
//single xfer, dest incremening, src const, byte, interrupt enable, edge
DMA1CTL = DMADT_0 | DMADSTINCR_3 | DMASRCINCR_0 | DMASBDB | DMAIE;
DMACTL4 |= DMARMWDIS_L; //I have tried both setting this and not setting this
}
static void configSpi ()
{
//mast port
UCA0CTL1 = UCSWRST;
UCA0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC;
UCA0CTL1 = UCSSEL__SMCLK | UCSWRST;
UCB0BRW = 0x0010;
P3SEL |= UCx_SPIX_SCK | UCx_SPIX_MOSI;
P3SEL &= ~(UCx_SPIX_CS_N | UCx_SPIX_MISO);
P3DIR |= UCx_SPIX_SCK | UCx_SPIX_CS_N | UCx_SPIX_MOSI | UCx_SPIX_MISO;
//turn off chip select, pin is active low
P3OUT |= UCx_SPIX_CS_N;
UCA0IE = 0x00;
UCA0CTL1 &= ~UCSWRST
//slave port
UCA1CTL1 = UCSWRST;
UCA1CTL0 = UCCKPH | UCMSB | UCSYNC;
P3SEL |= UCx_SPIS_SCK;
P3DIR &= ~UCx_SPIS_SCK;
P5SEL |= UCx_SPIS_MOSI;
P5SEL &= ~(UCx_SPIS_CS_N | UCx_SPIS_MISO);
P5DIR &= ~(UCx_SPIS_CS_N | UCx_SPIS_MOSI);
P5DIR |= UCx_SPIS_MISO;
UCA1IE = 0x00;
UCA1CTL &= ~UCSWRST;
}
static void appStartup ()
{
P1DIR = PIN_OUTPUT_DIRECTION;
P2DIR = PIN_OUTPUT_DIRECTION;
P3DIR = PIN_OUTPUT_DIRECTION;
P4DIR = PIN_OUTPUT_DIRECTION;
P5DIR = PIN_OUTPUT_DIRECTION;
P6DIR = PIN_OUTPUT_DIRECTION;
P7DIR = PIN_OUTPUT_DIRECTION;
P1OUT = 0xff;
P2OUT = 0xff;
P3OUT = 0xff;
P4OUT = 0xff;
P5OUT = 0xff;
P6OUT = 0xff;
P7OUT = 0xff;
setupClock();
configSpi ();
configDma ();
P1IFG = 0;
P2IFG = 0;
}
//just some data to send to the hardware, once hardware receives this, it should send back some other data
unsigned char outMessage [] = {0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa};
//hardware sends back 12 bytes of data on receiving the first message
unsigned char inMessage [12] = {0};
void main ()
{
WDTCTL = WDTPW + WDTHOLD;
__enable_interrupt ();
dma0done = 0;
dma1done = 0;
appStartup ();
//toggle the reset
UCA0CTL1 |= UCSWRST;
UCA0CTL1 &= ~UCSWRST;
UCA1CTL1 |= UCSWRST;
UCA1CTL1 &= ~UCSWRST;
//ready the receive dma channel first
DMA1SA = (__data20 unsigned int *)&UCA1RXBUF;
DMA1DA = inMessage;
DMA1SZ = 12;
DMA1CTL |= DMAEN;
//set the chip select and ready the master/tx dma channel
P3OUT &= ~UCx_SPIX_CS_N;
DMA0SA = outMessage;
DMA0DA = (__data20 unsigned int *)&UCA0TXBUF;
DMA0SZ = sizeof(outMessage);
DMA0CTL |= DMAEN;
//trigger the transfer buffer empty to initiate transfer
UCA0IFG &= ~UCTXIFG;
UCA0IFG |= UCTXIFG;
while (1) {}
}