By default, HAL functions (HAL_SPI_TransmitReceive_IT/HAL_SPI_Transmit_IT/HAL_SPI_Receive_IT) assume that SPI is disabled between function invocation.
It's needed to set transfer size (CR2 register), that can be modified only if SPI disabled. But `stm32_spi_api.c` keeps SPI enabled after initialization.
This commit adds helper code for STM32H7 (SPI_IP_VERSION_V2) that disables SPI before HAL_SPI_TransmitReceive_IT/HAL_SPI_Transmit_IT/HAL_SPI_Receive_IT
and after end of transaction for HAL API compatibility.
Update SPI logic to process 16 bit words in the same way by sync/async,
3/4 wires modes:
- fix 3-wire synchronous transmission to move 2 or more bytes between buffer and
SPI register per word tarnsmission
- fix 4-wire synchronous transmission to move 2 or more bytes between buffer and
SPI register per word tarnsmission
`HAL_SPI_Receive_IT` HAL function causes dummy reads in 3-wire mode,
that causes data corruption in RX FIFO/register. It isn't possible
to fix it without signification refactoring, but we may prevent data
corruption with the following fixes:
- RX buffer/register cleanup after asynchronous transfer in 3-wire mode
- Explicit RX buffer/register cleanup after SPI initialization
(for cases if we re-create SPI object).
All STM32 families except STM32H7 has the following 3-wire SPI peculiarity in master receive mode:
SPI continuously generates clock signal till it's disabled by a software. It causes that a software
must disable SPI in time. Otherwise, "dummy" reads will be generated.
Current STM32 synchronous SPI 3-wire implementation relies on HAL library functions HAL_SPI_Receive/HAL_SPI_Transmit.
It performs some SPI state checks to detect errors, but unfortunately it isn't fast enough to disable SPI in time.
Additionally, a multithreading environment or interrupt events may cause extra delays.
This commit contains the custom transmit/receive function for SPI 3-wire mode. It uses critical sections to
prevents accidental interrupt event delays, disables SPI after each frame receiving and disables SPI during
frame generation. It adds some delay between SPI frames (~700 ns), but gives reliable 3-wire SPI communications.
- move a code that waits readable SPI state from `spi_master_write`
function to inline functions `msp_writable` and `msp_wait_writable`
- move a code that waits writeable SPI state from `spi_master_write`
function to inline functions `msp_readable` and `msp_wait_readable`
- move a code that writes data to SPI from `spi_master_write`
function to inline function `msp_write_data`
- move a code that reads data from SPI from `spi_master_write`
function to inline function `msp_read_data`
Static pinmap extension required to use pin_function() and pin_mode() functions instead of pinmap_pinout(). Unfortunatelly pin_function() does not allow passing NC pin.
Call pin_function() and pin_mode() only if MISO/MOSI pin is not NC.
With tickless mechanism hsem can be used for quite a long time
(time to set up PLL clock).
Also, if hsem is held to long, then this is not the current core which is faulty,
but probably the other (the one which hold the HSEM)
Add 2 targets for DISCO_H747I dualcore:
* DISCO_H747I -> for CM7 core
* DISCO_H747I_CM4 -> for CM4 core
Current restrictions:
* TICKLESS deactivated
* DeepSleep not supported (DeepSleep wrapped to sleep)
Warning: use of the same IP (example I2C1) by both core at the same time is not prevented,
but is strongly not recommended.
Some Hardware Semaphore are use for common IP, to manage concurrent access by both cores: Flash, GPIO, RCC.
Warning: Drag and drop of binary to DISCO_H747I will flash CM7.
In order to flash CM4, one can use STM32 CubeProgrammer tool.
Add a pulse when using hardware chip select for SPI transmissions.
CS is at low level when a transmission is on-going.
Be careful, this is not compatible with all modes. It will work only
if PHA is 0, ie spi mode is 0 or 2. See stm32xx reference manual,
chapter "NSS pulse mode" for more details.
Fix#10671
Signed-off-by: Vincent Veron <vincent.veron@st.com>
The DEVICE_FOO macros are always defined (either 0 or 1).
This patch replaces any instances of a define check on a DEVICE_FOO
macro with value test instead.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
This patch handles the case of SPI slave mode without MISO (NC).
In case MISO is not connected, we consider that SPI will be configured in
3 wires mode (CLK / MOSI / CS, but no MISO). In this case, the MOSI line
is bi-directional : SPI_DIRECTION_1LINE.
But as this is not supported yet in slave mode, we force it to
SPI_DIRECTION_2LINES. In this case slave SPI will receive data on MOSI
but nothing will be sent back to master as MISO is not connected.
Enabling SPI causes the clock to be output by default.
Most devices will not care about extra clock cycles, especially as long
as chip select is not active, nevertheless this may cause side issues
with other devices especially during init phase.
This was actually the case with a 3 wire device (LPS22HB sensor).
In case MISO is not passed at SPI init, then we consider a 3 wires SPI
configuration is requested, which corresponds to SPI_DIRECTION_1LINE
configuration parameter in STM32 HAL layer.
We're then handling this specific case of SPI_DIRECTION_1LINE,
in spi_master_write or spi_master_block_write, we call to HAL API
This commit implements a SPI mode which will offer better performance
thanks to usage of Lower Layer API which use fewer registers access,
at the cost of lower robustness (no error management).
There is an easy default implementation of spi_master_block_write that
just calls spi_master_write in a loop, so the default implementation
of spi_master_block_write has been added to all targets.