启动文件,其实也就是裸机编程文件

关于这个问题,三种解决方法:

  • 自己找博客、github、技术手册等,看看a9的启动文件,然后买块a9的开发板,自己烧录下载,运行。缺点:需要买板子,而且没有好用的IDE支撑(虽然eclipse经过一定的配置后也能行),下载程序很困难(可能需要sd卡反复插拔),调试可能更困难了,还需要买个jlink调试器,还只能gdb命令行调试(当然也有一些gdb前端调试软件,比如ozone等)。我这个博客也有写这个 windows上运行qemu仿真stm32板子a9板子实例_标biao的博客-CSDN博客
  • Linux的bootloader,一般是uboot是最为通用的bootloader,里面就有这样的代码。缺点:太复杂,扒拉出来学习成本太高。嵌入式杂记(uboot启动流程,简单易懂!!!)_标biao的博客-CSDN博客
  • 通过虚拟机qemu仿真a9板子。优点:程序的下载和调试都方便了;缺点:可能下载调试运行等操作比较慢,毕竟是仿真嘛,依赖于电脑性能。

三者我都尝试过,这里我建议选第三种方法吧。(而且我现在是在windows系统上搞这个,网上大部分教程都是在Ubuntu系统,对初学者不友好)

没必要重复造轮子,我们直接找现成的,国产嵌入式实时操作系统 rtthread 这方面就做得比较好,在各种处理器体系都有适配。

rtthread 官网:RT-Thread, RTOS, 物联网操作系统 - RT-Thread物联网操作系统

  1. 去下载它们的免费IDE,RT-Thread Studio
  2. 新建一个基于开发板的项目,开发板选择 VExpress-A9,这个是arm官方做产品测试搞出来的开发板,这里是对它进行了qemu的模拟,还能看到启动qemu用了哪些命令,自己命令行就可以借鉴使用了。

    下载命令:
    qemu-system-arm.exe -M vexpress-a9 -nographic        -kernel Debug/rtthread.bin

    调试命令:
    qemu-system-arm.exe -M vexpress-a9 -nographic -S -s       -kernel Debug/rtthread.elf

    关于每个选项什么意思,大家自己百度一下吧。

    注:经过RT-Thread Studio的github主页介绍,以及我的测试,rthread确实只支持a9这个板子的qemu仿真模拟(而且只能是单核,尽管我们可以在debug设置界面设置为多核,调试就会报错了,其它的,比如stm32f4这些都不支持(虽然有些地方说支持,是假的)。究其原因,RT-Thread Studio后台调用的是qemu-system-arm.exe这个软件,而不是qemu-system-guneclipse.exe这个(可以参考我的博客qemu的详细资料大全(入门必看!!!)_标biao的博客-CSDN博客)。

  3. 傻瓜式的构建项目,下载,调试就行。这也说明这个IDE做得真不错
  4. 启动文件在这儿



     
  5. a9的启动文件,rtthread封装得挺好,注释写得很清楚
    (1)设置处理器模式
    (2)设置FPU
    (3)设置一个栈
    (4)初始化bss段
    (5)设置是否适用多核的配置
    (6)设置mmu
    (7)跳入C语言函数

    自己可以打个断点,在这个IDE里调试运行一下,就全部明白了。

    同理其它处理器的启动文件如何搞(比如stm32,sparc等处理器的启动文件),也通过这个IDE新建工程就能看啦,但是不支持qemu仿真了。
_reset:
    /* set the cpu to SVC32 mode and disable interrupt */
    cps #Mode_SVC

#ifdef RT_USING_FPU
    mov r4, #0xfffffff
    mcr p15, 0, r4, c1, c0, 2
#endif

    /* disable the data alignment check */
    mrc p15, 0, r1, c1, c0, 0
    bic r1, #(1<<1)
    mcr p15, 0, r1, c1, c0, 0

    /* setup stack */
    bl      stack_setup

    /* clear .bss */
    mov     r0,#0                   /* get a zero                       */
    ldr     r1,=__bss_start         /* bss start                        */
    ldr     r2,=__bss_end           /* bss end                          */

bss_loop:
    cmp     r1,r2                   /* check if data to clear           */
    strlo   r0,[r1],#4              /* clear 4 bytes                    */
    blo     bss_loop                /* loop until done                  */

#ifdef RT_USING_SMP
    mrc p15, 0, r1, c1, c0, 1
    mov r0, #(1<<6)
    orr r1, r0
    mcr p15, 0, r1, c1, c0, 1 //enable smp
#endif

    /* initialize the mmu table and enable mmu */
    ldr r0, =platform_mem_desc
    ldr r1, =platform_mem_desc_size
    ldr r1, [r1]
    bl rt_hw_init_mmu_table
    bl rt_hw_mmu_init

    /* call C++ constructors of global objects                          */
    ldr     r0, =__ctors_start__
    ldr     r1, =__ctors_end__

ctor_loop:
    cmp     r0, r1
    beq     ctor_end
    ldr     r2, [r0], #4
    stmfd   sp!, {r0-r1}
    mov     lr, pc
    bx      r2
    ldmfd   sp!, {r0-r1}
    b       ctor_loop
ctor_end:

    /* start RT-Thread Kernel */
    ldr     pc, _rtthread_startup      
_rtthread_startup:
 
    /* 这里就是把rtthread_startup这个函数地址放在这儿了,实现上面的跳入C语言函数了 */
    .word rtthread_startup       

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐