1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 12:28:09 +00:00

refactor(core): extract framebuffer copy to separate bg_copy functionality

[no changelog]
This commit is contained in:
tychovrahe 2024-01-09 23:06:54 +01:00 committed by TychoVrahe
parent afefc17478
commit f08bed363d
4 changed files with 134 additions and 98 deletions

View File

@ -0,0 +1,25 @@
#ifndef TREZORHAL_BG_COPY_H
#define TREZORHAL_BG_COPY_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/**
* Wait for the data transfer completion
*/
void bg_copy_wait(void);
/**
* Performs data copy from src to dst in the background. The destination is
* constant, meaning the address is not incremented. Ensure the transfer
* completion by calling bg_copy_wait
*
* @param src source data address
* @param dst destination data address
* @param size size of data to be transferred in bytes
*/
void bg_copy_start_const_out_8(const uint8_t *src, uint8_t *dst, size_t size);
#endif

View File

@ -65,6 +65,8 @@ __IO DISP_MEM_TYPE *const DISPLAY_DATA_ADDRESS =
#error Framebuffer only supported on STM32U5 for now #error Framebuffer only supported on STM32U5 for now
#endif #endif
#include "bg_copy.h"
#define DATA_TRANSFER(X) \ #define DATA_TRANSFER(X) \
DATA((X)&0xFF); \ DATA((X)&0xFF); \
DATA((X) >> 8) DATA((X) >> 8)
@ -84,12 +86,6 @@ static uint16_t window_y1 = 0;
static uint16_t cursor_x = 0; static uint16_t cursor_x = 0;
static uint16_t cursor_y = 0; static uint16_t cursor_y = 0;
static volatile uint32_t dma_transfer_remaining = 0;
static volatile uint32_t dma_data_transferred = 0;
static DMA_HandleTypeDef DMA_Handle = {0};
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma);
#else #else
#define DATA_TRANSFER(X) PIXELDATA(X) #define DATA_TRANSFER(X) PIXELDATA(X)
#endif #endif
@ -254,9 +250,7 @@ int display_backlight(int val) {
// wait for DMA transfer to finish before changing backlight // wait for DMA transfer to finish before changing backlight
// so that we know that panel has current data // so that we know that panel has current data
if (backlight_pwm_get() != val && !is_mode_handler()) { if (backlight_pwm_get() != val && !is_mode_handler()) {
while (dma_transfer_remaining > 0) { bg_copy_wait();
__WFI();
}
} }
#endif #endif
@ -340,37 +334,6 @@ void display_setup_fmc(void) {
} }
#ifdef FRAMEBUFFER #ifdef FRAMEBUFFER
void display_setup_dma(void) {
// setup DMA for transferring framebuffer to display
__HAL_RCC_GPDMA1_CLK_ENABLE();
/* USER CODE END GPDMA1_Init 1 */
DMA_Handle.Instance = GPDMA1_Channel0;
DMA_Handle.XferCpltCallback = HAL_DMA_XferCpltCallback;
DMA_Handle.Init.Request = GPDMA1_REQUEST_HASH_IN;
DMA_Handle.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
DMA_Handle.Init.Direction = DMA_MEMORY_TO_MEMORY;
DMA_Handle.Init.SrcInc = DMA_SINC_INCREMENTED;
DMA_Handle.Init.DestInc = DMA_DINC_FIXED;
DMA_Handle.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
DMA_Handle.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
DMA_Handle.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
DMA_Handle.Init.SrcBurstLength = 1;
DMA_Handle.Init.DestBurstLength = 1;
DMA_Handle.Init.TransferAllocatedPort =
DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT0;
DMA_Handle.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
DMA_Handle.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&DMA_Handle);
HAL_DMA_ConfigChannelAttributes(&DMA_Handle, DMA_CHANNEL_SEC |
DMA_CHANNEL_SRC_SEC |
DMA_CHANNEL_DEST_SEC);
HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, IRQ_PRI_DMA, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
}
void display_setup_te_interrupt(void) { void display_setup_te_interrupt(void) {
#ifdef DISPLAY_TE_PIN #ifdef DISPLAY_TE_PIN
EXTI_HandleTypeDef EXTI_Handle = {0}; EXTI_HandleTypeDef EXTI_Handle = {0};
@ -454,7 +417,6 @@ void display_init(void) {
panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
#ifdef FRAMEBUFFER #ifdef FRAMEBUFFER
display_setup_dma();
display_setup_te_interrupt(); display_setup_te_interrupt();
#endif #endif
} }
@ -483,7 +445,6 @@ void display_reinit(void) {
#endif #endif
#ifdef FRAMEBUFFER #ifdef FRAMEBUFFER
display_setup_dma();
display_setup_te_interrupt(); display_setup_te_interrupt();
#endif #endif
} }
@ -554,66 +515,25 @@ void display_pixeldata(uint16_t c) {
void display_sync(void) {} void display_sync(void) {}
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma) {
if (dma_transfer_remaining > 0xFFFF) {
dma_transfer_remaining -= 0xFFFF;
dma_data_transferred += 0xFFFF;
} else {
dma_data_transferred += dma_transfer_remaining;
dma_transfer_remaining = 0;
}
if (dma_transfer_remaining > 0) {
uint32_t data_to_send =
dma_transfer_remaining > 0xFFFF ? 0xFFFF : dma_transfer_remaining;
if (act_frame_buffer == 0) {
HAL_DMA_Start_IT(
hdma,
(uint32_t) & ((uint8_t *)PhysFrameBuffer0)[dma_data_transferred],
(uint32_t)DISPLAY_DATA_ADDRESS, data_to_send);
} else {
HAL_DMA_Start_IT(
hdma,
(uint32_t) & ((uint8_t *)PhysFrameBuffer1)[dma_data_transferred],
(uint32_t)DISPLAY_DATA_ADDRESS, data_to_send);
}
}
}
void DISPLAY_TE_INTERRUPT_HANDLER(void) { void DISPLAY_TE_INTERRUPT_HANDLER(void) {
HAL_NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); HAL_NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM);
uint32_t data_to_send = DISPLAY_RESX * DISPLAY_RESY * 2 > 0xFFFF
? 0xFFFF
: DISPLAY_RESX * DISPLAY_RESY * 2;
if (act_frame_buffer == 1) { if (act_frame_buffer == 1) {
HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)PhysFrameBuffer1, bg_copy_start_const_out_8((uint8_t *)PhysFrameBuffer1,
(uint32_t)DISPLAY_DATA_ADDRESS, data_to_send); (uint8_t *)DISPLAY_DATA_ADDRESS,
DISPLAY_RESX * DISPLAY_RESY * 2);
} else { } else {
HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)PhysFrameBuffer0, bg_copy_start_const_out_8((uint8_t *)PhysFrameBuffer0,
(uint32_t)DISPLAY_DATA_ADDRESS, data_to_send); (uint8_t *)DISPLAY_DATA_ADDRESS,
DISPLAY_RESX * DISPLAY_RESY * 2);
} }
__HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN); __HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN);
} }
void GPDMA1_Channel0_IRQHandler(void) {
if ((DMA_Handle.Instance->CSR & DMA_CSR_TCF) == 0) {
// error, abort the transfer and allow the next one to start
dma_data_transferred = 0;
dma_transfer_remaining = 0;
}
HAL_DMA_IRQHandler(&DMA_Handle);
}
void display_refresh(void) { void display_refresh(void) {
while (dma_transfer_remaining > 0) { bg_copy_wait();
__WFI();
}
if (is_mode_handler()) { if (is_mode_handler()) {
// sync with the panel refresh // sync with the panel refresh
@ -640,9 +560,6 @@ void display_refresh(void) {
memcpy(PhysFrameBuffer1, PhysFrameBuffer0, sizeof(PhysFrameBuffer1)); memcpy(PhysFrameBuffer1, PhysFrameBuffer0, sizeof(PhysFrameBuffer1));
} }
} else { } else {
dma_transfer_remaining = DISPLAY_RESX * DISPLAY_RESY * 2;
dma_data_transferred = 0;
if (act_frame_buffer == 0) { if (act_frame_buffer == 0) {
act_frame_buffer = 1; act_frame_buffer = 1;
@ -729,11 +646,7 @@ void display_efficient_clear(void) {
memzero(PhysFrameBuffer0, sizeof(PhysFrameBuffer0)); memzero(PhysFrameBuffer0, sizeof(PhysFrameBuffer0));
} }
void display_finish_actions(void) { void display_finish_actions(void) { bg_copy_wait(); }
while (dma_transfer_remaining > 0) {
__WFI();
}
}
#else #else
// NOT FRAMEBUFFER // NOT FRAMEBUFFER

View File

@ -0,0 +1,97 @@
#include "bg_copy.h"
#include "irq.h"
#include STM32_HAL_H
#define MAX_DATA_SIZE 0xFFF0
static volatile uint32_t dma_transfer_remaining = 0;
static volatile uint32_t dma_data_transferred = 0;
static void *data_src = NULL;
static void *data_dst = NULL;
static DMA_HandleTypeDef DMA_Handle = {0};
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma) {
if (dma_transfer_remaining > MAX_DATA_SIZE) {
dma_transfer_remaining -= MAX_DATA_SIZE;
dma_data_transferred += MAX_DATA_SIZE;
} else {
dma_data_transferred += dma_transfer_remaining;
dma_transfer_remaining = 0;
}
if (dma_transfer_remaining > 0) {
uint32_t data_to_send = dma_transfer_remaining > MAX_DATA_SIZE
? MAX_DATA_SIZE
: dma_transfer_remaining;
HAL_DMA_Start_IT(hdma,
(uint32_t) & ((uint8_t *)data_src)[dma_data_transferred],
(uint32_t)data_dst, data_to_send);
}
}
void GPDMA1_Channel0_IRQHandler(void) {
if ((DMA_Handle.Instance->CSR & DMA_CSR_TCF) == 0) {
// error, abort the transfer and allow the next one to start
dma_data_transferred = 0;
dma_transfer_remaining = 0;
}
HAL_DMA_IRQHandler(&DMA_Handle);
if (dma_transfer_remaining == 0) {
// transfer finished, disable the channel
HAL_DMA_DeInit(&DMA_Handle);
HAL_NVIC_DisableIRQ(GPDMA1_Channel0_IRQn);
data_src = NULL;
data_dst = NULL;
}
}
bool bg_copy_pending(void) { return dma_transfer_remaining > 0; }
void bg_copy_wait(void) {
while (dma_transfer_remaining > 0) {
__WFI();
}
}
void bg_copy_start_const_out_8(const uint8_t *src, uint8_t *dst, size_t size) {
uint32_t data_to_send = size > MAX_DATA_SIZE ? MAX_DATA_SIZE : size;
dma_transfer_remaining = size;
dma_data_transferred = 0;
data_src = (void *)src;
data_dst = (void *)dst;
// setup DMA for data copy to constant output address
__HAL_RCC_GPDMA1_CLK_ENABLE();
/* USER CODE END GPDMA1_Init 1 */
DMA_Handle.Instance = GPDMA1_Channel0;
DMA_Handle.XferCpltCallback = HAL_DMA_XferCpltCallback;
DMA_Handle.Init.Request = GPDMA1_REQUEST_HASH_IN;
DMA_Handle.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
DMA_Handle.Init.Direction = DMA_MEMORY_TO_MEMORY;
DMA_Handle.Init.SrcInc = DMA_SINC_INCREMENTED;
DMA_Handle.Init.DestInc = DMA_DINC_FIXED;
DMA_Handle.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
DMA_Handle.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
DMA_Handle.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
DMA_Handle.Init.SrcBurstLength = 1;
DMA_Handle.Init.DestBurstLength = 1;
DMA_Handle.Init.TransferAllocatedPort =
DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT0;
DMA_Handle.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
DMA_Handle.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&DMA_Handle);
HAL_DMA_ConfigChannelAttributes(&DMA_Handle, DMA_CHANNEL_SEC |
DMA_CHANNEL_SRC_SEC |
DMA_CHANNEL_DEST_SEC);
HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, IRQ_PRI_DMA, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)src, (uint32_t)dst, data_to_send);
}

View File

@ -41,6 +41,7 @@ def configure(
"embed/models/model_T3T1_layout.c", "embed/models/model_T3T1_layout.c",
] ]
sources += [f"embed/trezorhal/stm32u5/displays/{display}"] sources += [f"embed/trezorhal/stm32u5/displays/{display}"]
sources += [f"embed/trezorhal/stm32u5/bg_copy.c"]
sources += ["embed/trezorhal/stm32u5/backlight_pwm.c"] sources += ["embed/trezorhal/stm32u5/backlight_pwm.c"]
sources += [ sources += [
"embed/trezorhal/stm32u5/displays/panels/lx154a2422.c", "embed/trezorhal/stm32u5/displays/panels/lx154a2422.c",