富芮坤fr8008gp lvgl遇坑:卡死在lvgl定时器中;SWD接口配置;

卡死在lvgl定时器中

官方提供的lvgl的demo在gui_main函数中如下设置定时器并调用window_manager_init函数初始化各个界面:

    /* Implement and register a function which can read an input device. E.g. for a touch pad */
    static lv_indev_drv_t indev_drv;                  /*Descriptor of a input device driver*/
    lv_indev_drv_init ( &indev_drv );          /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;    /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;      /*Set your driver function*/
    lv_indev_drv_register ( &indev_drv );      /*Finally register the driver*/

    //timer_reinit();
    __SYSTEM_TIMER_CLK_ENABLE();
    timer_init ( Timer0, system_get_clock_config() * 1000 * LV_TICK_COUNT, TIMER_DIV_NONE );
    timer_start ( Timer0 );
    NVIC_SetPriority ( TIMER0_IRQn, 5 );
    NVIC_EnableIRQ ( TIMER0_IRQn );

	//    os_timer_init(&lv_schedule_timer, lv_schedule_timer_handler, NULL);
    //    os_timer_start(&lv_schedule_timer, 20, true);
    timer_init ( Timer1, system_get_clock_config() * 1000 * 100, TIMER_DIV_NONE );
    timer_start ( Timer1 );
    NVIC_SetPriority ( TIMER1_IRQn, 6 );
    NVIC_EnableIRQ ( TIMER1_IRQn );
	
	//init display menu
    window_manager_init();

通过分析timer1中断回调函数可以看到该中断回调函数中是有调用lvgl的lv_timer_handler函数的,也就是说涉及到lvgl的相关流程:

__attribute__ ( ( section ( "ram_code" ) ) ) void timer1_handler ( void )
{
    uint32_t tick;
    timer_int_clear ( Timer1 );
    timer_stop ( Timer1 );

    tick = lv_timer_handler();
    timer_init ( Timer1, system_get_clock_config() * 1000 * tick, TIMER_DIV_NONE );
    timer_start ( Timer1 );
}

static void lv_schedule_timer_handler ( void *arg )
{
    lv_timer_handler();
}
/**
 * Call it periodically to handle lv_timers.
 * @return the time after which it must be called again
 */
LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
{
    TIMER_TRACE("begin");

    /*Avoid concurrent running of the timer handler*/
    static bool already_running = false;
    if(already_running) {
        TIMER_TRACE("already running, concurrent calls are not allow, returning");
        return 1;
    }
    already_running = true;

    if(lv_timer_run == false) {
        already_running = false; /*Release mutex*/
        return 1;
    }

    static uint32_t idle_period_start = 0;
    static uint32_t busy_time         = 0;

    uint32_t handler_start = lv_tick_get();

    if(handler_start == 0) {
        static uint32_t run_cnt = 0;
        run_cnt++;
        if(run_cnt > 100) {
            run_cnt = 0;
            LV_LOG_WARN("It seems lv_tick_inc() is not called.");
        }
    }

    /*Run all timer from the list*/
    lv_timer_t * next;
    do {
        timer_deleted             = false;
        timer_created             = false;
        LV_GC_ROOT(_lv_timer_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll));
        while(LV_GC_ROOT(_lv_timer_act)) {
            /*The timer might be deleted if it runs only once ('repeat_count = 1')
             *So get next element until the current is surely valid*/
            next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), LV_GC_ROOT(_lv_timer_act));

            if(lv_timer_exec(LV_GC_ROOT(_lv_timer_act))) {
                /*If a timer was created or deleted then this or the next item might be corrupted*/
                if(timer_created || timer_deleted) {
                    TIMER_TRACE("Start from the first timer again because a timer was created or deleted");
                    break;
                }
            }

            LV_GC_ROOT(_lv_timer_act) = next; /*Load the next timer*/
        }
    } while(LV_GC_ROOT(_lv_timer_act));

    uint32_t time_till_next = LV_NO_TIMER_READY;
    next = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll));
    while(next) {
        if(!next->paused) {
            uint32_t delay = lv_timer_time_remaining(next);
            if(delay < time_till_next)
                time_till_next = delay;
        }

        next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), next); /*Find the next timer*/
    }

    busy_time += lv_tick_elaps(handler_start);
    uint32_t idle_period_time = lv_tick_elaps(idle_period_start);
    if(idle_period_time >= IDLE_MEAS_PERIOD) {
        idle_last         = (busy_time * 100) / idle_period_time;  /*Calculate the busy percentage*/
        idle_last         = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/
        busy_time         = 0;
        idle_period_start = lv_tick_get();
    }

    already_running = false; /*Release the mutex*/

    TIMER_TRACE("finished (%d ms until the next timer call)", time_till_next);
    return time_till_next;
}

按照上面的代码,很容易出现卡死在Timer1中断函数中的现象,这个现象并不是必现的,复位十次基本有3次能够出现:
在这里插入图片描述

   lv_mem_buf_get
        0x10028474:    2800        .(      CMP      r0,#0
        0x10028476:    bf08        ..      IT       EQ
        0x10028478:    4770        pG      BXEQ     lr
        0x1002847a:    e92d41f0    -..A    PUSH     {r4-r8,lr}
        0x1002847e:    2100        .!      MOVS     r1,#0
        0x10028480:    4e32        2N      LDR      r6,[pc,#200] ; [0x1002854c] = 0x11009904
        0x10028482:    b088        ..      SUB      sp,sp,#0x20
        0x10028484:    4605        .F      MOV      r5,r0
        0x10028486:    f04f32ff    O..2    MOV      r2,#0xffffffff
        0x1002848a:    2701        .'      MOVS     r7,#1
        0x1002848c:    eb0603c1    ....    ADD      r3,r6,r1,LSL #3
        0x10028490:    7998        .y      LDRB     r0,[r3,#6]
        0x10028492:    f0100f01    ....    TST      r0,#1
        0x10028496:    d113        ..      BNE      0x100284c0 ; lv_mem_buf_get + 76
        0x10028498:    889b        ..      LDRH     r3,[r3,#4]
        0x1002849a:    42ab        .B      CMP      r3,r5
        0x1002849c:    d310        ..      BCC      0x100284c0 ; lv_mem_buf_get + 76
        0x1002849e:    d107        ..      BNE      0x100284b0 ; lv_mem_buf_get + 60
        0x100284a0:    eb0600c1    ....    ADD      r0,r6,r1,LSL #3
        0x100284a4:    7187        .q      STRB     r7,[r0,#6]
        0x100284a6:    f8560031    V.1.    LDR      r0,[r6,r1,LSL #3]
        0x100284aa:    b008        ..      ADD      sp,sp,#0x20
        0x100284ac:    e8bd81f0    ....    POP      {r4-r8,pc}
        0x100284b0:    2a00        .*      CMP      r2,#0
        0x100284b2:    db04        ..      BLT      0x100284be ; lv_mem_buf_get + 74
        0x100284b4:    eb0600c2    ....    ADD      r0,r6,r2,LSL #3
        0x100284b8:    8880        ..      LDRH     r0,[r0,#4]
        0x100284ba:    4283        .B      CMP      r3,r0
        0x100284bc:    d200        ..      BCS      0x100284c0 ; lv_mem_buf_get + 76
        0x100284be:    b24a        J.      SXTB     r2,r1
        0x100284c0:    1c48        H.      ADDS     r0,r1,#1
        0x100284c2:    b2c1        ..      UXTB     r1,r0
        0x100284c4:    2910        .)      CMP      r1,#0x10
        0x100284c6:    d3e1        ..      BCC      0x1002848c ; lv_mem_buf_get + 24
        0x100284c8:    2a00        .*      CMP      r2,#0
        0x100284ca:    bfb8        ..      IT       LT
        0x100284cc:    2400        .$      MOVLT    r4,#0
        0x100284ce:    db07        ..      BLT      0x100284e0 ; lv_mem_buf_get + 108
        0x100284d0:    eb0600c2    ....    ADD      r0,r6,r2,LSL #3
        0x100284d4:    7187        .q      STRB     r7,[r0,#6]
        0x100284d6:    f8560032    V.2.    LDR      r0,[r6,r2,LSL #3]
        0x100284da:    b008        ..      ADD      sp,sp,#0x20
        0x100284dc:    e8bd81f0    ....    POP      {r4-r8,pc}
        0x100284e0:    eb0600c4    ....    ADD      r0,r6,r4,LSL #3
        0x100284e4:    7980        .y      LDRB     r0,[r0,#6]
        0x100284e6:    f0100f01    ....    TST      r0,#1
        0x100284ea:    d004        ..      BEQ      0x100284f6 ; lv_mem_buf_get + 130
        0x100284ec:    1c60        `.      ADDS     r0,r4,#1
        0x100284ee:    b2c4        ..      UXTB     r4,r0
        0x100284f0:    2c10        .,      CMP      r4,#0x10
        0x100284f2:    d3f5        ..      BCC      0x100284e0 ; lv_mem_buf_get + 108
        0x100284f4:    e7fe        ..      B        0x100284f4 ; lv_mem_buf_get + 128
        0x100284f6:    4816        .H      LDR      r0,[pc,#88] ; [0x10028550] = 0x11007a94
        0x100284f8:    f8561034    V.4.    LDR      r1,[r6,r4,LSL #3]
        0x100284fc:    f8df8050    ..P.    LDR      r8,[pc,#80] ; [0x10028550] = 0x11007a94
        0x10028500:    6840        @h      LDR      r0,[r0,#4]
        0x10028502:    002a        *.      MOVS     r2,r5
        0x10028504:    d00b        ..      BEQ      0x1002851e ; lv_mem_buf_get + 170
        0x10028506:    4541        AE      CMP      r1,r8
        0x10028508:    d10f        ..      BNE      0x1002852a ; lv_mem_buf_get + 182
        0x1002850a:    4629        )F      MOV      r1,r5
        0x1002850c:    f008fca6    ....    BL       lv_tlsf_malloc ; 0x10030e5c
        0x10028510:    ea5f0800    _...    MOVS     r8,r0
        0x10028514:    bf04        ..      ITT      EQ
        0x10028516:    4668        hF      MOVEQ    r0,sp
        0x10028518:    f000f848    ..H.    BLEQ     lv_mem_monitor ; 0x100285ac
        0x1002851c:    e008        ..      B        0x10028530 ; lv_mem_buf_get + 188
        0x1002851e:    4541        AE      CMP      r1,r8
        0x10028520:    bf1c        ..      ITT      NE
        0x10028522:    2900        .)      CMPNE    r1,#0
        0x10028524:    f008fc4a    ..J.    BLNE     lv_tlsf_free ; 0x10030dbc
        0x10028528:    e002        ..      B        0x10028530 ; lv_mem_buf_get + 188
        0x1002852a:    f008fcb0    ....    BL       lv_tlsf_realloc ; 0x10030e8e
        0x1002852e:    4680        .F      MOV      r8,r0
        0x10028530:    f1b80f00    ....    CMP      r8,#0
        0x10028534:    d009        ..      BEQ      0x1002854a ; lv_mem_buf_get + 214
        0x10028536:    eb0600c4    ....    ADD      r0,r6,r4,LSL #3
        0x1002853a:    7187        .q      STRB     r7,[r0,#6]
        0x1002853c:    8085        ..      STRH     r5,[r0,#4]
        0x1002853e:    f8468034    F.4.    STR      r8,[r6,r4,LSL #3]
        0x10028542:    b008        ..      ADD      sp,sp,#0x20
        0x10028544:    4640        @F      MOV      r0,r8
        0x10028546:    e8bd81f0    ....    POP      {r4-r8,pc}
        0x1002854a:    e7fe        ..      B        0x1002854a ; lv_mem_buf_get + 214
    $d

这时候把window_manager_init函数放到定时器初始化之前就能够解决这个问题:

    /* Implement and register a function which can read an input device. E.g. for a touch pad */
    static lv_indev_drv_t indev_drv;                  /*Descriptor of a input device driver*/
    lv_indev_drv_init ( &indev_drv );          /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;    /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;      /*Set your driver function*/
    lv_indev_drv_register ( &indev_drv );      /*Finally register the driver*/

	//init display menu
    window_manager_init();

    //timer_reinit();
    __SYSTEM_TIMER_CLK_ENABLE();
    timer_init ( Timer0, system_get_clock_config() * 1000 * LV_TICK_COUNT, TIMER_DIV_NONE );
    timer_start ( Timer0 );
    NVIC_SetPriority ( TIMER0_IRQn, 5 );
    NVIC_EnableIRQ ( TIMER0_IRQn );

	//    os_timer_init(&lv_schedule_timer, lv_schedule_timer_handler, NULL);
    //    os_timer_start(&lv_schedule_timer, 20, true);
    timer_init ( Timer1, system_get_clock_config() * 1000 * 100, TIMER_DIV_NONE );
    timer_start ( Timer1 );
    NVIC_SetPriority ( TIMER1_IRQn, 6 );
    NVIC_EnableIRQ ( TIMER1_IRQn );

这样改虽然不会死机了,但是会出现表盘界面表针出来很晚的现象,这个后期再想办法优化:

lvgl表盘界面表针晚出现

未修改前的效果请看文章:https://blog.csdn.net/cheng___yi/article/details/128622148

SWD接口配置

我们从官方提供的硬件参考资料可以得到SWD占用如下管脚:
在这里插入图片描述
通过和技术支持沟通知道这两个管脚默认是SWD功能(未确定),但是我这里依旧在proj_init函数中做了如下配置:

    // configure PSRAM pin and init PSRAM
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_0, PORTC0_FUNC_QSPI0_IO3 );
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_1, PORTC1_FUNC_QSPI0_SCLK0 );
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_2, PORTC2_FUNC_QSPI0_CSN0 );
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_3, PORTC3_FUNC_QSPI0_IO1 );
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_4, PORTC4_FUNC_QSPI0_IO2 );
    system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_5, PORTC5_FUNC_QSPI0_IO0 );
    psram_init();
	system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_6, PORTC6_FUNC_SW_TCK );
	system_set_port_mux ( GPIO_PORT_C, GPIO_BIT_7, PORTC7_FUNC_SW_DIO );

经过测试依旧没有什么作用,SWD依旧连接不上,原厂说SWD要连接不上有如下可能:要么进睡眠了,要么IO被复用其他功能了
但是我都没有这方面的设置,无语了,最后原厂说让我擦除一下芯片再用JLINK连接看看,我擦除后发现确实可以连接上,然后我重新烧录代码和flash,发现竟然可以连接了,无语!应该是原来芯片做了相关设置造成不能够连接,我擦除重新烧录后就可以了!这个问题最终都没有找到根本原因!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STLINK是ST公司推出的一款调试和编程工具,被用于将计算机与ST微控制器连接起来。STLINK SWD接口是STLINK的一种通信接口,用于通过串行线调试与目标微控制器进行通信。 STLINK SWD接口采用两根线实现与目标微控制器的连接:SWDIO和SWCLK。其SWDIO线用于双向传输数据和调试信息,而SWCLK线则用于时钟同步。通过STLINK SWD接口,可以实现对目标微控制器的调试、下载和运行控制等操作。 使用STLINK SWD接口进行调试时,需要将STLINK连接到目标微控制器上的SWD接口上,并通过相应的调试软件进行配置和控制。在调试过程,可以通过STLINK与目标微控制器进行双向通信,实现对寄存器的读写、程序的下载、运行控制以及断点设置等操作。 STLINK SWD接口具有以下特点: 首先,它是一种高速的接口,可以实现快速的数据传输和调试操作。其次,SWD接口相对于JTAG接口来说,线数较少,因此在PCB设计时更加简单,可以减小目标系统的尺寸。另外,STLINK SWD接口还支持多线调试和多目标调试,可以同时连接多个目标微控制器进行调试。 总之,STLINK SWD接口是一种用于调试和编程的通信接口,通过STLINK与目标微控制器连接,实现对目标微控制器的调试、下载和运行控制等操作。它具有高速、简单、支持多目标调试等特点,是嵌入式系统开发常用的调试工具之一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值