cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f401rct uses partial framebuffer to display skewed when refreshing the control,

victor.wu
Associate II

0693W00000Lz91nQAB.gifUsing threadx rtos, spi is written to st7796 rbg565 480*320, the interface display is normal during initialization, but it is abnormal when the widget is refreshed in handletickevent

1 ACCEPTED SOLUTION

Accepted Solutions
MM..1
Chief II

I complete dont understand your code, read docu for partial mode...

For example part of my driver c file. (Note: Generated files isnt for edit then show it here is waste space

volatile uint8_t IsTransmittingBlock_;
void UNIMM_dmacallback(void)
{
	IsTransmittingBlock_ = 0;
	DisplayDriver_TransferCompleteCallback();
}
void Display_Bitmap(const uint16_t *bitmap, uint16_t posx, uint16_t posy, uint16_t sizex, uint16_t sizey)
{
  IsTransmittingBlock_ = 1;
  GC9A01A_SetWindow(posx, posy, posx+sizex-1, posy+sizey-1);
//DMA test
  HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);
  SPI_send_dma(GC9A01A_SPI_periph, 1, (uint8_t *)bitmap, sizex*sizey, UNIMM_dmacallback);
}

View solution in original post

6 REPLIES 6
victor.wu
Associate II

Does anyone know the reason, thank you very much for your help

MM..1
Chief II

Maybe better is show your code for init display and refresh system.

victor.wu
Associate II

A workaround method is adopted here. A global variable is judged in the timer interrupt. If the writing spi tft thread has completed the transmission, it will be executed.

if(writing == 2)

 {

  writing = 0;

  IsTransmittingBlock_ = 0;

  DisplayDriver_TransferCompleteCallback();

 }

void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h)

{

 if(writing == 2 || writing == 0)

 {

  wr_x = x ;

  wr_y = y;

  wr_w = w;

  wr_h = h;

  pix = pixels;

  writing = 1;

   

  IsTransmittingBlock_ = 1;

  //DisplayDriver_TransferCompleteCallback();

   

 }

// IsTransmittingBlock_ = st7796_draw_rect(x , y , x + w , y + h , (void*)pixels);

// if(IsTransmittingBlock_ == 0)

// {

//  DisplayDriver_TransferCompleteCallback();

// }

}

void app_user_task(unsigned long para)

{

 volatile uint32_t base ,tick ,acculate;

 uint32_t lcd_frame_tick;

  

 for(;;)

 { 

  tx_thread_sleep(1);

  if(++acculate >= 100)

  {

   acculate = 0;

   tick = HAL_GetTick() - base;

   base = HAL_GetTick();

  }

   

  if((HAL_GetTick() - lcd_frame_tick ) >= 1000)

  {

   lcd_frame_tick = HAL_GetTick();    

  }

   

  if(writing == 1 )

  {

    

   st7796_draw_rect(wr_x , wr_y , wr_x + wr_w , wr_y + wr_h , (void*)pix);

   writing = 2;

   uint16_t buf[256];

   for(int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)

   {

    buf[i] = (i >> 2) << 5;

   }

   st7796_draw_rect(100 , 250 , 100+127 , 252 , (void*)buf);

  }

   

 }

}

extern "C"

void DisplayDriver_TransferCompleteCallback()

{

 // After completed transmission start new transfer if blocks are ready.

  touchgfx::startNewTransfer();

}

}

extern "C"

void touchgfxSignalVSync(void)

{

  /* VSync has occurred, increment TouchGFX engine vsync counter */

  touchgfx::HAL::getInstance()->vSync();

  /* VSync has occurred, signal TouchGFX engine */

  touchgfx::OSWrappers::signalVSync();

}

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

{

  HAL::flushFrameBuffer(rect);

  // 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().

 //PartialFrameBufferManager::tryTransmitBlock();

  

  frameBufferAllocator->markBlockReadyForTransfer();

  if (!touchgfxDisplayDriverTransmitActive())

  {

    touchgfx::Rect r;

    // Get pointer to block buffer and coordinates of the rect

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

    // Start transmission of the block

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

  }

}

extern "C" int touchgfxDisplayDriverTransmitActive();

extern "C" void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h);

extern "C" void touchgfxSignalVSync(void);

// Block Allocator for Partial Framebuffer strategy

static ManyBlockAllocator<11520, /* block size */

          3, /* number of blocks */

          2 /* bytes per pixel */

          > blockAllocator;

void TouchGFXGeneratedHAL::initialize()

{

  HAL::initialize();

  registerEventListener(*(Application::getInstance()));

  // Partial framebuffer strategy

  setFrameBufferAllocator(&blockAllocator);

  setFrameRefreshStrategy(HAL::REFRESH_STRATEGY_PARTIAL_FRAMEBUFFER);

}

/*

 * Initialize frame buffer semaphore and queue/mutex for VSYNC signal.

 */

void OSWrappers::initialize()

{

  CHAR* pointer;

  /* Create a byte memory pool from which to allocate the thread stacks. */

  if (tx_byte_pool_create(&oswrapper_byte_pool, (CHAR*) "OSWrapper Byte Pool", oswrapper_heap_mem,

              OSWRAPPER_BYTE_POOL_SIZE) != TX_SUCCESS)

  {

    assert(0 && "Failed to create OSWrapper Pool memory!");

  }

  /* Allocate the vsync_q. */

  if (tx_byte_allocate(&oswrapper_byte_pool, (VOID**) &pointer,

             OSWRAPPER_QUEUE_SIZE, TX_NO_WAIT) != TX_SUCCESS)

  {

    assert(0 && "Failed to allocate memory for the Vsync Message Queue!");

  }

  // Create a queue of length 1

  if (tx_queue_create(&vsync_q, (CHAR*) "Vsync Message Queue", TX_1_ULONG,

            pointer, OSWRAPPER_QUEUE_SIZE) != TX_SUCCESS)

  {

    assert(0 && "Failed to create Vsync Message Queue!");

  }

  // Create the Framebuffer Semaphore (Binary)

  if (tx_semaphore_create(&frame_buffer_sem, (CHAR*) "FrameBuffer Semaphore", 0) != TX_SUCCESS)

  {

    assert(0 && "Failed to create FrameBuffer Semaphore!");

  }

   

  //giveFrameBufferSemaphore();

}

if(writing == 2)

 {

  writing = 0;

  IsTransmittingBlock_ = 0;

  DisplayDriver_TransferCompleteCallback();

 }

victor.wu
Associate II

From the phenomenon, it seems that the touchgfx kernel has data misalignment when rendering part of the buffer, and it has been repeatedly confirmed that the spi program written to the st7796 is correct.

MM..1
Chief II

I complete dont understand your code, read docu for partial mode...

For example part of my driver c file. (Note: Generated files isnt for edit then show it here is waste space

volatile uint8_t IsTransmittingBlock_;
void UNIMM_dmacallback(void)
{
	IsTransmittingBlock_ = 0;
	DisplayDriver_TransferCompleteCallback();
}
void Display_Bitmap(const uint16_t *bitmap, uint16_t posx, uint16_t posy, uint16_t sizex, uint16_t sizey)
{
  IsTransmittingBlock_ = 1;
  GC9A01A_SetWindow(posx, posy, posx+sizex-1, posy+sizey-1);
//DMA test
  HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);
  SPI_send_dma(GC9A01A_SPI_periph, 1, (uint8_t *)bitmap, sizex*sizey, UNIMM_dmacallback);
}

victor.wu
Associate II

Confirm that the problem lies in the setwindows function, st7796_draw_rect(wr_x , wr_y , wr_x + wr_w -1 , wr_y + wr_h -1, (void*)pix); need to set x2, y2 minus 1, so the window is dislocated, thank you very much You, the partial buffers are really nice to use, and can take advantage of graphics on a low-cost chip.