Part Number: MSP430F6659
I've had this problem on two different peripheral chips, but the one I'm showing here is the code for a DRV8353RS motor driver chip since that's also a ti product.
I'm writing in the last update of version 8 of Code Composer Studio.
Here's the SPI init.
void drv_spi_init(){
// p9.4-6
P9SEL |= (BIT4 | BIT5 | BIT6);
USCI_B_SPI_initMasterParam drv_param = {0};
drv_param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK; //Verified
drv_param.clockSourceFrequency = UCS_getSMCLK(); //"In SPI master mode, there is only one reason why UCBUSY never gets clear: you don’t have a clock."
drv_param.desiredSpiClock = 9600000; //Verified, subject to change
drv_param.msbFirst = USCI_B_SPI_MSB_FIRST; //Verified
drv_param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT; //Somewhat Verified. (Data is captured on the falling edge and propagated on the rising edge)
drv_param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW; //Verified via diagram, no text.
if(USCI_B_SPI_initMaster(USCI_B2_BASE, &drv_param)){
_no_operation();
} else{
drv_error_vector |= SPI_NO_INIT;
}
//This enable definitely goes after the init, I checked it twice.
USCI_B_SPI_enable(USCI_B2_BASE);
}
Here's the read function
uint16_t drv_single_read_only(uint8_t address){
address &= 0x0F; //Addresses for this device are only 4 bits.
address <<= 3; //And for read only commands, should be placed immediately following a leading 0 bit.
//They want a full data frame to be 16 bits even if you're only reading a single register and have no data to give them.
drv_rx_pos = 0;
drv_tx_pos = 0;
drv_tx_buff[drv_tx_pos] = address; //Load the command (This is somewhat redundant since this is read only, and only one register, but for write ops and multiregister ops, it's useful)
drv_tx_buff[drv_tx_pos + 1] = 0x00; //Load the data
//Turn on RX interrupt
USCI_B_SPI_enableInterrupt (USCI_B2_BASE, USCI_B_SPI_RECEIVE_INTERRUPT);
//Turn on TX interrupt
USCI_B_SPI_enableInterrupt (USCI_B2_BASE, USCI_B_SPI_TRANSMIT_INTERRUPT);
for(regular_timer_outer = 0xFFFF; ((regular_timer_outer > 0) && (!USCI_B_SPI_isBusy(USCI_B2_BASE))); regular_timer_outer--){
_no_operation();
}
if (!(regular_timer_outer > 0)){
drv_error_vector |= SPI_BUSY;
}
USCI_B_SPI_transmitData (USCI_B2_BASE, drv_tx_buff[drv_tx_pos]);
//UCB2TXBUF = drv_tx_buff[drv_tx_pos]; //This starts off the chain. Once it shifts out, the interrupt triggers and shifts out the next byte.
for(regular_timer_outer = 0xFFFF; (regular_timer_outer > 0) && ((drv_tx_pos < 2) || (drv_rx_pos < 2)); regular_timer_outer--){
_no_operation();
}
if (!(regular_timer_outer > 0)){
if(drv_tx_pos < 2){
drv_error_vector |= TX_TIMEOUT;
}
if(drv_rx_pos < 2){
drv_error_vector |= RX_TIMEOUT;
}
}
//Turn off RX interrupt
USCI_B_SPI_disableInterrupt (USCI_B2_BASE, USCI_B_SPI_RECEIVE_INTERRUPT);
//Turn off TX interrupt
USCI_B_SPI_disableInterrupt (USCI_B2_BASE, USCI_B_SPI_TRANSMIT_INTERRUPT);
uint16_t temp = 0;
temp = drv_rx_buff[0];
temp <<= 8;
temp |= drv_rx_buff[1];
return temp;
}
So, we're getting consistent SPI Busy being raised, and we're never getting a TX/RX interrupt trigger.
I have already tried disabling and re-enabling the SPI module before the read, and during each SPI busy check. I have one version of the board that has a 3.3v pullup resistor on the SDO line, and another board that does not, both get the same error. I have also tried to bypass the SPI module's clock scaler by setting SMCLK to the desired 96000 baud. I've also lowered the speed by a factor of 10, which also did not see any change in behavior. I've also tried to use ACLK, though I didn't change as many of those settings afterwards.
Questions:
1) How can I further determine whether this is a hardware or a software issue?
2) Can you point me to where I can find the register info for the SPI module so I can try a more manual approach?
3) Is there something obvious I'm missing from having spent so long bashing my head against this? (Which reminds me, yes I did double check that the chip I'm trying to talk to is in fact on B2).