This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Part Number: MSP432P401R
I noticed a weird behaviour with library function
uint_fast8_t SPI_getInterruptStatus(uint32_t moduleInstance, uint16_t mask)
In breif, used to check whether UCxTXBUF is ready for a new byte during a multi-byte transmission, if previously sent byte MSB was '1' it sets SPI SIMO pin high.
I replaced
while (!SPI_getInterruptStatus(DevHandle->SensorSpiModule, SENSE_SPI_TRANSMIT_INTERRUPT));
with the following instruction
while(!(UCTXIFG & SENSE_SPI_INTERRUPT_FLAG_REGISTER));
circumventing the issue, that actually was negatively affecting communication with my slave SPI sensor.
Is that the expected behaviour for SPI_getInterruptStatus anyway?
That function (the source is right there in \TI) just reads the USCI IFG register then AND-s it with the mask you supply.
What you're describing is an effect where reading the IFG alters the (Tx) data stream, which seems improbable. It's not just faith in the hardware -- I've seen a fair amount of code which uses this technique, and no one has reported an effect like this.
Is there any chance your driverlib source has been corrupted? (I did that once.) How sure are you that "DevHandle->SensorSpiModule" is correct?
Is there more context here?
Dear Bruce,
I was quite surprised as well. Unfortunately I did not save any oscilloscope trace. Anyway, I was configuring a SPI sensor which requires sequences of uint16_t values to be sent from master (MCU) to slave (sensor).
All I can say is that it was impossible for me to read back data from a specific register, and yes, even more weird: other registers worked.
I am configuring registers in sequence, repeating the following write-read procedure for each one:
Carefully analysing bus traffic with an oscilloscope I noticed that MOSI wire was always set high between the address byte and the dummy one, apparently with no reason. It was not being sampled at clock rising edge anyway, so in theory it shoudn't have been a problem. This didn't happen for the write routine, before sending the configuration byte. Changing the READ busy-wait method solved everything.
I will try to reproduce that as soon as I can, maybe by library is messed-up, or I inadvertently made some other change in the code and now it works regardless of how I implemented the busy wait.
Dear Bruce,
you can have a look at the oscilloscope traces below:
Yellow -> chipselect
blue -> MOSI
pink -> clock
green -> MISO
You were right: I was polling on the receive flag indeed,
while (!SPI_getInterruptStatus(DevHandle->SensorSpiModule, SENSE_SPI_TRANSMIT_INTERRUPT));
works just as expected:
I was programming the SPI controller to clear receive interrupt flag before sending a byte, and wait for it once the byte was sent. In the end, according to the SPI protocol you can assume slave has completely received a byte once you get one back, right? Well, placing the following code into the readout routine
// Transmit address byte SPI_transmitData(DevHandle->SensorSpiModule, (uint_fast8_t)(Address|(1<<7))); // Wait for RX buffer to be ready while (!SPI_getInterruptStatus(DevHandle->SensorSpiModule, SENSE_SPI_RECEIVE_INTERRUPT)); // Clear interrupt flag SPI_clearInterruptFlag(DevHandle->SensorSpiModule, SENSE_SPI_RECEIVE_INTERRUPT); // Transmit dummy-byte SPI_transmitData(DevHandle->SensorSpiModule, 0x00);
gets to the following traces:
It didn't seem to be likely that the microcontroller sets MOSI with no reason while resetting or polling an interrupt flag register. So, the last screenshot (3) has been acquired disconnecting sensor SDI from the MCU. The unexpected MOSI signal comes from the microcontroller. Yet, being reset before dummy byte is sent, MOSI glitch should not affect the readout procedure, isn't it?
Dear Bruce,
sorry for the late answer, but I have been waiting to collect some more details before replying.
First of all: thanks for the workaround hint, it is an interesting way to know when data is ready to be fetched.
The sensor is a LIS3DSH from STM. I got in contact with their tech assistance and they provided me an example project to run on my spare STM32eval. Well, according to the oscilloscope traces, the way they manage the SPI bus looks quite like the one I had implemented at first on MSP432. Master SDO retains address LSB (last bit sent) before the effective data byte is transferred (not MSB), but read/write operations succeed in any case.
Could it be that after idling the SPI peripheral wakes up with MISO pin set as output, compromising sensor output signal?
I attach a pair of acquisitions from STM environment:
WRITE:
READ:
Dear Bruce,
I made some additional tests and tried to hazard a guess regarding issue root causes.
You can have a look at the following link for further information.
https://community.st.com/s/question/0D50X00009kHRHISA4/failure-reading-from-lis3dsh-spi-interface
Hi Bob,
nice to hear from you again!
Did you have a look at the link in my previous post? Please let me know what you think about it, it's being viewed by many, but nobody replies..
Just to clutter the HOLD TIME computation out, I tried using SPI_isBusy(), as below:
// Transmit data byte SPI_transmitData(SensorInUse->ModuleInstance, (uint_fast8_t)SpiTxByte); // Wait for TX buffer to be ready while (!SPI_getInterruptStatus(SensorInUse->ModuleInstance, SPI_TRANSMIT_INTERRUPT_FLAG)); // Wait Spi to be ready while(SPI_isBusy(SensorInUse->ModuleInstance)); // Set CS GPIO_setOutputHighOnPin(SensorInUse->CsPort, SensorInUse->CsPin);
But ChipSel goes high before transmission ends.
(P.S. Waiting also for TX buffer to be ready could be redundant, I know)
I implemented your suggestion.
// Lower CS GPIO_setOutputLowOnPin(SensorInUse->CsPort, SensorInUse->CsPin); // Wait setup time while(--Timeout); // Wait for TX buffer to be ready while (!SPI_getInterruptStatus(SensorInUse->SerialPeripheral, SPI_TRANSMIT_INTERRUPT_FLAG)); // Transmit address byte SPI_transmitData(SensorInUse->SerialPeripheral, (uint_fast8_t)(SpiActiveAddress|(1<<7))); // Wait for TX buffer to be ready while (!SPI_getInterruptStatus(SensorInUse->SerialPeripheral, SPI_TRANSMIT_INTERRUPT_FLAG)); // Transmit dummy-byte SPI_transmitData(SensorInUse->SerialPeripheral, 0x00); // Wait for spi module to be ready while(SensorInUse->SpiModuleAddress->STATW & EUSCI_B_STATW_SPI_BUSY); // Set CS GPIO_setOutputHighOnPin(SensorInUse->CsPort, SensorInUse->CsPin);
It seems to work, hooray!
**Attention** This is a public forum