[经验分享] 【平头哥RVB2601创意应用开发】RVB2601之启动流程

zhengyad   2022-4-21 17:52 楼主

自己的理解,不对的地方请指正。

工程组成

初始化相关文件

 

初始化相关文件都放在了sys文件夹下。

单片机在main函数之前,都得先初始化堆栈和中断向量表。

在启动代码startup.s中对向量表和堆栈进行了管理,代码如下:

/*
 * Copyright (C) 2017-2019 Alibaba Group Holding Limited
 */
 
 /******************************************************************************
 * @File     startup.S
 * @brief    startup file. Should use with
 *           GCC for CSKY Embedded Processors
 * @version  V1.0
 * @date     29. July 2019
 ******************************************************************************/
 
#include <csi_config.h>
 
.section .vectors, "aw", @progbits
    .align  6
    .globl  __Vectors
    .type   __Vectors, @object
__Vectors:
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   tspend_handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_IRQHandler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
 
    /* External interrupts */
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
    .long   Default_IRQHandler
 
    .text
    .align   2
    .long    Reset_Handler
    .rept    15
    .long    0
    .endr
    .long    Reset_Handler
_start:
    .text
    .align  2
    .globl  Reset_Handler
    .type   Reset_Handler, %function
    .globl  __driver_test_service__
    .weak   __driver_test_service__
    .type   __driver_test_service__, %function
    
Reset_Handler:
    csrc    mstatus, 8
.option push
.option norelax
    la      gp, __global_pointer$
.option pop
    la      a0, Default_Handler
    ori     a0, a0, 3
    csrw    mtvec, a0
 
    li      a0, 0x2000
    csrs    mstatus, a0
 
    la      a0, __Vectors
    csrw    mtvt, a0
 
    la      a0, 0x100000
    csrw    mhint, a0
 
    la      sp, g_top_irqstack
 
#ifndef __NO_SYSTEM_INIT
    jal     SystemInit
#endif
 
    la     a0, __driver_test_service__
    beq    zero, a0, 1f
    jalr   a0
    j      __exit
    
1:
    jal    pre_main
 
    .size   Reset_Handler, . - Reset_Handler
 
__exit:
    j      __exit
 
.section .stack
 
    .align  3
    .global g_base_irqstack
    .global g_top_irqstack
g_base_irqstack:
    .space CONFIG_ARCH_INTERRUPTSTACK
g_top_irqstack:

 


Default_Handler在vectors.S中定义

 

#ifdef CONFIG_KERNEL_NONE
    .align  2
    .global Default_IRQHandler
    .weak   Default_IRQHandler
    .type   Default_IRQHandler, %function
Default_IRQHandler:
    .
    .
    .
    .
    .
    .
#else
    .align  2
    .global Default_IRQHandler
    .weak   Default_IRQHandler
    .type   Default_IRQHandler, %function
Default_IRQHandler:
    .
    .
    .
    .
    .
    .
 
#endif


根据 CONFIG_KERNEL_NONE 得定义,对Default_Handler进行条件编译,用不用内核对中断是有影响的。

 

g_top_irqstack在vectors.S中定义

 

 

 

通过指令  jal     SystemInit  对系统初始化

 

SystemInit函数定义在system.c中

/**
  * @brief  initialize the system
  *         Initialize the psr and vbr.
  * @param  None
  * @return None
  */
void SystemInit(void)
{
    enable_theadisaee();
 
    cache_init();
 
    section_init();
 
    interrupt_init();
 
    soc_set_sys_freq(CPU_196_608MHZ);
 
    csi_etb_init();
 
    sys_dma_init();
 
    csi_tick_init();
 
#ifdef CONFIG_XIP
    sys_spiflash_init();
#endif
    bootrom_uart_uninit();
}


可以看出,通过SystemInit函数,基本对中断、时钟、dma、tick等等板上资源进行了初始化。

最后通过指令  

jal    pre_main 

跳转到main函数。
pre_main函数定义:

__attribute__((weak)) void pre_main(void)
{
#ifndef CONFIG_KERNEL_RHINO
#ifndef CONFIG_NUTTXMM_NONE
    extern void mm_heap_initialize();
    mm_heap_initialize();
#endif
#endif
 
    main();
}
main函数作为用户应用程序的入口。
 

本帖最后由 zhengyad 于 2022-4-21 17:56 编辑

回复评论 (1)

RVB2601之启动流程没发现那里不对,很好

点赞  2022-4-22 07:09
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复