精华内容
下载资源
问答
  • 单片机启动流程分析

    2020-11-07 14:40:28
    单片机启动流程概述 单片机上电后一直到准备好C语言运行环境并跳转到main函数执行总共经历了5个步骤: 1.内核初始化; 2.强制PC指针指向中断向量表的复位中断向量执行复位中断函数; 3.在复位中断函数中调用 ...

    一 单片机启动流程概述

    单片机上电后一直到准备好C语言运行环境并跳转到main函数执行总共经历了5个步骤:
    1.内核初始化;
    2.强制PC指针指向中断向量表的复位中断向量执行复位中断函数;
    3.在复位中断函数中调用 SystemInit 函数,初始化时钟,配置中断向量表等
    4.调用 __main 函数完成全局/静态变量的初始化和重定位工作,初始化堆栈和库函数
    5.跳转到main函数中执行

    二 内核初始化

    在单片机上电后首先会进行一系列内核的初始化,关于这部分工作我们只需要了解即可,在内核初始化的过程中主要做了以下几件事情:

    1.内核复位和NVIC寄存器部分清零;
    2.内核设置堆栈:内核从向量表0地址读出堆栈地址,并设置主堆栈指针(SP_main);
    3.设置PC和LR寄存器
    a. LR设置未初始复位值0xFFFF FFFF
    b. 单片机的内部硬件机制自动将PC指针定位到中断向量表的复位中断向量出,把复位中断函数Reset_Handler的地址赋值给PC指针,然后跳转执行Reset_Handler。

    三 复位中断函数 Reset_Handler

    在内核复位的最后一步,将PC指针指向了复位中断向量,而复位中断服务函数中的内容才是我们真正需要关心的内容。查看IAR环境中的* .s 单片机汇编启动文件有以下一段内容:

    Reset_Handler    PROC
                     EXPORT  Reset_Handler             [WEAK]
         IMPORT  __main
         IMPORT  SystemInit
                     LDR     R0, =SystemInit  ;加载SystemInit的地址到寄存器R0中
                     BLX     R0               ;跳转R0中的地址执行(执行SystemInit函数)
                     LDR     R0, =__main      ;加载SystemInit的地址到寄存器R0中
                     BX      R0               ;跳转R0中的地址执行(执行__main函数)
                     ENDP
    

    上面的代码就是Reset_Handler的中断服务函数,可以看到在服务中断函数中先使用 IMPORT声明了两个函数 __mainSystemInit,然后顺序跳转执行SystemInit和**__main**函数。下面我们再来了解一下这两个函数具体干了些什么事情:
    SystemInit 函数:

    在system_stm32f4xx.c文件中我们可以看到该函数的定义,该函数主要干了以下两件事情:
    1.初始化时钟:SYSCLK,HCLK,PCLK2 and PCLK1 prescalers
    2.配置中断向量表:中断向量表的定位是在 Flash 还是 SRAM,是否需要偏移)
    注意:可以通过system_stm32f4xx文件中的宏定义修改系统时钟频率(通过设置锁相环的相关系数),中断向量表的地址(位于SRAM还是Flsah,是否偏移,偏移地址多少等参数)

    __main()函数(在IAR中是 __iar_program_start ):

    该函数被封装进了编译器的库中,所以不同的IDE该函数的名称有所区别,但所实现的功能大致类似:

    1.完成全局变量/静态变量/常量的初始化和重定位工作:
    a. 跳转进入__scatterload_rt2函数:通过设置四个寄存器来配置待copy内容(静态变量、全局变量、常量)的的加载域和运行域,设置待copy内容的大小,为后续__scatterload_cpy()函数服务。
    b. 跳转进入__scatterload_cpy函数,完成静态变量、全局变量、常量的从flash到SRAM的重定位。
    c. 跳转进入__scatterload_zeroinit函数,完成未初始化的全局变量的初始化。

    2.初始化堆栈(这里指程序栈)和库函数:
    跳转进入__user_steup_stackheap函数:调用**__user_libspac__user_libspace**为C库保持了静态数据。这是一个96字节,0初始化的数据块,该块由C库创建。在C库初始化期间可以用来当做临时栈。再调用 __user_initial_stackheap 用户的初始化堆栈函数,实现用户的堆栈的配置,调用 _fp_init 和 __rt_fp_status_addr (C库函数) 两个函数调用实现浮点运算的支持。

    3.程序的跳转,进入main()函数:
    跳转进入用户的main函数

    注意:

    1. 未初始化和初始值为零的全局变量,静态变量一般在RAM中, 初始值不为零的全局变量/静态变量 一般在FLASH中。
    2. 因为Flash不能随机写(只能写0,不能写1),所以一般会在程序运行之前将初始值不为零的全局变量重定位到RAM中。
    3. 全局变量和常量的地址在编译时都已经被分配好了(所以能够在 .map 文件中看到), 而局部变量则是程序运行时在栈中创建的,栈空间大小可以在IDE中设置。
    4. 单片机启动时,不需要用将代码从ROM搬移到RAM ,而 ARM 则需要。单片机程序执行的过程分三个步骤:取执行->分析指令->执行指令。取指令的任务是:根据 PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从 RAM 存取相关数据。要知道RAM取数的速度是远高于ROM的,但是单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。而ARM不同,CPU运行的频率高,远大于从 ROM读写的速度,所以一般有大型的操作系统时,都需要将代码部分拷贝到RAM中再执行。
    展开全文
  • 单片机启动文件简介

    2019-11-16 12:58:00
    单片机启动文件简介 初始化堆栈指针SP 初始化程序计数器指针PC 设置堆、栈的大小 设置异常向量表的入口地址 配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM) 设置C库的分支...

    单片机启动文件简介

    • 初始化堆栈指针SP

    • 初始化程序计数器指针PC

    • 设置堆、栈的大小

    • 设置异常向量表的入口地址

    • 配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM)

    • 设置C库的分支入口__main(最终用来调用main函数)

    特殊中断

    PendSV
    定义:可悬起异常,如果我们把它配置为最低优先级,那么如果同时有多个异常被触发,他会再其他异常执行完毕后再执行,而且任何异常都可以打断它。
    PendSV典型使用场合是上下文切换时(在不同任务之间切换)上下文切换被触发的场合可以是: (1):执行一个系统调用。 比如 OSSched(); // 执行任务调用。 (2):系统滴答定时器(SYSTICK)中断,(轮转调度中需要)。
    SVCall
    简述:一种由程序进行触发的中断,默认开启
    起源:SVC(系统服务调用,亦简称系统调用)多用于在操作系统之上的软件开发中。SVC 用于产生系统函数的调用请求。例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个 SVC 异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。
    用途:可以通过设置,使得一段代码能够被某些中断打断,而不能被另外一些中断打断,比如可用于确保模拟IIC的时序不被打断而造成通信失败
    注意: SVC 异常是必须立即得到响应的(若因优先级不比当前正处理的高,或是其它原因使之无法立即 响应,将引发HardFault) 主从优先级等等概念和普通中断相同(且地位相同,即该特殊中断其实也不特殊)//祝:默认情况下,除HardFault和NMI,其它中断的优先级均为0,0(附加提醒,group设置需先于priority设置)

    B与BL

    1. b与bl指令的作用是什么?

       实现程序跳转,也就是调用子程序。
      
    2. b与bl指令的区别是什么?

      b指令:简单的程序跳转,跳转到到目标标号处执行。
      bl指令:带链接程序跳转,也就是要带返回地址。在发生跳转前,将当前PC-4保存到R14中。 也就是返回地址存在R14中,所以可以在子程序返回时只要MOV PC, LR即可。
      
    3. b与bl指令分别如何使用?使用时注意事项有哪些?举例说明。

         b . ;死循环。"."--表示当前地址。
         b reset ;跳入reset处理程序
         bl label ;跳入label函数,同时将当前PC-4保存到R14中
      

    BX、BLX、BXJ
    BX:跳转并切换指令集。
    BLX:带链接跳转并切换指令集。
    BXJ:跳转并转换为 Jazelle 执行。

    常用汇编

    1、EQU(Equate)
    一般格式为: 标号: EQU 操作数 指令功能为将操作数赋予标号,两边的值完全相等。使用EQU伪指令给一个标号赋值后,此标号在整个源文件中值固定。 AREA: EQU 1000H ;将标号AREA赋值为1000H
    2、ORG(Origin)
    一般格式为: ORG xxxxH(绝对地址或标号) XxxxH决定此语句后第一条指令(或数据)的地址。该段源程序或数据被连续存放在此后的地址内,直到下一条ORG指令为止。 ORG 8000H ;此后目标代码存储在存储器中以0x8000h开始的地址空间中。 ADD R1,#1 MOV R2,#2
    3、DB(Define Byte)
    一般格式为:标号:DB 字节常数或字符或表达式 标号字段可有可无,字节常数或字符是指一个字节数据。此伪指令的功能是把字节常数或字节串存放至内存连续的地址空间中。 ORG 8000H DATA1:DB 43H,09H,08H DATA2:DB 07H 伪指令DB指定了43H,09H,08H 顺序存放在8000H开始的存储单元中,DATA2中的07H紧挨着DATA1的地址空间存放,即07H存放在8003H单元中。 注:DW(Define Word)指令定义与DB类似,区别在于DW定义一个字,DB定义一个字节。
    4、END
    一般格式为:标号:END 地址或标号 地址或标号可以忽略。此伪指令用于指示汇编语言程序段结束。因此一个源程序中仅有一个END,且一般放在程序最后。若END放在程序中间,则END后面的语句将不再被汇编。
    5、AREA
    一般格式为:标号 sectionname{,attr}{,attr}…… Sectionname指定节的名称。节是不可分的已命名独立代码模块或数据模块,由连接器进行处理。 Attr则是一个或多个用逗号分隔的节的属性。
    6、PUBLIC
    一般格式为:PUBLIC 标识符1,标识符2…… 在开发较为复杂的应用程序时,其执行文件的生成一般由多个目标文件链接而成。多个目标文件之间一般存在数据交互,汇编语言中通过伪指令PUBLIC及EXTRN来解决模块之间的联系。PUBLIC用来说明当前模块中可被其他模块所引用的公共标识符。 PUBLIC _STARTUP 声明标识符_STARTUP可被其他模块所引用。
    7、EXTRN或EXTERN
    一般格式为:EXTRN 标识符1:类型1,标识符2:类型2……. 表明标识符1、2是外部标识符,其已经在其他模块中被定义为类型1、类型2等。在一个模块中,可用多条EXTRN来说明本模块中所引用的外部标识符。实质为汇编器提供一个并未在当前汇编文件中定义的名称。 注:EXTRN所声明的标识符必须在其定义的模块中被PUBLIC声明为公共标识符,且声明的标识符类型需与该标识符定义类型一致。 类似:EXPORT或GLOBAL 声明一个符号,链接器可以使用此符号解析不同对象和库文件中的符号引用。即,可使其他文件中的代码能够访问当前文件中的符号。
    8、PROC
    一般格式为:<过程名> PROC [类型] 此指令为过程定义指令。过程即子程序,一个过程可以被其他程序调用(CALL指令)。 <过程名> PROC [类型] ……. ……. ENDP 注: PROC和ENDP必须成对出现。
    9、SPACE
    一般格式为:标号 SPACE 表达式 此指令用于分配一片连续的存储区域并初始化为0。表达式为要分配的字节数。SPACE可用“%”来代替。 DataSpace SPACE 1000 ;分配连续1000个字节的存储单元DataSpace并初始化为0。
    10、ENTRY
    此指令用于声明程序的入口点。一个程序至少有一个入口点。 AREA TEST, CODE, READONLY ENTRY ;程序入口点。
    11、PRESERVE8
    一般格式为:PRESERVE8 {bool} PRESERVE8指令指定当前文件需保持堆栈八字节对齐方式。其通过设置PRES8编译属性通知连接器。 PRESERVE8 ;保持代码堆栈八字节对齐。 PRESERVE8 {FALSE} ;不保持代码堆栈八字节对齐。
    12、CODE16、CODE32
    一般格式为:CODE16(或CODE32) CODE16通知编译器,其后的指令序列为16位的Thumb指令。 CODE32通知编译器,其后的指令序列为32位的ARM指令。 在实用ARM指令和Thumb指令混合编程的代码里,可使用这两天指令进行切换。注:指令只能通知编译器其后的指令类型,并不能对处理器进行状态的切换。
    13、IMPORT
    此指令类似于EXTERN。用于通知编译器即将使用的标号在其他源文件中定义。无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中。 一般格式为:IMPORT 标号 {[WEAK]} 标号在程序中区分大小写,[WEAK]表示当所有源文件中均找不到此标号时,编译器也不会显示错误信息。 AREA INIT, CODE, READONLY IMPORT Main ;通知编译器当前文件要引用标号Main,但其定义在其他源文件中。
    14、DCD( Data Definition )
    语法格式: 标号 DCD (或 DCDU ) 表达式 DCD (或 DCDU )伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。 DCD 也可用 “ & ” 代替。 用 DCD 分配的字存储单元是字对齐的,而用 DCDU 分配的字存储单元并不严格字对齐。 使用示例: DataTest DCD 4 , 5 , 6 ;分配一片连续的字存储单元并初始化。

    扩充

    • SEV
      多处理器环境中向所有的处理器发送事件(包括自身)。在符合CMSIS的设备驱动库中,可以使用“__SEV()”实现该操作
    • WFE
      等待事件,如果没有之前该事件的记录,进入休眠模式;如果有的话,则清除事件锁存并继续执行;在符合CMSIS的设备驱动库中,可以使用“__WFE()”函数实现该操作,不过若你使用供应商特定的休眠模式,效果会更好

    因为从思维导图到大纲模式的排版真心不咋地,感兴趣的小伙伴可关注公众号,【嵌入式学习之从入门到放弃】获取思维导图版。

    欢迎各位大佬,新手指教。

    展开全文
  • 修改后的51单片机启动汇编文件,仅作参考,慎用。
  • 本文详细介绍STM32单片机启动的过程,既从上电Reset_Handle跳转到main()函数的过程。其中,会着重解释__main的汇编代码 STM32启动过程 1. 从Reset_Handler开始启动 Reset_Handler的代码如下,参考《startup_stm32f10...

    本文详细介绍STM32单片机启动的过程,既从上电Reset_Handle跳转到main()函数的过程。其中,会着重解释__main的汇编代码

    STM32启动过程

    1. 从Reset_Handler开始启动

    Reset_Handler的代码如下,参考《startup_stm32f10x_hd.s》
    在这里插入图片描述
    1-计算SystemInit函数入口地址,并把地址load到R0;
    R0 = [PC + 24] = [0x08000144 + 24 +4] = [0x08000160] = 0x08000495
    从Keil中可查看地址的值
    2 – 执行r0所指向的函数,既 SystemInit();同时,把下一条指令的地址(既PC+4)保存到lr(r14)中
    3 – 计算__main的入口地址,并load到r0
    在这里插入图片描述
    在这里插入图片描述
    4 – 执行__main()

    __main 的执行过程

    • __main函数内容
      在这里插入图片描述
    • SP(R13)赋值
      SP = [pc +12 +4] = [0x08000130 + 12 + 4] = [0x08000140] = 0x20000408
      在这里插入图片描述
    • 执行 __scatterload() (地址0x08000168),并load R14, lr = 0x08000139
      在这里插入图片描述

    __scatterload函数执行过程

    在这里插入图片描述
    在这里插入图片描述

    __scatterload_copy执行过程

    在这里插入图片描述
    在这里插入图片描述

    __scatterload_zeroinit执行过程

    在这里插入图片描述
    在这里插入图片描述

    __main_after_scatterload执行过程

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • STM32F10X单片机启动uCLinux的BootLoader程序,可代替官方发布的BootLoader。仅限于启动基于STM3210E开发板的xipImage内核,并且要去掉内核中的Splash输出。
  • 找了半天才找到的头文件,现在分享给大家,亲测F005单片机可用,其他系列没试过,可以考虑下载试一试。
  • 单片机启动文件

    千次阅读 2018-01-21 18:12:58
    初始化堆栈指针SP 初始化PC指针 初始化中断向量表 配置系统时钟 调用C库函数_main,最终去到C的世界
    • 初始化堆栈指针SP
    • 初始化PC指针
    • 初始化中断向量表
    • 配置系统时钟
    • 调用C库函数_main,最终去到C的世界
    展开全文
  • 51单片机启动代码:STARTUP.A51

    千次阅读 2014-01-18 23:40:06
    通过Keil编译器建立工程时,Keil会提示是否添加STARTUP.A51文件到工程,该文件即为51单片机启动代码。 51单片机复位后马上执行STARTUP.A51文件中的启动代码,根据启动代码中的设置依次执行以下操作: 内部RAM...
  • STM8单片机启动流程彻底探究--基于IAR开发环境
  • 最近在做TI单片机TM4C123GE6PZ的BootLoader,需要对启动文件做出修改,折腾了半宿,弄得事实而非。 IAR默认提供了单片机启动文件,cstart.s或者其他cstartxxx.s,并且已经编译到库文件里面,刚开始尝试修改IAR/...
  • 最近在给公司的ADAS DCU做内存分配(Memory Allocation...3. TC397单片机的Memory Map和一些备注 1. ECU启动流程 图总比文字直观: 如上图所示,上电以后其实就三步: "运行ROM的启动函数 -- 跳转到FLASH里...
  • 单片机启动代码详解

    千次阅读 2015-02-09 20:57:53
    启动代码通常都烧写在flash中,它是系统一上电就执行的一段程序,它运行在任何用户c代码之前。上电后,arm处理器处于arm态,运行于管理模式,同时系统所有中断被禁止,pc到地址0处取指令执行。一个可执行映像文件...
  • 1. 单片机启动,此时数码管不显示,当对应编号的按键按下,则数码管上显示对应按键的键值。 ***
  • Version S Description Date By V1 ...单片机在执行main函数之前,都干了什么呢?...用KEIL学STM32单片机编程的时候,按下其仿真...会发现进入到一个启动文件startup_stm32f10x_md.s,运行指示光标,会停在一个位置...
  • ;/*****************************************************************************; * @file: startup_SKEAZ1284.s; * @purpose: CMSIS Cortex-M0plus Core Device Startup File for the; * SKEAZ128...
  • 启动代码通常都烧写在flash中,它是系统一上电就执行的一段程序,它运行在任何用户c代码之前。上电后,arm处理器处于arm态,运行于管理模式,同时系统所有中断被禁止,pc到地址0处取指令执行。一个可执行映像文件...
  • MODULE ?cstartup ;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start EXTERN S...
  • 启动文件源码如下: ; Amount of memory (in bytes) allocated for Stack ; Tailor this value to your application needs ; <h> Stack Configuration ; <o> Stack Size (in Bytes) <0x0-0...
  • 开头的话: 之前一直用现成的LED工程demo,改改就上,也...一、STM32上电启动 BOOT1 BOOT0 启动方式 X 0 从STM32内置flash启动,JTAG或者SWD固化程序位置 1 1 从STM32内置SRAM启动,由于SRAM没有程序存储能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,997
精华内容 798
关键字:

单片机启动