2021-03-09 06:31 AM
Hi All,
Using an STM32F446RE with TouchGFX 4.16 and MX25L6433F external SPI flash.
When generating the TouchGFX project, the generated TouchGFXGeneratedDataReader.cpp contains a few errors which prevents the data from flash being used.
Here is the generated file:
/**
******************************************************************************
* File Name : TouchGFXGeneratedDataReader.cpp
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include <TouchGFXGeneratedDataReader.hpp>
#include <stm32f4xx.h>
/*
* External Interface description for starting transmissions
*/
extern "C" void DataReader_WaitForReceiveDone();
extern "C" void DataReader_ReadData(uint32_t address24, uint8_t* buffer, uint32_t length);
extern "C" void DataReader_StartDMAReadData(uint32_t address24, uint8_t* buffer, uint32_t length);
/*
* flashEndAddress is calculated using the FLASH_BASE address provided in stm32f4xx.h
* and by reading the flash size of the MCU located at address FLASHSIZE_BASE.
* FLASHSIZE_BASE is in kBytes and is shifted left to translate into an address space.
*/
TouchGFXGeneratedDataReader::TouchGFXGeneratedDataReader() :
flashEndAddress(FLASH_BASE + ((*(uint16_t*)FLASHSIZE_BASE) << 10)) {}
bool TouchGFXGeneratedDataReader::addressIsAddressable(const void* address)
{
/* Check if adrress is in internal flash */
if (address >= (void*)FLASH_BASE && address <(void*)(flashEndAddress))
{
return true;
}
/* Check if adrress is in internal RAM */
if (address >= (void*)SRAM_BASE && address <(void*)(SRAM_BASE + SRAM_SIZE_MAX))
{
return true;
}
// Address is neither internal RAM or internal flash
return false;
}
void TouchGFXGeneratedDataReader::copyData(const void* src, void* dst, uint32_t bytes)
{
/* If requested number of bytes are less than 250
* CPU and polling will be used to read from flash.
* If number of bytes requested is larger than 250
* a DMA transfer will be started.
*/
if (bytes < 250)
{
/* Start transfer using the CPU */
DataReader_ReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
}
else
{
/* Start transfer using DMA */
DataReader_StartDMAReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
/* Wait on data transmision complete */
DataReader_WaitForReceiveDone();
}
}
void TouchGFXGeneratedDataReader::startFlashLineRead(const void* src, uint32_t bytes)
{
/* Start transfer using DMA */
DataReader_StartDMAReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
}
const uint8_t* TouchGFXGeneratedDataReader::waitFlashReadComplete()
{
/*
* Switch line buffer and then wait for transmission to complete before returning new buffer.
*/
uint8_t* readBuffer = readToBuffer1 ? buffer1 : buffer2;
DataReader_WaitForReceiveDone();
readToBuffer1 = !readToBuffer1;
return readBuffer;
}
First the STM32F4 Hals don't seem to define "SRAM_SIZE_MAX" so I have to add
#define SRAM_SIZE_MAX 0x00020000
Then while it compiles, the data from the flash is not used on the display. I have to add
memcpy(dst, (readToBuffer1 ? buffer1 : buffer2), bytes);
to line 72 of copyData function.
While these workarounds seem to work, are they the best way to approach the problem? Or is there a better solution to this that I have missed
Any help will be much appreciated
Cheers,
Ed
2021-06-21 01:26 PM
It looks like this is exactly a TouchGFX generator bug. I also spent 2 days solving this problem, because sometimes the obvious is not easy to see :)
I did not use slow memcpy, but simply pointed out:
DataReader_StartDMAReadData((uint32_t)src, (uint8_t*)dst, bytes);
A more elegant solution - override the copyData() in TouchGFXDataReader.cpp.
2021-07-09 02:43 AM
Same problem !
My hardware: NUCLEO-F446RE + X-NUCLEO-GFX01M1.
My software: STM32CubeIDE Version: 1.6.1, STM32Cube_FW_F4_V1.26.1, X-CUBE-TOUCHGFX 4.17.0
My workaround is based on the TouchGFXGeneratedDataReader.cpp file generated by STM32CumeMX for the STM32G071.
#define SRAM_SIZE_MAX (0x00020000UL) /*!< maximum SRAM size (up to 128 KBytes) */
.....
void TouchGFXGeneratedDataReader::copyData(const void* src, void* dst, uint32_t bytes)
{
/* Redirect copy data through driver interface */
DataReader_StartDMAReadData((uint32_t)src, (uint8_t*)dst, bytes);
/* Wait on data transmision complete */
DataReader_WaitForReceiveDone();
}
void TouchGFXGeneratedDataReader::startFlashLineRead(const void* src, uint32_t bytes)
{
/* If requested number of bytes are less than 40
* CPU and polling will be used to read from flash.
* If number of bytes requested is larger than 40
* a DMA transfer will be started.
*/
if (bytes < 40)
{
/* Start transfer using the CPU */
DataReader_ReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
}
else
{
/* Start transfer using DMA */
DataReader_StartDMAReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
}
}
In this case, however, the Minimum DMA tranfer size parameter (setted to 40 in the CubeMX) is checked in the startFlashLineRead instead of in the copyData.
Before the bug is fixed in the STM32CubeIDE I think someone from ST support, like @Martin KJELDSEN or @Alexandre RENOUX, should point out what is the correct solution.
/Antonello
2021-07-09 02:58 AM
Please try 4.17.0 - Fixed a bug related to this.
2021-07-09 05:02 AM
Yes, apart from define SRAM_SIZE_MAX 4.17.0 fix this bug
/Antonello
2021-07-12 12:48 AM
That's great. I could look into SRAM_SIZE_MAX with the firmware team.