OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3540|回复: 11

stm32的代码为什么从start.s启动运行?程序的真正入口是在哪里指定的?

[复制链接]

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
发表于 2020-4-4 16:38:25 | 显示全部楼层 |阅读模式
10金钱
我们都知道main之前是start.s帮忙配置了堆栈,才能跳到c运行。start.s也做了系统初始化,配置了RWROZI等区。
但是有个问题,
start.s为什么是最早运行的?
程序的真正入口是在哪里指定的?

本来以为链接文件有entry,找了半天没找到ld文件,只找到一个sct文件,也没有相关的入口说明

最佳答案

查看完整内容[请看2#楼]

RESET符号是mdk下的 .s 和 .sct中的, 在iar中的名字可能不一样,但原理一样。
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-4 16:38:26 | 显示全部楼层
ultraelec 发表于 2020-4-4 17:58
1、先看上电运行基本流程
上电后先从0地址获取栈顶
然后从地址:0x0000 0004执行指令。

RESET符号是mdk下的 .s 和 .sct中的,
在iar中的名字可能不一样,但原理一样。
uevip#126.com
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-4 17:58:35 | 显示全部楼层
1、先看上电运行基本流程
上电后先从0地址获取栈顶
然后从地址:0x0000 0004执行指令。

2、结合启动配置与地址映射
假设你配置了boot0/boot1引脚为 x/0,则0x0000 0000映射至Flash地址0x0800 0000
所以,上电先从0x0800 0004执行指令。
而放在0x0800 000的代码就是start.s中的RESET段,即异常向量表(由链接脚本指定)。
最先运行的是异常向量表的复位中断,可以看该代码处会调用SystemInit,然后调用__main,最终进入你的C中的main函数
uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-5 10:12:32 | 显示全部楼层
ultraelec 发表于 2020-4-4 16:38
RESET符号是mdk下的 .s 和 .sct中的,
在iar中的名字可能不一样,但原理一样。

谢了兄弟,在.sct中找到了
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }

意思是RESET段,放最前面。

但是这个.sct文件是MDK自动生成的,MDK又是基于什么配置得知把RESET段放在最前呢?这个是我们配置的,还是MDK自己约定的,用MDK的开发都要把向量表放在RESET段
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-5 12:39:32 | 显示全部楼层
tao475824827 发表于 2020-4-5 10:12
谢了兄弟,在.sct中找到了
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
...

基于啥?当然是基于特定的硬件啊。放在开头是默认行为。
放在开头位置不一定是必须的,但在默认情况下是最合理的。
MDK不会自己拍脑袋随便放,要根据具体硬件。
STM32的一些单片机的硬件行为就是上电取栈顶,然后就执行0x0000 0004 的代码(实际是中断函数地址)。
合理的做法就是将向量表放于此处,从而可以开机能够正确的执行复位中断,做最进本的初始化工作,然后再做其它。
你后边也可以手动将向量表重定位到其他有效位置,但这种情况一般是loader+app多固件的应用会用到。
MDK的sct会根据options for target中的配置而改变的,在你没有确定需求之前不要改。
uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-5 16:40:42 | 显示全部楼层
ultraelec 发表于 2020-4-5 12:39
基于啥?当然是基于特定的硬件啊。放在开头是默认行为。
放在开头位置不一定是必须的,但在默认情况下是 ...

嗯,放在前面是最合理的。因为M3的内核就是去0x0地址找MSP,去0x4找地址跳转。
然后st把0x8000000映射过来。


我们编译的时候声明了RESET段,在sct文件中指明了RESET放最前,

但是我想知道,就是在keil里,sct文件是怎么来的,这个文件我删掉了,下次build会重新生成,可见是keil自己知道,要把RESET这个段放在最前面。
我在配置中找到这一面,并没有关于RESET段的设置,
无标题.png

其他面就再找不到相关sct文件的配置了。

就是RESET放在最前,这是一个约定,还是一个我人为可以改的?比如我在start.s里把这段定为RESET2,也想指定到最前面,有方法吗
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-5 17:15:00 | 显示全部楼层
tao475824827 发表于 2020-4-5 16:40
嗯,放在前面是最合理的。因为M3的内核就是去0x0地址找MSP,去0x4找地址跳转。
然后st把0x8000000映射过 ...

无语,你去掉Use Memory那行选项的√啊!
那不写着用Target Dialog的链接脚本吗,你选中了当然是使用根据Target选项中的生成sct啊!

去掉√,你就可以添加使用自己的.sct了,愿意怎么改就怎么改。
uevip#126.com
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-5 17:20:30 | 显示全部楼层
163817pmhzaazzx6d4uxux.png
uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-5 22:51:27 | 显示全部楼层
ultraelec 发表于 2020-4-5 17:15
无语,你去掉Use Memory那行选项的√啊!
那不写着用Target Dialog的链接脚本吗,你选中了当然是使用根 ...

是的,如果我不去掉√,target选项会帮忙生成一个sct文件,同时在这个sct文件里指定RESET段为first。
为什么要指定“reset”,这个是约定的吗。
因为在option选项卡里,我们有配置RAM和ROM信息,这些被生成到.sct文件里,我能理解。但是我们没有配置RESET信息,没有指明说要把RESET放在最前,但是keil自动生成的RESET被指定了最前。
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2018-9-1
在线时间
178 小时
发表于 2020-4-7 16:08:26 | 显示全部楼层
tao475824827 发表于 2020-4-5 22:51
是的,如果我不去掉√,target选项会帮忙生成一个sct文件,同时在这个sct文件里指定RESET段为first。
为 ...

我觉得吧,你还不如用gcc开发单片机程序,看datasheet,从零开始。
上边已经说了为什么要把向量表放在最前边,你还纠结这些干啥?   
还要我再把已经回复的内容在粘贴过来吗???????????

基于啥?当然是基于特定的硬件啊。放在开头是默认行为。
放在开头位置不一定是必须的,但在默认情况下是最合理的。
MDK不会自己拍脑袋随便放,要根据具体硬件。。。。


你懂不懂啥叫默认行为????

一个汽车,只要驾驶位坐的是个司机就行,车就能开,至于司机叫张三李四没有任何关系。驾驶位正常就应该放个司机,MDK家的司机就叫RESET,默认就把它放在驾驶位。
是不是必须的?答:不是,驾驶位放个死人也可以,可能奇葩目的就是不想让车开动,只想放个人在那个位置就行了。
奇葩目的或者说更高级目的,不在MDK提供的自动服务机制下。

默认情况就是,只要你需要MDK的司机,那MDK就将自家司机放在驾驶位,不提供死人,也不提供改名服务。
没有什么约定,驾驶位放司机,不是MDK跟谁约定的,这是根据车本身决定的。
如果你觉得MDK提供的RESET这位司机驾驶技能差,或者不会漂移,或者仅仅因为名字不符合你口味,
那好,你可以不用,你可以自己弄个叫任何名字的司机都可以。
那你去掉选项不让MDK自动生成 .sct,然后你自己修改或使用自己的.s 和 .sct,随便你怎么弄,向量表定义成什么名字、向量表放不放在开头、放在哪随你便呀。

懂得启动原理就可以了,你还这些钻牛角尖有啥用。
你没指定的东西多了,你指定makefile了吗?
.s 是你自己写的吗?__main是你写的吗?编译选项都是你指定的吗?




uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-7 17:34:44 | 显示全部楼层
ultraelec 发表于 2020-4-7 16:08
我觉得吧,你还不如用gcc开发单片机程序,看datasheet,从零开始。
上边已经说了为什么要把向量表放在最 ...

哈哈,懂了,谢谢,例子很生动。
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-7 17:36:29 | 显示全部楼层
ultraelec 发表于 2020-4-7 16:08
我觉得吧,你还不如用gcc开发单片机程序,看datasheet,从零开始。
上边已经说了为什么要把向量表放在最 ...

最近是想用gcc来做的,觉得以前用keil,很多东西都被隐藏了,理解的不深入。真正往下想,就会觉得越来越多不懂。因为是自己一个人想的,可能有些地方就想偏了,非常感谢你~
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 01:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表