Hi, I am trying to interface a TMS320F28335ZJZA to an iC-Haus iC-MHM position sensor over SPI. The sensor SPI interface requires multiple (8) 8-bit words in a single SPI frame. I'm having trouble configuring the McBSP on the F28335 to send and receive data this way.
It seems like there are three options. Each of these examples uses only 2 words per frame instead of 8 for simplicity:
Option 1, Polling: This code successfully sends the first 8-bit word in the frame but then produces RSYNCERR and XSYNCERR during the second word transmission.
McBSP configuration:
McbspbRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
McbspbRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word, Digital loopback dis.
McbspbRegs.SPCR1.bit.DLB = 1;
McbspbRegs.SPCR1.bit.CLKSTP = 3; // clock stop mode bits (0-1: disabled, 2: clock stop with no clock delay, 3: clock stop with half-cycle delay)
McbspbRegs.PCR.bit.FSXM = 1; //transmit frame synch mode bit (0: external pin, 1: supplied by sample rate generator)
McbspbRegs.PCR.bit.FSRM = 1; //receive frame synch mode bit (0: external pin, 1: supplied by sample rate generator)
McbspbRegs.PCR.bit.CLKXM = 1; //transmit clock mode bit (in stop clock mode: 0: slave in SPI, 1: master in SPI)
McbspbRegs.PCR.bit.CLKRM = 1; //receive clock mode bit (in loopback mode: 0: MCLKR pin in high impedance state, 1: internal MCLKR driven by internal CLKX)
McbspbRegs.PCR.bit.SCLKME = 0; //sample rate generator input clock mode bit, used with CLKSM to select input clock
McbspbRegs.PCR.bit.DX_STAT = 0; //DX pin bit (0: drive DX pin low, 1: drive DX pin high)
McbspbRegs.PCR.bit.DR_STAT = 0; //DR pin status bit (0: DR pin is low, 1: DR pin is high)
McbspbRegs.PCR.bit.FSXP = 1; //transmit frame-synch polarity bit (0: transmit frame-synch pulses are active high, 1: active low)
McbspbRegs.PCR.bit.FSRP = 0; //receive frame-synch polarity bit (0: receive frame-synch pulses are active high, 1: active low)
McbspbRegs.PCR.bit.CLKXP = 0; //transmit clock polarity bit (transmit data sampled on 0: rising, 1: falling edge)
McbspbRegs.PCR.bit.CLKRP = 1; //receive clock polarity bit (transmit data sampled on 0: falling, 1: rising edge)
McbspbRegs.RCR1.bit.RWDLEN1= 0; // 8-bit word receive
McbspbRegs.RCR1.bit.RFRLEN1= 1; // 2-word frames
McbspbRegs.RCR2.bit.RDATDLY= 1; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspbRegs.XCR1.bit.XWDLEN1= 0; // 8-bit word transmit
McbspbRegs.XCR1.bit.XFRLEN1= 1; // 2-word frames
McbspbRegs.XCR2.bit.XDATDLY= 1; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
McbspbRegs.SRGR2.all=0x0000;
McbspbRegs.SRGR2.bit.CLKSM = 1; //sample rate generator input clock mode bit (used with SCLKME bit)
McbspbRegs.SRGR2.bit.FPER = 0; //frame synch period bits for FSG, FPER = 1 CLKG periods
McbspbRegs.SRGR1.bit.FWID = 0; // Frame Width = 1 CLKG period
McbspbRegs.SRGR1.bit.CLKGDV = 0x95; //divide-down value for CLKG, SPI_CLK_FREQ = INCLK / (CLKGDV+1) => 150mhz/150=1mhz spi clk
McbspbRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
delay_loop(); // Wait at least 2 SRG clock cycles
McbspbRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspbRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspbRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
Transmission (foreground):
while( McbspbRegs.SPCR2.bit.XRDY == 0 ) { checkErrors(); } //wait for current data to clear transmit buffer
McbspbRegs.DXR1.all = sdata[0]; //write to transmit buffer
while( McbspbRegs.SPCR2.bit.XRDY == 0 ) { checkErrors(); } //wait for current data to clear transmit buffer
McbspbRegs.DXR1.all = sdata[1]; //write to transmit buffer
while( McbspbRegs.SPCR1.bit.RRDY == 0 ) { checkErrors(); } //wait to receive data
rdata[0] = McbspbRegs.DRR1.all; //read from receive buffer
while( McbspbRegs.SPCR1.bit.RRDY == 0 ) { checkErrors(); } //wait to receive data
rdata[1] = McbspbRegs.DRR1.all; //read from receive buffer
void checkErrors(void){
if(McbspbRegs.SPCR1.bit.RFULL){
error();
}
if(McbspbRegs.SPCR1.bit.RSYNCERR){
error();
}
if(McbspbRegs.SPCR2.bit.XSYNCERR){
error();
}
EALLOW;
if(DmaRegs.CH1.CONTROL.bit.OVRFLG){
error();
}
EDIS;
}
Option 2, DMA: This code produces similar output as option 1, successfully sending the first 8-bit word in the frame and then producing RSYNCERR and XSYNCERR during the second word transmission.
McBSP configuration: same as option 1.
DMA configuration:
EALLOW;
DmaRegs.DMACTRL.bit.HARDRESET = 1;
asm(" NOP"); // Only 1 NOP needed per Design
DmaRegs.CH1.MODE.bit.CHINTE = 0;
// Channel 1, McBSPB transmit
DmaRegs.CH1.BURST_SIZE.all = 0; // 1 word/burst
DmaRegs.CH1.SRC_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.DST_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.TRANSFER_SIZE = 1; // Interrupt every frame (2 bursts/transfer)
DmaRegs.CH1.SRC_TRANSFER_STEP = 1; // Move to next word in buffer after each word in a burst
DmaRegs.CH1.DST_TRANSFER_STEP = 0; // Don't move destination address
DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32) &sdata[0]; // Start address = buffer
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32) &sdata[0]; // Not needed unless using wrap function
DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32) &McbspbRegs.DXR1.all; // Start address = McBSPB DXR
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = (Uint32) &McbspbRegs.DXR1.all; // Not needed unless using wrap function
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear peripheral interrupt event flag
DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear sync flag
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // Clear sync error flag
DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF; // Put to maximum - don't want destination wrap
DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // Put to maximum - don't want source wrap
DmaRegs.CH1.MODE.bit.SYNCE = 0; // No sync signal
DmaRegs.CH1.MODE.bit.SYNCSEL = 0; // No sync signal
DmaRegs.CH1.MODE.bit.CHINTE = 1; // Enable channel interrupt
DmaRegs.CH1.MODE.bit.CHINTMODE = 1; // Interrupt at end of transfer
DmaRegs.CH1.MODE.bit.PERINTE = 1; // Enable peripheral interrupt event
DmaRegs.CH1.MODE.bit.PERINTSEL = DMA_MXEVTB; // Peripheral interrupt select = McBSP MXSYNCB
DmaRegs.CH1.MODE.bit.CONTINUOUS = 0; //continuous: (1) DMA re-initializes when TRANSFER_COUNT is zero and waits for the next interrupt event trigger
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
// Channel 2, McBSPB Receive
DmaRegs.CH2.MODE.bit.CHINTE = 0;
DmaRegs.CH2.BURST_SIZE.all = 0; // 1 word/burst
DmaRegs.CH2.SRC_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH2.DST_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH2.TRANSFER_SIZE = 1; // Interrupt every 2 bursts/transfer
DmaRegs.CH2.SRC_TRANSFER_STEP = 0; // Don't move source address
DmaRegs.CH2.DST_TRANSFER_STEP = 1; // Move to next word in buffer after each word in a burst
DmaRegs.CH2.SRC_ADDR_SHADOW = (Uint32) &McbspbRegs.DRR1.all; // Start address = McBSPB DRR
DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = (Uint32) &McbspbRegs.DRR1.all; // Not needed unless using wrap function
DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &rdata[0]; // Start address = Receive buffer (for McBSP-B)
DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32) &rdata[0]; // Not needed unless using wrap function
DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1; // Clear peripheral interrupt event flag
DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1; // Clear sync flag
DmaRegs.CH2.CONTROL.bit.ERRCLR = 1; // Clear sync error flag
DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF; // Put to maximum - don't want destination wrap
DmaRegs.CH2.SRC_WRAP_SIZE = 0xFFFF; // Put to maximum - don't want source wrap
DmaRegs.CH2.MODE.bit.CHINTE = 1; // Enable channel interrupt
DmaRegs.CH2.MODE.bit.CHINTMODE = 1; // Interrupt at end of transfer
DmaRegs.CH2.MODE.bit.PERINTE = 1; // Enable peripheral interrupt event
DmaRegs.CH2.MODE.bit.PERINTSEL = DMA_MREVTB; // Peripheral interrupt select = McBSP MRSYNCB
DmaRegs.CH2.MODE.bit.CONTINUOUS = 0; //continuous: (1) DMA re-initializes when TRANSFER_COUNT is zero and waits for the next interrupt event trigger
DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
EDIS;
Option 3, Interrupts: This will be the next thing to try, but I suspect I am doing something wrong with the previous two options.
Please advise.
Additional info:
CCS 6.1.0.00104
ControlCARD, C28343 Experimenter's Kit