打印
[牛人杂谈]

MCU在运行到main()之前都干了什么

[复制链接]
1300|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
很多ARM工程师想当然的以为,自己开发的应用程序,用AK100Pro仿真器下载进入调试,MCU的PC指针必定停留在main()函数的入口。但实际上,在运行到main()前,MCU还做了很多事情。这里以一个LPC1700的Keil工程为例说明。

  MCU上电复位后,通常会从一个固定的地址开始启动,比如ARM7复位后的入口地址为0x00000000;或者类似Cortex-M内核从中断向量表中取出入口地址,中断向量表的地址必须是固定的。

  LPC1700为Cortex-M3内核,所以启动时会从中断向量表(地址0x00000000)处取出入口地址和堆栈指针,分别加载到PC和SP中。

  入口地址处通常放的是芯片相关的启动代码。这部分代码要完成很多芯片初始化的动作,由于与特定型号芯片相关,所以不能随随便便地就用到别的型号芯片上。通常我们会使用官方提供的例程,然后以此为基础进行必要的修改。以下是LPC1700的初始化代码,所有硬件相关的初始化操作放在了SystemInit()函数中。


    SystemInit()完成的功能可以有:设置看门狗、外部存储器接口、内核时钟等等。当然,这些代码有些是可以放到后面的main()函数中完成,但有些则必须放在运行到__main之前完成。

  芯片初始化完成后,接下来是执行C运行环境的初始化。C环境的初始化主要包含两点:

  按照分散加载文件的配置,将相应的数据段和代码段拷贝到相关位置,将ZI段清零。通过这个功能可以将C代码中未指定初始化值的全局变量和静态变量对应的内存清零,然后将指定初始化的全局变量和静态变量对应的内存初始化。另外,如果有通过分散加载文件设置代码存储在Flash中,然后自动搬运到RAM中运行(该功能将在后续**中细讲),也会在该阶段完成这个自动搬运工作。

  之后是初始化C库,完成后才跳转到main()。

  所以说,在main()运行前,MCU其实已经做了很多工作了。如果程序下载没有出现问题,但是就是跑不到main(),有可能不是仿真器的问题。是否会是main()之前的初始化操作异常?

沙发
mintspring| | 2016-8-23 13:19 | 只看该作者
一般会有个.s文件,声明系统的内存分布,程序入口,已经最后跳转到main函数的地址指针。

使用特权

评论回复
板凳
zhuomuniao110| | 2016-8-25 21:38 | 只看该作者
我们编写的main其实就只是系统的一个函数而已

使用特权

评论回复
地板
heisexingqisi| | 2016-8-25 22:44 | 只看该作者
https://bbs.21ic.com/icview-1619808-1-1.html
此贴也可以很好的说明这个问题

使用特权

评论回复
5
mintspring| | 2016-8-25 22:58 | 只看该作者

一个是ARM,一个是IAR的,为何还不同大小。

使用特权

评论回复
6
mintspring| | 2016-8-25 23:02 | 只看该作者
__vector_table
    DCD     sfe(CSTACK)
    DCD     __iar_program_start

    DCD     NMI_Handler
    DCD     HardFault_Handler
    DCD     0
    DCD     0
    DCD     0
    DCD     0
    DCD     0
    DCD     0
    DCD     0
    DCD     SVC_Handler
    DCD     0
    DCD     0
    DCD     PendSV_Handler
    DCD     SysTick_Handler

    ; External Interrupts
    DCD     BOD_IRQHandler              ; Brownout low voltage detected interrupt                 
    DCD     WDT_IRQHandler              ; Watch Dog Timer interrupt                              
    DCD     EINT0_IRQHandler            ; External signal interrupt from PB.14 pin               
    DCD     EINT1_IRQHandler            ; External signal interrupt from PB.15 pin               
    DCD     GPIOP0P1_IRQHandler         ; External signal interrupt from P0[15:0] / P1[13:0]     
    DCD     GPIOP2P3P4_IRQHandler       ; External interrupt from P2[15:0]/P3[15:0]/P4[15:0]     
    DCD     PWMA_IRQHandler             ; PWM0 or PWM2 interrupt                                 
    DCD     PWMB_IRQHandler             ; PWM1 or PWM3 interrupt                                 
    DCD     TMR0_IRQHandler             ; Timer 0 interrupt                                      
    DCD     TMR1_IRQHandler             ; Timer 1 interrupt                                      
    DCD     TMR2_IRQHandler             ; Timer 2 interrupt                                      
    DCD     TMR3_IRQHandler             ; Timer 3 interrupt                                      
    DCD     UART0_IRQHandler            ; UART0 interrupt                                       
    DCD     UART1_IRQHandler            ; UART1 interrupt                                       
    DCD     SPI0_IRQHandler             ; SPI0 interrupt                                         
    DCD     SPI1_IRQHandler             ; SPI1 interrupt                                         
    DCD     Default_Handler             ; SPI2 interrupt                                         
    DCD     Default_Handler             ; SPI3 interrupt                                         
    DCD     I2C0_IRQHandler             ; I2C0 interrupt                                         
    DCD     I2C1_IRQHandler             ; I2C1 interrupt                                       
    DCD     Default_Handler             ; Reserved                                       
    DCD     Default_Handler             ; Reserved                                         
    DCD     Default_Handler             ; Reserved
    DCD     Default_Handler             ; Reserved
    DCD     Default_Handler             ; Reserved
    DCD     ACMP01_IRQHandler           ; ACMP0/1 interrupt
    DCD     ACMP23_IRQHandler           ; ACMP2/3 interrupt
    DCD     Default_Handler             ; Reserved
    DCD     PWRWU_IRQHandler            ; Clock controller interrupt for chip wake up from power-
    DCD     ADC_IRQHandler              ; ADC interrupt                                          
    DCD     Default_Handler             ; Reserved
    DCD     RTC_IRQHandler              ; Real time clock interrupt      

使用特权

评论回复
7
734774645| | 2016-8-25 23:28 | 只看该作者
这个到底干了什么交给编译器和系统去做吧

使用特权

评论回复
8
304bloodwar| | 2016-8-26 12:51 | 只看该作者
你也可以自己写启动文件,直接跳转到main而不經過__main

使用特权

评论回复
9
戈卫东| | 2016-8-26 20:44 | 只看该作者
难道是周那里来的高人?

使用特权

评论回复
10
vtech_hosea| | 2016-9-20 08:17 | 只看该作者
新塘的MCU 启动 被简化了好多,keil里面有很多选好的编译链接选项。总之LD文件都不用自己做,连data节区这些都把你固定死了(全部集中在内部ram的最后面)。在ic内部启动。直接统一赋初值。总之是简单的不能再简单了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

236

帖子

4

粉丝