RK3566 Android11 替换开机logo导致死机问题


Platform: RK3566
OS: Android 11
U-boot: v2017.09
Kernel: v4.19.219
SDK Version:rk356x_box_11.0_release_v1.0.9_20220309
Module: uboot logo


问题

替换开机logo后出现报错死机的情况,主要报错信息如下:

"Synchronous Abort" handler, esr 0x96000145

Reason: Exception from a Data abort, from current exception level
PC = 0000000000a01afc
LR = 0000000000a51c08
SP = 00000000eb9f8560
ESR_EL2 = 0000000096000145
Reloc Off = 00000000ed34b000

解法

uboot目录下修改

diff --git a/drivers/video/drm/rockchip_display.c b/drivers/video/drm/rockchip_display.c
index 939beb9387..775597841e 100644
--- a/drivers/video/drm/rockchip_display.c
+++ b/drivers/video/drm/rockchip_display.c
@@ -1331,6 +1331,7 @@ static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
                        ret = -EINVAL;
                        goto free_header;
                }
+                flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));
 
                logo->offset = 0;
                logo->ymirror = 0;
@@ -1345,7 +1346,7 @@ static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
 
        memcpy(&logo_cache->logo, logo, sizeof(*logo));
 
-       flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));
+       //flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));
 
 free_header:

简要分析

上述解法据客户说来源于RK姚工,没有做具体的解释,我自己尝试简单分析理解下:

  1. 我测试到该问题与logo图片的位深有关,24位的会出问题,8位的不会。据客户反馈2G ddr的机器上不会,我手上的是4G和8G的,都测到了问题。
  2. 看定义注释可知flush_dcache_range()函数应该是用于清除指定范围的dcache
/*
 * Flush range(clean & invalidate) from all levels of D-cache/unified cache
 */
void flush_dcache_range(unsigned long start, unsigned long stop)
{
        __asm_flush_dcache_range(start, stop);
}
/*
 * void __asm_flush_dcache_range(start, end)
 *
 * clean & invalidate data cache in the range
 *
 * x0: start address
 * x1: end address
 */
.pushsection .text.__asm_flush_dcache_range, "ax"
ENTRY(__asm_flush_dcache_range)
        mrs     x3, ctr_el0
        lsr     x3, x3, #16 
        and     x3, x3, #0xf
        mov     x2, #4
        lsl     x2, x2, x3              /* cache line size */

        /* x2 <- minimal cache line size in cache system */
        sub     x3, x2, #1
        bic     x0, x0, x3
1:      dc      civac, x0       /* clean & invalidate data or unified cache */
        add     x0, x0, x2
        cmp     x0, x1
        b.lo    1b  
        dsb     sy  
        ret 
ENDPROC(__asm_flush_dcache_range)
.popsection

其中的ALIGN()宏是一个内存对齐操作1,防止frame buffer可能不是cache line size的整数倍时出错。

#define ALIGN(x,a)              __ALIGN_MASK((x),(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
  1. 根据参考资料2,cache有3种操作:clean,invalid,flush,其中flush是对每条cache line 先clean,再invalid.
  2. 上述出问题的代码位于load_bmp_logo()函数,看其命名应该就是加载logo的bmp图片,其中通过can_direct_logo()来判断位深,如果是24位或32位就直接设置下offset和ymirror然后送到cache去,如果位深小等于16位则要先强制设为16位再进行操作。根据目前的测试情况,是只能对小等于16位的图片进行flush cache,否则就会出错。
    虽然看了一些参考资料34,但是出错的具体原因还不甚明了,希望有了解的同学可以指导一下。
if (!can_direct_logo(logo->bpp)) {
                /*
                 * TODO: force use 16bpp if bpp less than 16;
                 */
                logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp;
                dst_size = logo->width * logo->height * logo->bpp >> 3;
                dst = get_display_buffer(dst_size);
                if (!dst) {
                        ret = -ENOMEM;
                        goto free_header;
                }
                if (bmpdecoder(pdst, dst, logo->bpp)) {
                        printf("failed to decode bmp %s\n", bmp_name);
                        ret = -EINVAL;
                        goto free_header;
                }
                flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));

                logo->offset = 0;
                logo->ymirror = 0;
        } else {
                logo->offset = get_unaligned_le32(&header->data_offset);
                if (reserved == BMP_PROCESSED_FLAG)
                        logo->ymirror = 0;
                else
                        logo->ymirror = 1;
        }
        logo->mem = dst;

        memcpy(&logo_cache->logo, logo, sizeof(*logo));


如有谬误欢迎指正,感谢阅读~

参考资料


  1. Linux align函数,linux内核中ALIGN解析(示例代码) ↩︎

  2. 刷cache的3种操作:clean/invalid/flush ↩︎

  3. linux cpu cache ↩︎

  4. 移植u-boot v2018 ↩︎

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值