Skip to main content
PIRRI.1
Associate II
September 7, 2020
Question

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

  • September 7, 2020
  • 27 replies
  • 5987 views

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

This topic has been closed for replies.

27 replies

MM..1
Super User
September 15, 2020

Have you any canvas graphics on screen, when yes have you canvas buffer defined, too how you implement flushrect function?

PIRRI.1
PIRRI.1Author
Associate II
September 16, 2020

What did you means with flushrect function ?

It is flushframebuffer function ?

Normaly, no canvas graphics are present on screen.

MM..1
Super User
September 17, 2020

Partial buffer strategy sends rectangles , then i name it , but yes i mean flushframebuffer , but as is explained in last spi part

here is named func ...

if (fba->hasBlockReadyForTransfer())

{

touchgfx::Rect r;

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

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

}

Read https://support.touchgfx.com/docs/development/ui-development/scenarios/lowering-memory-usage-with-partial-framebuffer/

PIRRI.1
PIRRI.1Author
Associate II
September 20, 2020

This buffer strategy is implemented in the software.

This is made like this ( is part of 'Lowering Memory Usage with Partial Framebuffer' of touchgfx support ) :

void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect) {

 HAL::lockFrameBuffer(); //SYNC WITH FRAMEWORK. Get pointer to current framebuffer.

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

 HAL::flushFrameBuffer(rect);

 //Try to take a display semaphore - Always free at this point

 //touchgfx::OSWrappers::takeFrameBufferSemaphore(); // always inside HAL::lockFrameBuffer()

 // Once flushFrameBuffer() is called by the framework a block is already for transfer

 // Mark it ready for transfer and transmit it if user defined method isTransmittingData() does not return false

 // If data is not being transmitted, transfer the data with user defined method transmitFrameBufferBlock().

 fba->markBlockReadyForTransfer();

 if ( !TFT_ManagerIsTransmittingData() ) {

   touchgfx::Rect r;

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

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

 }

 //Unlock TouchGFX framebuffer and give semaphore back - Flushframebuffer() is now a part of RENDER_TIME.

 HAL::unlockFrameBuffer();

 touchgfx::OSWrappers::giveFrameBufferSemaphore();

}

I don't understand why only 150 lines can be drawing on screeen ?

The ucHeap size cannot be increase as big than 32K in RAM ( only 32K of RAM in STM32F0 ).

I also had another request :

1 ) Does relationship exists between caching bitmap and Frame buffer Allocator ?

2 ) If Bitmap are cahing, normally these bitmap must be copied to frame allocator ? in my case is not the case. Why ?

Thanks for you reply

Philippe

Alexandre RENOUX
Visitor II
September 21, 2020

There's no relationship between caching bitmap and framebuffer allocator except that both are related to RAM.

Framebuffer Allocator is dedicated to the framebuffer (as the name states) and more specifically corresponds to the partial framebuffer in itself (how many blocks ? What size per block?)

To cache bitmaps you need to allocate a different piece of RAM.

I reckon that having only a small internal RAM and trying to cache bitmaps as well as having a partial framebuffer could be too much.

/Alexandre

MM..1
Super User
September 20, 2020

I agree this info page and example code is little chaos. Why is marked block for transfer and then if manager transfer can be skipped.

Why is in if local touchgfx::Rect r; that isnt assigned ... CHAOS.

I mean this example need some modification to work properly. As first you need high speed

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

When this function isnt quick, your stack is overloaded with waited rect object to transmit...

Maybe anybody ST help you.

Alexandre RENOUX
Visitor II
September 21, 2020

"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

MM..1
Super User
September 21, 2020

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...

Alexandre RENOUX
Visitor II
September 23, 2020

@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

PIRRI.1
PIRRI.1Author
Associate II
September 23, 2020

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

MM..1
Super User
September 23, 2020

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

PIRRI.1
PIRRI.1Author
Associate II
September 23, 2020

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.