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).