cancel
Showing results for 
Search instead for 
Did you mean: 

Ddrawing line with partial frame strategy on STM32F0 based on STM32G0 eval board

PIRRI.1
Associate II

I'm using STM32f030cc MCU connected to an SD card and TFT Display 320x240 through SPI interface on a specific board. The SPi1 is used. it's the same configuration as the STM32G081 eval board and the partial frame buffer strategy is based on the STM32G0 software ( partialframebuffer_G0 project example)

The SPI DMA method is implemented on the sotware.

Touchgfx is used to draw on the TFT SPI display. Only 50 line can be drawn on the TFT.

if more are drawn, the software crashed and go into hardfault handler.

Does the touchgfx software contain a limitation to 50 lines ?

Can you explain to me why there is such limitation and how to do for drawing 240 lineson TFT display over touchgfx ?

Thanks for you quick answer

Best regards

Philippe IRRIEN

27 REPLIES 27

"This info page and example code is little chaos"

Which page are you referring to ? https://support.touchgfx.com/docs/development/ui-development/scenarios/lowering-memory-usage-with-partial-framebuffer/ this one ?

Could you elaborate a bit more what you don't understand ?

/Alexandre

Hi Alexandra , i write bold my question to example:

Transferring Frame Buffers on SPI Display

The STM32G081 evaluation kit has a SPI display. The principle for transferring the rectangles to the display is the same as for the DSI, but some details are different.

First, when a rectangle is drawn, we start a transfer if none is already in progress:

STM32G0HAL.cpp

void STM32G0HAL::flushFrameBuffer(const touchgfx::Rect& rect)

{

HAL::flushFrameBuffer(rect);

frameBufferAllocator->markBlockReadyForTransfer(); here marked

//start transfer if not running already!

if (!LCDManager_IsTransmittingData()) but here maybe not transfered , is this clean?

{

touchgfx::Rect r;

const uint8_t* pixels = frameBufferAllocator->getBlockForTransfer(r);

LCDManager_SendFrameBufferBlockWithPosition((uint8_t*)pixels, r.x, r.y, r.width, r.height);

}

}

The function LCDManager_SendFrameBufferBlockWithPosition starts a SPI transfer to the display using DMA.

The SPI transfer complete handler calls a function when the transfer is complete:

STM32G0HAL.cpp

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) SPI complete dont say what is complete

{

UNUSED(hspi); WTF unused

LCD_CS_HIGH();

isTransmittingData = 0;

//Change to SPI datasize to 8 bit from 16 bit

heval_Spi.Instance->CR2 &= ~(SPI_DATASIZE_16BIT - SPI_DATASIZE_8BIT);

//signal transfer complete

LCDManager_TransferComplete(); here marked as complete rect send but this maybe isnt true, you need send commands to display then data

}

The LCDManager_TransferComplete functions starts a new transfer:

STM32G0HAL.cpp

void LCDManager_TransferComplete() this function is called from where, when only up marked line then is good for big chaos

{

touchgfx::startNewTransfer();

}

void startNewTransfer()

{

FrameBufferAllocator* fba = HAL::getInstance()->getFrameBufferAllocator();

fba->freeBlockAfterTransfer();

blockIsTransferred = true;

if (fba->hasBlockReadyForTransfer())

{

touchgfx::Rect r; seems as unassigned but ok is assigned as reference in getBlockForTransfer

const uint8_t* pixels = fba->getBlockForTransfer(r);

LCDManager_SendFrameBufferBlockWithPosition((uint8_t*)pixels, r.x, r.y, r.width, r.height);

and this send i see as more important speed function for framebuffering to work, but no one word around this in example

}

}

_________________________________________________________________________________________________________________________________________

Maybe this is clear for you but i see little chaos without info how SPI display work.

For explain full framebuffer for 50Hz framerate need transfer all pixels in max time 1/50s .

No memory or stack heap trouble.

Partial framebuffer seems use ManyBlockAllocator, but too any heap. Why? Next chaos...

Hello,

The framerate of 50Hz can explain the fact that depending of ucHeap size only 50 frames has drawn on display?

Can this framerate be changed ?

@MM..1​ 

Sometimes the transfer can take longer than expected. In this case, we don't send the rendered block - see the condition if (!LCDManager_IsTransmittingData()). However, the block is still marked as ready to be transferred, therefore next time you are ready to transfer, the block will be sent to the display.

Let's imagine that your partial framebuffer is made of 3 blocks. This means that you can have a maximum of 3 blocks marked as ready to be transferred. After that, you will have to literally wait for the currently being transferred block to be completely sent.

If one block has been transferred successfully, void LCDManager_TransferComplete() is called which will start a new transfer. We don't want to wait for the next block to be rendered before sending a new block if one is pending in the queue. This why we also call LCDManager_SendFrameBufferBlockWithPosition() in here.

Note that void STM32G0HAL::flushFrameBuffer(const touchgfx::Rect& rect) is called very very often because it is called every time a block has been rendered and NOT everytime a frame has been rendered.

For UNUSED, I invite you to search on Google. This simply indicates that the parameter of the function is not used.

One other important notion is that an SPI display has an internal RAM embedded just like DSI, and just like DSI the display does not care about the MCU and just refresh itself every x milliseconds according to the datasheet. For some of these displays, the refresh rate can be modified through code. That means that if you don't update the screen fast enough you will see some Tearing Effect because the display will refresh itself even though the update is not complete. Therefore, you will have one part that is updated and one part that is from the old frame.

This is why partial framebuffer is mostly dedicated to low cost MCU with simple enough graphics do avoid unwanted artifacts on the display.

Hope it is clearer for you now.

/Alexandre

Alexandre RENOUX
Principal

@PIRRI.1​ 

This 50 lines drawing issue should not be related to TouchGFX. Nothing is meant to stop at line 50 in our implementation.

To debug, you could check your flushFrameBuffer() function and check the Rects that come in.

You should also check your driver, maybe it is not correctly configured.

/Alexandre

MM..1
Chief III

@PIRRI.1​ your code for upper post saeems different as code from info page. Why you dont use reference?

Dear Alexandre,

After a debug session, I've found the problem.

I tried to explain :

-> The blitCopyAlphaPerPixel(const uint16_t* sourceData,, ...) funvtion is called with the bitmap source address ( sourceData point to bitmap )

The bitmap has a size of 320 x 240 x 2 = 0x25800 bytes to drawn. The problem comes with the source data address.

In my case, the source address is 0x8028400. So the software comes into hardfault after drawing 152 lines because the sourceData pointer increase up to

0x8040000 which is an illegal address for my STM32F0 platform ( 256K of flash area )

To avoid this problem, I allocated the bitmap address to 0x8010000.

Now all the 240 lines are drawing.

Philippe

My source code is a part of the partialframbuffer_GO project.

This is why is different from the code on the touchgfx support.

I found the problem and solved it on my STM32F0 platform. Now , the software can draw 240 lines on the screen.