From 1b889179ed614cdaf8513151467d107298164450 Mon Sep 17 00:00:00 2001 From: Pat Rogers Date: Sat, 21 Mar 2026 17:29:44 -0500 Subject: [PATCH] Fix display coherency problem when D-cache is enabled Fixes the case in which the LTDC displayed content would occasionally slew to the left and then snap back immediately. Affects: stm32-dma2d_bitmap, framebuffer_ltdc DMA2D_Fill_Rect was called without Synchronous => True, allowing DMA2D writes to the hidden framebuffer to still be in progress when Internal_Update_Layer flushed and handed the buffer to LTDC. This caused occasional display corruption ("slewing") as LTDC scanned out a partially-written buffer. Fix Fill_Rect to use Synchronous => True, consistent with Fill. Add Clean_DCache in Internal_Update_Layer covering the hidden buffer before Set_Frame_Buffer, ensuring CPU-written dirty cache lines are flushed to physical memory before LTDC DMA reads them. --- boards/stm32_common/dma2d/stm32-dma2d_bitmap.adb | 8 +++++--- boards/stm32_common/ltdc/framebuffer_ltdc.adb | 9 ++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/boards/stm32_common/dma2d/stm32-dma2d_bitmap.adb b/boards/stm32_common/dma2d/stm32-dma2d_bitmap.adb index aa7b44ee7..d650d803f 100644 --- a/boards/stm32_common/dma2d/stm32-dma2d_bitmap.adb +++ b/boards/stm32_common/dma2d/stm32-dma2d_bitmap.adb @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- -- --- Copyright (C) 2015-2016, AdaCore -- +-- Copyright (C) 2015-2026, AdaCore -- -- -- -- Redistribution and use in source and binary forms, with or without -- -- modification, are permitted provided that the following conditions are -- @@ -153,7 +153,8 @@ package body STM32.DMA2D_Bitmap is X => Area.Position.X, Y => Area.Position.Y, Width => Area.Width, - Height => Area.Height); + Height => Area.Height, + Synchronous => True); else DMA2D_Fill_Rect (DMA_Buf, @@ -161,7 +162,8 @@ package body STM32.DMA2D_Bitmap is X => Area.Position.Y, Y => Buffer.Width - Area.Position.X - Area.Width, Width => Area.Height, - Height => Area.Width); + Height => Area.Width, + Synchronous => True); end if; else Parent (Buffer).Fill_Rect (Area); diff --git a/boards/stm32_common/ltdc/framebuffer_ltdc.adb b/boards/stm32_common/ltdc/framebuffer_ltdc.adb index b27d5540a..c49af8282 100644 --- a/boards/stm32_common/ltdc/framebuffer_ltdc.adb +++ b/boards/stm32_common/ltdc/framebuffer_ltdc.adb @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- -- --- Copyright (C) 2015-2016, AdaCore -- +-- Copyright (C) 2015-2026, AdaCore -- -- -- -- Redistribution and use in source and binary forms, with or without -- -- modification, are permitted provided that the following conditions are -- @@ -32,6 +32,7 @@ with STM32.DMA2D.Interrupt; with STM32.DMA2D.Polling; with STM32.SDRAM; use STM32.SDRAM; +with Cortex_M.Cache; package body Framebuffer_LTDC is @@ -377,12 +378,18 @@ package body Framebuffer_LTDC is null; when 1 => Display.Buffers (LCD_Layer, 2).Wait_Transfer; + Cortex_M.Cache.Clean_DCache + (Display.Buffers (LCD_Layer, 2).Addr, + Display.Buffers (LCD_Layer, 2).Buffer_Size); STM32.LTDC.Set_Frame_Buffer (Layer => LCD_Layer, Addr => Display.Buffers (LCD_Layer, 2).Addr); Display.Current (LCD_Layer) := 2; when 2 => Display.Buffers (LCD_Layer, 1).Wait_Transfer; + Cortex_M.Cache.Clean_DCache + (Display.Buffers (LCD_Layer, 1).Addr, + Display.Buffers (LCD_Layer, 1).Buffer_Size); STM32.LTDC.Set_Frame_Buffer (Layer => LCD_Layer, Addr => Display.Buffers (LCD_Layer, 1).Addr);