cancel
Showing results for 
Search instead for 
Did you mean: 

Partial framebuffer article and generated code missing details

AIlie.2
Associate II

I am trying to implement this using an ILI9341 display, like here helentronica.com/2021/01/22/touchgfx-on-a-custom-made-low-cost-board-with-the-ili9341-controller-over-spi/

The article at support.touchgfx.com/4.21/docs/development/scenarios/lowering-memory-usage-with-partial-framebuffer does not provide sufficient details for implementing this strategy using the latest generated code (STM32CubeIDE 1.11.00). A few issues:

  • startNewTransfer is shown in the article as being in TouchGFXHAL.cpp, but the code generator puts it in TouchGFXGeneratedHAL.cpp, which is supposed to not be edited, and it's not declared with __weak, so it cannot be overridden.
  • startNewTransfer has an additional line blockIsTransferred = true; which does not appear in the generated code, and blockIsTransferred is not declared anywhere. I saw some implementation elsewhere that had it connected to FrameBufferAllocatorWaitOnTransfer and FrameBufferAllocatorSignalBlockDrawn, but neither is mentioned in the article.

Is there an up-to date version of this article somewhere I'm missing? Or a complete functioning example?

Sorry for not linking, "new" members can't post links.

5 REPLIES 5
MM..1
Chief III

You maybe sleep, weak is exactly for override , and you place it in touchgfxhal.

All constants and help variables is based on your implement send rect. DMA is pref.

AIlie.2
Associate II

Appreciate the reply, but I can't really make sense of what you're saying.

My point is that yes, I can use the __weak prefix to override the default implementation, but that change is not recommended and will be overwritten by the code generator.

As for the article, it is incomplete because it uses a variable that is obviously defined and updated elsewhere, to implement a desired behavior that is, likewise, undocumented.

example from generated

__weak void FrameBufferAllocatorWaitOnTransfer()
{
  /* NOTE: This function should not be modified, when the fuction is needed,
   *       FrameBufferAllocatorWaitOnTransfer should be implemented in the user file
   */
}

you leave here as is

and in your any file place

void FrameBufferAllocatorWaitOnTransfer()
{
  ...
}

and write partial code is your job , not generator

ex.

volatile uint8_t IsTransmittingBlock_;
void UNIMM_dmacallback(void)
{
	IsTransmittingBlock_ = 0;
	DisplayDriver_TransferCompleteCallback();
}
 

 for details you open demo project in touchgfx for G071 board.

AIlie.2
Associate II

Thank you, appreciate the reply. The logic you're describing is the exact same as in the blog post I linked to. However, it does not correspond to the latest documentation, which includes the new variable blockIsTransferred. This new variable, as far as I can tell, is supposed to tell the frameBufferAllocator to wait for a transfer when there are no free blocks.

/**
 * Called by FrameBufferAllocator to wait for a LCD Transfer, when the allocator has no free
 * blocks. The LCD driver can use this function to synchronize the UI thread with the
 * transfer logic.
 */
void FrameBufferAllocatorWaitOnTransfer();
 
/**
 * Called by FrameBufferAllocator when a block is drawn and therefore ready for transfer. The
 * LCD driver should use this method to start a transfer.
 */
void FrameBufferAllocatorSignalBlockDrawn();

This blockIsTransferred variable appears in the documentation article, but is not explained, nor is it defined anywhere in the generated code.

All I'm trying to ascertain is which version is the right one (generated code or documentation) to get a proper implementation.

AIlie.2
Associate II

I got a working solution: make the declaration of startNewTransfer in TouchGFXGeneratedHAL to __weak, and override it in TouchGFXHAL with the implementation shown in the documentation. The whole thing looks like this:

static volatile bool blockIsTransferred = false;
 
namespace touchgfx
{
void FrameBufferAllocatorWaitOnTransfer()
{
  while(!blockIsTransferred);
}
 
void FrameBufferAllocatorSignalBlockDrawn()
{
    blockIsTransferred = false;
}
 
 
// A user must call touchgfx::startNewTransfer(); once transmitFrameBufferBlock() has successfully sent a block.
void startNewTransfer()
{
    FrameBufferAllocator* fba = HAL::getInstance()->getFrameBufferAllocator();
    // Free the previous transmitted block, marking it ready for rendering
      fba->freeBlockAfterTransfer();
    blockIsTransferred = true;
 
    if (fba->hasBlockReadyForTransfer())
    {
        touchgfx::Rect r;
        // Get pointer to block buffer and coordinates of the rect
        const uint8_t* pixels = fba->getBlockForTransfer(r);
        // Start transmission of the block
        touchgfxDisplayDriverTransmitBlock((uint8_t*)pixels, r.x, r.y, r.width, r.height);
    }
}
}
 
extern "C"
void DisplayDriver_TransferCompleteCallback()
{
  // After completed transmission start new transfer if blocks are ready.
	blockIsTransferred = false;
    touchgfx::startNewTransfer();
}

The documentation and generated code should be updated accordingly.