2025-06-01 11:29 AM
Hello, the problem here is that SPI works :) I am successfully using SPI on my STM32H743 MCU for many years now.
Now I encountered the problem with the same code, the same configuration of SPI but the difference is that the slave SPI chip is not there ( a new module with the same chip is not yet assembled). I am running the same code to debug something else , yet this SPI communication returns HAL_OK ! No timeout!
I never had this before ('cause I always had my slave chip connected) . The HAL_SPI_TransmitReceive() function of SPI library still returns HAL_OK :)
Here is a fragment of my code (SPI configured duplex master, data 16-bit, FIFO =1, speed 1.875 MBits/s, software driving CS) :
Spi4NSSEn; // chip select enabled
// addr_cmd[] provides 2 addresses for 2 channels of ADC converter
// pots_bin is a buffer for the ADC result in 0-256 range of POT sweep
if(HAL_SPI_TransmitReceive(&pots_hspi, (uint8_t *)addr_cmd, (uint8_t *)pots_bin, 2, 5000) != HAL_OK ) // transmit and receive 2 data frames (16-bit each)
{
Spi4NSSDis; // chip select dissable
return false;
}
I think that HAL_SPI_TransmitReceive() function should return HAL_TIMEOUT or HAL_ERROR but debugging through the lines looks like everything "works fine" with non-existent slave ! And code seems to be "logical" ... I promise here that SPI slave is not present , MCU is talking to the Universe :)
Please somebody let me know which part of HAL_SPI_TransmitReceive() code should return error from non-existent slave so I could find why it is not getting there.
All library is the latest and so STM32CubeIDE v. 1.18.1
Solved! Go to Solution.
2025-06-01 11:30 PM - edited 2025-06-01 11:33 PM
@eBirdman wrote:So if I understand correctly the timeout is only for the MCU internal SPI driver to check it's configuration, right? This is only useful for debugging of a newly configured device. Once configuration is working who needs the always running checkup of configuration ?
The HAL_SPI_TransmitReceive waits for a bit in some SPI status register to flip. If properly configured it should always flip (though a cosmic ray or power supply glitch can crash the peripheral). If it doesn't flip the function would otherwise get stuck. Sometimes SPI needs to be reconfigured for different devices (different clock frequency for instance) at runtime. In theory you could break something there. Perhaps set the clock frequency way too low so the transaction does finish, but takes 100 times longer, effectively freezing the application if it is a realtime application. Alternatively you can use the non-blocking function so only the SPI part of the application freezes.
@eBirdman wrote:I am using INA239 2-channel SPI ADC converter from TI .
This device has a device ID register. A perfect register to check presence of the chip at startup. It's a reasonable assumption the chip is not going to be disconnected at runtime. Though it doesn't hurt to do sanity checks on values.
The last bit of the temperature register reads as 0. So with a pullup and no device it would read all 1's.
Bus voltage, current and power registers are full range, so all possible values are valid. So your application could detect values that are too high as an error. This would cover a broken circuit, broken ADC or disconnected ADC.
2025-06-01 11:34 AM
2025-06-01 11:37 AM - edited 2025-06-01 11:37 AM
This is the expected behavior. The SPI transmit and/or receive function on the master will succeed regardless of whether or not the slave is there. There is no two-way handshake or acknowledgement like there is with I2C.
2025-06-01 11:38 AM - edited 2025-06-01 11:43 AM
SPI is simply 2 shift registers. There is no error detection in SPI (though some chips add an optional checksum/crc to the data).
The master does not know if the MISO pin is floating, shorted or connected to a slave.
I recommend enabling a pull-up or pull-down on the MISO pin so that if no slave is connected (or not selected via CSN) the data is always all 1' or all 0's. The application has to do a sanity check to see if the data is valid.
The master cannot detect if the slave is listening to the MOSI line either. There is no ACK (usually).
SPI doesn't have timeouts and doesn't need it since it's realtime. Data is clocked in and out and then the transaction is done. There is no asynchronous response to wait for (UART) and no clock stretching (I2C).
2025-06-01 12:26 PM
This is confusing. The api defined as
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
And the code you can search for "Timeout management" to see it handling user's Timeout (which in my case 5sec) and also library defined HAL_MAX_TIMEOUT .
Does it have anything to do with slave chip?
2025-06-01 2:00 PM - edited 2025-06-01 2:02 PM
The timeout is there in case there peripheral is not configured correctly or crashes somehow. That way the blocking function will not wait forever for the transaction to finish. The SPI transactions are usually shorter than 1 millisecond. So waiting for 2 ticks is plenty (1-2ms).
What slave are you connecting? Please tell me the exact model.
2025-06-01 2:25 PM
I am using INA239 2-channel SPI ADC converter from TI . So if I understand correctly the timeout is only for the MCU internal SPI driver to check it's configuration, right? This is only useful for debugging of a newly configured device. Once configuration is working who needs the always running checkup of configuration ?
2025-06-01 11:30 PM - edited 2025-06-01 11:33 PM
@eBirdman wrote:So if I understand correctly the timeout is only for the MCU internal SPI driver to check it's configuration, right? This is only useful for debugging of a newly configured device. Once configuration is working who needs the always running checkup of configuration ?
The HAL_SPI_TransmitReceive waits for a bit in some SPI status register to flip. If properly configured it should always flip (though a cosmic ray or power supply glitch can crash the peripheral). If it doesn't flip the function would otherwise get stuck. Sometimes SPI needs to be reconfigured for different devices (different clock frequency for instance) at runtime. In theory you could break something there. Perhaps set the clock frequency way too low so the transaction does finish, but takes 100 times longer, effectively freezing the application if it is a realtime application. Alternatively you can use the non-blocking function so only the SPI part of the application freezes.
@eBirdman wrote:I am using INA239 2-channel SPI ADC converter from TI .
This device has a device ID register. A perfect register to check presence of the chip at startup. It's a reasonable assumption the chip is not going to be disconnected at runtime. Though it doesn't hurt to do sanity checks on values.
The last bit of the temperature register reads as 0. So with a pullup and no device it would read all 1's.
Bus voltage, current and power registers are full range, so all possible values are valid. So your application could detect values that are too high as an error. This would cover a broken circuit, broken ADC or disconnected ADC.
2025-06-02 9:47 AM
Thanks a lot to all the characters of array even though unsigned :)