mirror of
https://github.com/espressif/esp-idf.git
synced 2026-01-19 05:27:11 +00:00
fix(ppa): fix potential SRM operation stuck on DMA issue
Apply a workaound to bypass macro block order function in PPA SRM when specific conditions are met to avoid SRM operation getting stuck
This commit is contained in:
@@ -156,6 +156,28 @@ bool ppa_srm_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel
|
||||
ppa_ll_srm_enable_mirror_x(platform->hal.dev, srm_trans_desc->mirror_x);
|
||||
ppa_ll_srm_enable_mirror_y(platform->hal.dev, srm_trans_desc->mirror_y);
|
||||
|
||||
// Hardware bug workaround (DIG-734)
|
||||
uint32_t w_out = srm_trans_desc->in.block_w * srm_trans_desc->scale_x_int + srm_trans_desc->in.block_w * srm_trans_desc->scale_x_frag / PPA_LL_SRM_SCALING_FRAG_MAX;
|
||||
uint32_t w_divisor = (ppa_out_color_mode == PPA_SRM_COLOR_MODE_ARGB8888 || ppa_out_color_mode == PPA_SRM_COLOR_MODE_RGB888) ? 32 : 64;
|
||||
uint32_t w_left = w_out % w_divisor;
|
||||
w_left = (w_left == 0) ? w_divisor : w_left;
|
||||
uint32_t h_mb = (ppa_ll_srm_get_mb_size(platform->hal.dev) == PPA_LL_SRM_MB_SIZE_16_16) ? 16 : 32;
|
||||
uint32_t h_in_left = srm_trans_desc->in.block_h % h_mb;
|
||||
h_in_left = (h_in_left == 0) ? h_mb : h_in_left;
|
||||
uint32_t h_left = h_in_left * srm_trans_desc->scale_y_int + h_in_left * srm_trans_desc->scale_y_frag / PPA_LL_SRM_SCALING_FRAG_MAX;
|
||||
const uint32_t dma2d_fifo_depth_bits = 12 * 128;
|
||||
color_space_pixel_format_t out_pixel_format = {
|
||||
.color_type_id = ppa_out_color_mode,
|
||||
};
|
||||
uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format);
|
||||
bool bypass_mb_order = false;
|
||||
if (((w_out > w_divisor) || (srm_trans_desc->in.block_h > h_mb)) && // will be cut into more than one trans unit
|
||||
((w_left * h_left * out_pixel_depth) < dma2d_fifo_depth_bits)
|
||||
) {
|
||||
bypass_mb_order = true;
|
||||
}
|
||||
ppa_ll_srm_bypass_mb_order(platform->hal.dev, bypass_mb_order);
|
||||
|
||||
ppa_ll_srm_start(platform->hal.dev);
|
||||
|
||||
// No need to yield
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "hal/color_hal.h"
|
||||
#include "esp_cache.h"
|
||||
#include "ppa_performance.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
@@ -837,3 +838,86 @@ TEST_CASE("ppa_fill_performance", "[PPA]")
|
||||
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
TEST_CASE("ppa_srm_stress_test", "[PPA]")
|
||||
{
|
||||
// Configurable parameters
|
||||
const uint32_t w = 200;
|
||||
const uint32_t h = 200;
|
||||
const ppa_srm_color_mode_t in_cm = PPA_SRM_COLOR_MODE_RGB565;
|
||||
const ppa_srm_color_mode_t out_cm = PPA_SRM_COLOR_MODE_RGB565;
|
||||
const ppa_srm_rotation_angle_t rotation = PPA_SRM_ROTATION_ANGLE_0;
|
||||
const float scale_x = 1.0;
|
||||
const float scale_y = 1.0;
|
||||
|
||||
color_space_pixel_format_t in_pixel_format = {
|
||||
.color_type_id = in_cm,
|
||||
};
|
||||
color_space_pixel_format_t out_pixel_format = {
|
||||
.color_type_id = out_cm,
|
||||
};
|
||||
|
||||
uint32_t in_buf_size = w * h * color_hal_pixel_format_get_bit_depth(in_pixel_format) / 8;
|
||||
uint32_t out_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_get_bit_depth(out_pixel_format) / 8, 64);
|
||||
uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_NULL(out_buf);
|
||||
uint8_t *in_buf = heap_caps_aligned_calloc(4, in_buf_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_NULL(in_buf);
|
||||
|
||||
ppa_client_handle_t ppa_client_handle;
|
||||
ppa_client_config_t ppa_client_config = {
|
||||
.oper_type = PPA_OPERATION_SRM,
|
||||
.max_pending_trans_num = 1,
|
||||
};
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
||||
|
||||
// Test on different sizes of the block
|
||||
int test_iterations = 50;
|
||||
while (test_iterations-- > 0) {
|
||||
uint32_t block_w_initial = esp_random() % (w - 100);
|
||||
uint32_t block_h_initial = esp_random() % (h - 100);
|
||||
block_w_initial = (block_w_initial == 0) ? 1 : block_w_initial;
|
||||
block_h_initial = (block_h_initial == 0) ? 1 : block_h_initial;
|
||||
uint32_t block_w = 0;
|
||||
uint32_t block_h = 0;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
block_w = block_w_initial + i;
|
||||
block_h = block_h_initial + i;
|
||||
// printf("block_w = %ld, block_h = %ld\n", block_w, block_h);
|
||||
ppa_srm_oper_config_t oper_config = {
|
||||
.in.buffer = in_buf,
|
||||
.in.pic_w = w,
|
||||
.in.pic_h = h,
|
||||
.in.block_w = block_w,
|
||||
.in.block_h = block_h,
|
||||
.in.block_offset_x = 0,
|
||||
.in.block_offset_y = 0,
|
||||
.in.srm_cm = in_cm,
|
||||
|
||||
.out.buffer = out_buf,
|
||||
.out.buffer_size = out_buf_size,
|
||||
.out.pic_w = block_w,
|
||||
.out.pic_h = block_h,
|
||||
.out.block_offset_x = 0,
|
||||
.out.block_offset_y = 0,
|
||||
.out.srm_cm = out_cm,
|
||||
|
||||
.rotation_angle = rotation,
|
||||
.scale_x = scale_x,
|
||||
.scale_y = scale_y,
|
||||
|
||||
.rgb_swap = 0,
|
||||
.byte_swap = 0,
|
||||
|
||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_handle, &oper_config));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
||||
|
||||
free(in_buf);
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
@@ -600,6 +600,17 @@ static inline void ppa_ll_srm_get_dma_dscr_port_mode_block_size(ppa_dev_t *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether to bypass the macro block order function in PPA SRM
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param enable True to bypass; False to not bypass
|
||||
*/
|
||||
static inline void ppa_ll_srm_bypass_mb_order(ppa_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->sr_byte_order.sr_macro_bk_ro_bypass = enable;
|
||||
}
|
||||
|
||||
//////////////////////////////////// Blending ////////////////////////////////////////
|
||||
/*
|
||||
* Alpha Blending Calculation:
|
||||
|
||||
Reference in New Issue
Block a user