2024-10-21 02:49 AM - edited 2024-10-21 03:55 AM
Folks,
I've used SPI many times on STM32F1, F0, F4 devices, but am have a mare with a H563. I have two 74HC165s reading sixteen switches.
For hours and hours I couldn't get any clock out when I executed:
SPI2->TXDR = 0;
Eventually I tried setting the CSTART bit in the CR1 register (I really can't get my head round what the manual is trying to say for this bit, it's incredibly poorly written) and that then sprung the clock in to life for a burst of clock activity when I wrote 0 to the transmit register.
However, no matter what value is in DSIZE in the CFG1 register I always get 32 bit clocks sent out.
I am getting a sixteen bit value in the RX register, not a thirty-two-bit value though.
So, for example, if I set the switch that corresponds to the fourth data bit in the stream, I get the thirty-two clocks, but I get a value of 0x1000 in the RX register of the SPI peripheral. If I set the number of clocks in the DSIZE portion of CFG1 to thirty-two bits then I get 0x10000000 in the Rx register.
So, what on earth is going on with the SPI CLK on the SCLK pin here? Why is DSIZE making no difference to number of clocks? I'm assuming there's something fundamental I'm not understanding with this SPI peripheral on the H563, it does seem a load more complicated that previous SPI peripherals I've used.
Thanks!
2024-12-03 07:18 AM
Hello,
at new SPI applied at H5, the master starts the data transfer once the CSTART bit of the SPI_CR1 register is set, provided the SPI is enabled and the TxFIFO content is not empty. Both the SPI_TXDR and SPI_RXDR are sensitive to data casting (asm instruction applied for their read/write). When the access to/from the SPI_TXDR/SPI_RXDR registers is a multiple of the configured data size, data packing is applied automatically by the HW (the lowest significant bits/bytes are communicated first). If you have data size set to 4 bits and apply single 32-bit write access of the TXDR, you perform storage of 4 data in fact what should raise transaction 4x 4bit = 16 bit stream on the bus (data frames from 4 to 8 bits occupy always one byte of the FIFO each). You have applied sequence of two such access great probably what is performed by the system as 8x 4bit = 32 bit stream. Similar principle is valid for casting SPI_RXDR. By single 32-bit access of this register you perform reading 4 data from the RxFIFO. Moreover you can apply a flexible FIFOs threshold and group data into large packets. If it is set to 8 at your case, the stream of 8-data (up to 8-bit size) can be handled by two 32-bit fast data transfer based on single FIFO TXP/RXP/DXP occupancy event (no matter if data flow is handled by pooling, interrupt or DMA). The main sense here is to make data transfer very efficient and so decrease the load of the system (CPU and associated bus matrix) to minimum when control fast data flow especially.
Rgds,
Petr
2024-12-03 07:29 AM - edited 2024-12-03 07:30 AM
Hi,
Thanks for the reply.
Are you saying that:
SPI2->TXDR = 0;
Must be:
SPI2->TXDR = (uint16_t)0;
And that the DSIZE in the CFG1 register is irrelevant?
2024-12-09 05:43 AM
Hello,
good idea is to open stm32h5xx_hal_spi.c collecting the HAL SPI drivers and inspect the code there a bit. You can find lines like
*(__IO uint8_t *)&hspi->Instance->TXDR = (*hspi->pTxBuffPtr);
or
(*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->RXDR;
at HAL_SPI_TransmitReceive() procedure there.
The DSIZE setting is relevant of course. You cannot apply upper lines if the DSIZE is configured greater than 8 bits. Oppositely, data packing will be applied automatically if you use uint16_t or uint32_t casting of the TXDR/RXDR while the DSIZE fits into single byte at the FIFOs (means the DSIZE is configured up to 8 bit) as I've explained at my previous reply to you.
Rgds,
Petr
2024-12-09 06:32 AM
Hi,
Sorry I don't use Cube and I don't understand the snippets of code above at all.
I'll try rephrasing my question.
Let's make a simple example of wanting to send a single uint16_t out on the SPI2 peripheral and for the purposes of this, we're assuming we've already checked that the Tx register is empty. Is this what I need?
void send_value(uint16_t val_to_send)
{
SPI2->TXDR = (uint16_t)val_to_send;
}
Also, sorry to be slow, I'm not understanding what this means either:
"Oppositely, data packing will be applied automatically if you use uint16_t or uint32_t casting of the TXDR/RXDR while the DSIZE fits into single byte at the FIFOs (means the DSIZE is configured up to 8 bit) as I've explained at my previous reply to you."
This seems to be saying DSIZE is irrelevant. You seem to be saying if DSIZE is set to 8, but I cast the value sending out to be sixteen bits, I'll get sixteen clocks on SCLK?
Thanks!