2022-01-27 05:03 AM
Dear all,
Can someone help me on that topic ?
Goal :
I need to send a large amount of 8 bit via SPI as fast as possible (SPI display).
The frame buffer is around 160 000b so size need to be uint32_t.
Strategy :
Use SPI register to avoid 16bit size HAL limitation.
Use HAL_SPI_TRANSFERT as reference in terms of performance, register manipulation should give us a speed rate >= HAL.
Start with small framebuffer ie : uint8_t image[1000]
Environment:
I am working with a nucloSTM32U5 on SPI2 with no slave attached, but CLK and MOSI monitored.
See attached configuration
The code:
void xSPI_Send_Data( SPI_TypeDef *spi, uint8_t *pdata, uint32_t size)
{
// Disable SPI2
CLEAR_BIT(spi->CR1, SPI_CR1_SPE);
// Set TSIZE to 0 (defaut value) for unknown size transfert
MODIFY_REG(spi->CR2, SPI_CR2_TSIZE, 0);
// Enable SPI2
if ((spi->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) {
// If disabled, I enable it
SET_BIT(spi->CR1, SPI_CR1_SPE);
}
// Master transfert start
SET_BIT(spi->CR1, SPI_CR1_CSTART);
// Transfert in 8 bit Mode
while (size > 0)
{
if(SPI_IsActiveFlag_TXP)
{
*(volatile uint8_t *)&spi->TXDR = *pdata;
pdata += sizeof(uint8_t);
size--;
//HAL_Delay(10);
}
}
// Disable SPI2
CLEAR_BIT(spi->CR1, SPI_CR1_SPE);
}
uint8_t SPI_IsActiveFlag_TXP(SPI_TypeDef *SPIx)
{
return ((READ_BIT(SPIx->SR, SPI_SR_TXP) == (SPI_SR_TXP)) ? 1 : 0);
}
Results :
Can't manage to get all the datas (see attached) and in terms of speed rate i am about 10-15%% faster then HAL library but with data corruption.
Next ? :
I tried to add some tests on the register code, datas are fine but the speed rate is divided by 2.
Can someone point me out what I am missing here ?
Thanks
2022-01-27 05:24 AM
Dont waste time with this hard chaos. Use Transmit_DMA.
spi_init(word16bit);
HAL_SPI_Transmit_DMA(&hspi, pBuff, Len);
2022-01-27 05:36 AM
Thank for your answer, but I really want to understand what is missing.
If someone used SPI U5 registers can share there.
2022-01-27 08:13 AM
I mean you have more fails first
if(SPI_IsActiveFlag_TXP)
second
uint8_t SPI_IsActiveFlag_TXP(SPI_TypeDef *SPIx)
{
return ((READ_BIT(SPIx->SR, SPI_SR_TXP) == (SPI_SR_TXP)) ? 1 : 0);
}
check if this code works and dont need !
2022-01-27 09:20 AM
Why do you think there's a 16-bit limitation in HAL? Word size for SPI can be 32-bits.
Code would be faster by writing 32-bits at once instead of 8 (or using DMA in the first place).
> if(SPI_IsActiveFlag_TXP)
This is nonsense, you're not calling the function. If you want to check the flag:
if (spi->SR & SPI_SR_TXP)
2022-01-27 12:28 PM
Thanks for pointing out my mistake.
I copy the code if someone needs it
void xSPI_Send_Data( SPI_TypeDef *spi, uint8_t *pdata, uint32_t size)
{
// Disable SPI2
CLEAR_BIT(spi->CR1, SPI_CR1_SPE);
// Set TSIZE to 0 (defaut value) for unknown size transfert
MODIFY_REG(spi->CR2, SPI_CR2_TSIZE, 0);
// Enable SPI2
if ((spi->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) {
// If disabled, I enable it
SET_BIT(spi->CR1, SPI_CR1_SPE);
}
// Master transfert start
SET_BIT(spi->CR1, SPI_CR1_CSTART);
// Transfert in 8 bit Mode
while (size > 0)
{
if (SPI_IsActiveFlag_TXP (spi))
{
*(volatile uint8_t *)&spi->TXDR = *pdata;
pdata += sizeof(uint8_t);
size--;
}
}
// Wait last TxFIFO transmission complete
while (!(SPI_IsActiveFlag_TXC (spi)))
{
}
// Disable SPI2
CLEAR_BIT(spi->CR1, SPI_CR1_SPE);
}
uint8_t SPI_IsActiveFlag_TXP(SPI_TypeDef *SPIx)
{
return ((READ_BIT(SPIx->SR, SPI_SR_TXP) == (SPI_SR_TXP)) ? 1 : 0);
}
uint8_t
SPI_IsActiveFlag_TXC (SPI_TypeDef *SPIx)
{
return ((READ_BIT(SPIx->SR, SPI_SR_TXC) == (SPI_SR_TXC)) ? 1 : 0);
}
I forgot also to wait TXC flag, before disable SPI.
Now it is working fine.
2022-01-27 12:38 PM
Thank again TDK,
Just a reply here concerning what I meant with the 16 bit HAL limitation:
I was not clear, HAL for U5 use TSIZE register and this register is 16bit, so TxXferCount max value is 65535.
You are right, 32bit can be used instead of 8bit, so you can trick it and send 4 times more bits, but still you are limited to 4 * 65535 bits.
If bigger data need, HAL_SPI can be call again ;)
2022-01-27 01:11 PM
Ah okay, it does appear to take the length as a 16-bit parameter even though it doesn't need to.
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
DMA has a similar 65535 transaction limit on other families. Haven't played with the U5 at all, probably still there.