在嵌入式系统中,从设备上电到执行应用程序的main()函数,bootloader扮演着至关重要的角色。作为
在嵌入式系统中,从设备上电到执行应用程序的main()函数,bootloader扮演着至关重要的角色。作为系统启动的首个程序,bootloader负责初始化硬件、设置运行环境,并最终将控制权移交至应用程序。
从冷上电到main()函数的执行,嵌入式系统的启动流程可分为以下几个阶段:
上电复位:微控制器在接收到电源或复位信号后,从预定义的复位向量地址开始执行代码。通常,这个地址位于Flash存储器的起始位置(如STM32的0x08000000)。初始硬件设置:处理器执行存储在ROM或Flash中的代码,配置时钟系统、存储器控制器等关键硬件,确保系统稳定运行。Bootloader执行,Bootloader接管控制权,进一步初始化系统,可能包括:设置堆栈和堆。初始化外设。从外部存储器加载应用程序代码(若需要)。执行安全检查,如验证固件数字签名。跳转到应用程序的入口点。应用程序启动:启动代码完成环境设置后,调用main()函数,应用程序开始执行。对于带操作系统的系统(如嵌入式Linux),Bootloader会加载并启动操作系统内核。1
硬件初始化
上电后,微控制器首先执行硬件初始化。这通常包括:
时钟配置:设置系统时钟、PLL(锁相环)等,以确保处理器和外设以正确的频率运行。存储器配置:初始化存储器控制器,启用RAM或外部存储器。外设初始化:配置关键外设,如串口、GPIO等。这些初始化通常在汇编语言中实现,以确保高效和精确。例如,在STM32中,系统时钟的初始化可能在SystemInit()函数中完成。
2
引导模式与应用模式的抉择
许多Bootloader支持两种模式:
引导模式:用于固件更新或调试,通常通过特定输入(如按键、GPIO状态或串口命令)触发。应用模式:默认模式,直接运行应用程序。Bootloader会在启动时短暂等待用户输入(如按下F2、Delete键或设置特定GPIO)。若无输入,则跳转到应用程序代码。例如,U-Boot(一种常见的嵌入式Bootloader)通过串口、USB或以太网检测用户输入。
3
启动代码
启动代码是Bootloader的核心部分,负责为应用程序准备运行环境。主要任务包括:
设置堆栈指针:为函数调用和局部变量分配堆栈空间。初始化数据段:将初始化数据(.data段)从Flash复制到RAM。将未初始化数据(.bss段)清零。调用main()函数:将控制权移交至应用程序。在某些系统中,启动代码还会初始化C/C++运行时环境,如调用静态构造函数(C++)或设置标准库。
例如,STM32的启动代码通常在汇编文件中实现,如startup_stm32f4xx.s,位于STM32Cube固件包中(STM32CubeF4)。其主要功能包括:
定义向量表,包含初始堆栈指针和复位处理程序地址。实现复位处理程序(Reset Handler),执行初始化任务并调用main()。以下是一个简化的STM32启动代码示例(基于ARM Cortex-M):
代码语言:javascript代码运行次数:0运行复制Reset_Handler: ; 设置堆栈指针 ldr r0, =_estack mov sp, r0 ; 复制.data段从Flash到RAM ldr r1, =_sidata ldr r2, =_sdata ldr r3, =_edata b LoopCopyDataInitCopyDataInit: ldr r4, [r1], #4 str r4, [r2], #4LoopCopyDataInit: cmp r2, r3 bcc CopyDataInit ; 清零.bss段 ldr r2, =_sbss ldr r3, =_ebss mov r4, #0 b LoopFillZerobssFillZerobss: str r4, [r2], #4LoopFillZerobss: cmp r2, r3 bcc FillZerobss ; 调用main函数 bl main ; 如果main返回,进入无限循环 b .登录后复制
菜鸟下载发布此文仅为传递信息,不代表菜鸟下载认同其观点或证实其描述。
版权投诉请发邮件到 cn486com#outlook.com (把#改成@),我们会尽快处理
Copyright © 2019-2020 菜鸟下载(www.cn486.com).All Reserved | 备案号:湘ICP备2023003002号-8
本站资源均收集整理于互联网,其著作权归原作者所有,如有侵犯你的版权,请来信告知,我们将及时下架删除相应资源