2024-02-14 08:46 PM
STM says: OCTOSPI can generate a "regular SPI" transaction. But is not true:
A "regular SPI transaction" means actually on OCTOSPI: a half-duplex SPI transaction (using just IO0, but for both directions).
I you want to generate a "regular" SPI transactions, as full-duplex ! (IO0 = MOSI, IO1 = MISO, bi-directional) - it is NOT possible.
OCTOSPI cannot do WRITE and READ at the same time (always just half-duplex), And the pins for OCTOSPI are NOT shared with a "regular SPI device" (like SPI1, SPI2, SPI3).
Here is a solution:
Now I have a shared use of the OCTOSPI pins (as QSPI), also like a "regular SPI" (e.g. changing to full-duplex, bi-directional SPI slave connected).
See my schematics for it at the end:
connect SCK from OCTOSPI Master to SPI3 Slave SCK and listen on OCTOSPI IO1 as SPI3 Slave MOSI (RX). It works (up to 40 MHz).
The project is here (for my own PCB, on NUCLEO board you need two flying wires):
https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI
Remark:
The OCTOSPI cannot generate just a transaction without CMD. So, the first data byte to send via OCTOSPI as "regular" SPI master goes into the CMD register. Now the following bytes to send can be the data part (no ADDR and no ALT bytes to send).
This makes it a bit tricky on SPI3 as Slave RX: the first two bytes come very fast together: one data byte is the CMD byte and then the 2nd data byte, without any gap on SCK signal.
So, my TX and RX loop looks like this:
do
{
*((__IO uint8_t *)data_reg) = *hospi->pBuffPtr;
/* Wait till fifo threshold or transfer complete flags are set to read received data */
status = OSPI_WaitFlagStateUntilTimeout(hospi, (HAL_OSPI_FLAG_FT | HAL_OSPI_FLAG_TC), SET, tickstart, Timeout);
if (status != HAL_OK)
{
break;
}
if (i == 0)
{
/* on first iteration we get CMD and one byte! */
while ( ! __HAL_SPI_GET_FLAG(&hspi3, SPI_FLAG_RXP)) {;}
*(hospi->pBuffPtr - 1) = SPI3->RXDR;
while ( ! __HAL_SPI_GET_FLAG(&hspi3, SPI_FLAG_RXP)) {;}
*hospi->pBuffPtr = SPI3->RXDR;
i = 1;
}
else
{
while ( ! __HAL_SPI_GET_FLAG(&hspi3, SPI_FLAG_RXP)) {;}
*hospi->pBuffPtr = SPI3->RXDR; //XXXX
}
hospi->pBuffPtr++;
hospi->XferCount--;
} while (hospi->XferCount > 0U);
See, that I am expecting to get two bytes at the beginning (CMD with data0 and regular data1), sent by the OCTOSPI TX when starting the transaction.
Schematics:
Here the schematics I use on my PCB (SPI3 is a Slave listener on OCTOSPI signals). On a NUCLEO board you need external wires to accomplish the same (see the pink traces under the STM MCU chip, on NUCLEO board as flying wires).
Only this gives me a REAL "regular" SPI on OCTOSPI (with sharing the same pins).
Solved! Go to Solution.
2024-02-14 08:47 PM
It works fine for me (except: SPI3 as Slave is not so fast as OCTOSPI can generate transactions, max. is 40 MHz).
2024-02-14 08:47 PM
It works fine for me (except: SPI3 as Slave is not so fast as OCTOSPI can generate transactions, max. is 40 MHz).