ATIME

main函数从哪来?

了解C语言的小伙伴,一定会好奇为什么编程都会从main函数开始执行。相信很多学过的人都只是知道一个程序是从main函数这个入口进入的,但main函数又是从哪里来的呢?
对于在电脑上编程,如在windows/Linux上,main函数是由操作系统调用的,main函数完成后,会给操作系统返回值。
对于最简单的嵌入式程序,CPU从上电开始,需要执行以下步骤:
  1. 从启动文件的代码开始执行程序。
  2. 启动代码跳转到main函数
  3. main函数结束后返回启动文件也就是说,main函数是由人为设定的,并不一定要叫做main函数。
启动文件:
因进入main函数后程序是以C语言编写,C语言中的函数实现需要出入栈,因此启动文件在跳转到main函数前需要先设置栈。完成栈的设置后,启动文件会做一些硬件方面的初始化工作,如内存的初始化。下面将以之前的代码为例进行讲解:
随后调用main函数,设置main函数的返回地址。
main函数返回后,启动文件还会进行一些清理工作。
@******************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************       
   
.extern     main
.text 
.global _start 
_start:
Reset:                  
    ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
    bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
    // bl是位置无关码,相当于:PCnew = PC + 偏移
    //                         PCnew = (4+8) + 0x28 = 0x34
    
    //ldr pc, =disable_watch_dog  /* 这样写将出错 */
    
    bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK
    bl  memsetup            @ 设置存储控制器以使用SDRAM
    bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
    ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
on_sdram:
    ldr sp, =0x34000000     @ 设置栈指针
    ldr lr, =halt_loop      @ 设置返回地址
    ldr pc, =main           @ 调用main函数
halt_loop:
    b   halt_loop
这里以SDRAM程序的启动文件为例,程序流程如下:
  1. 关闭看门狗,否则程序会不断重启。
  2. 初始化SDRAM,然后将程序拷贝到SDRAM中执行。
  3. 设置栈指针。
  4. 跳转到main函数。
  5. 设置main函数返回后进入一个死循环,防止程序跑飞。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注