打印

MDK4.6环境下STM32F10xxxx.S一段一段看

[复制链接]
8455|79
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
明月小厨|  楼主 | 2013-1-2 14:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
通常在建立一个新的工程时都要遇到启动代码;好象不添加启动代码的话,后面很多工作没法完成;当然牛人例外;
启动代码都完成了些什么?要注意什么?真的不清楚;
对STM32F10X的启动代码有三个,分别对应,ld,md,hd;我现在手头用的是md,以后要用hd的;不过大同小异;
看看启动代码都干了什么?(需要懂一点点汇编);
如果第一次接触STM32F10X和MDK;这部分内容不适合.直接找个开发板跑跑例程更有成就感;

在后面我会把代码一小段一小段按顺序贴出来;大家共同学习(其实是我向大家学习);

沙发
明月小厨|  楼主 | 2013-1-2 14:38 | 只看该作者
;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
;* File Name          : startup_stm32f10x_md.s
;* Author             : MCD Application Team
;* Version            : V3.5.0
;* Date               : 11-March-2011
;* Description        : STM32F10x Medium Density Devices vector table for MDK-ARM
;*                      toolchain.  
;*                      This module performs:
这是本启动代码系统自动提供的,版本号:V3.5.0

使用特权

评论回复
板凳
明月小厨|  楼主 | 2013-1-2 14:40 | 只看该作者
第一段:
Stack_Size      EQU     0x00000400
AREA    STACK, NOINIT, READWRITE, ALIGN=3

Stack_Mem       SPACE   Stack_Size
__initial_sp

使用特权

评论回复
地板
明月小厨|  楼主 | 2013-1-2 14:44 | 只看该作者
本帖最后由 明月小厨 于 2013-1-3 11:34 编辑

这部分代码是说堆栈;
堆栈大小400;还声明了一个堆栈段,不用初始化,可读写;//一上来就0x400的大堆栈,出手很大方;
ALIGN=3?什么意思?
=1;是单字节对齐(不对齐),=2是2字节对齐;=4是4字节对齐;=8是8字节对齐......
=3?难道是三个字节对齐?请高手解释解释;难道M3的堆栈与众不同?
//后面的高手解释的清楚;这里M3有点不一样;ADS的ARM7是这样处理的;M3是另一种意思;
//这种创新要不得,会搞的人头晕;

使用特权

评论回复
5
明月小厨|  楼主 | 2013-1-2 14:53 | 只看该作者
本帖最后由 明月小厨 于 2013-1-2 14:59 编辑

第二个问题:双堆栈;
M3有二个SP指针,一个是MSP,一个是PSP;应该对应二个堆栈区;启动代码中会处理这些吗?

使用特权

评论回复
6
明月小厨|  楼主 | 2013-1-2 15:26 | 只看该作者
本帖最后由 明月小厨 于 2013-1-3 11:36 编辑

Stack_Mem       SPACE   Stack_Size

//SPACE (%与SPACE 同义) 分配一片连续的字节存储区域并初始化为0
这不是堆栈区吗?怎么又要初始化清零呢?
前一句NOINIT,后一句SPACE;是不是很矛盾?
//这里是另一个堆栈区;双堆栈.但处理方式不太一样,不知道为什么这样搞脑子;

使用特权

评论回复
7
明月小厨|  楼主 | 2013-1-2 15:30 | 只看该作者
Thumb-2汇编伪操作命令集.pdf (130.76 KB)

使用特权

评论回复
8
明月小厨|  楼主 | 2013-1-2 15:31 | 只看该作者
第三章_第二节_thumb2指令集及汇编格式.zip (3.52 MB)

使用特权

评论回复
9
明月小厨|  楼主 | 2013-1-2 15:47 | 只看该作者
Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

使用特权

评论回复
10
明月小厨|  楼主 | 2013-1-2 15:50 | 只看该作者
明月小厨 发表于 2013-1-2 15:47
Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3

Stack         Heap:又冒出来一个堆,长度减半;难道这就算是双堆栈了?

使用特权

评论回复
11
明月小厨|  楼主 | 2013-1-2 16:08 | 只看该作者
                PRESERVE8
                THUMB
//8字节对齐;
//下面指令是THUMB

; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
//上面是RESET段;只读;
//用EXPORT声明了三个全局变量(编译器自己用的)

__Vectors   DCD     __initial_sp                   ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                ......
                DCD     SysTick_Handler            ; SysTick Handler
//上面这一段是系统级别的异常
//DCD是说明给这些标号(异常)分配一段字内存地址,半字对齐;
//相当于C语言中的声明,先声明,再定义并使用它们;

                ; External Interrupts
                DCD     WWDG_IRQHandler         ; Window Watchdog
                ......
                DCD     USBWakeUp_IRQHandler  ; USB Wakeup from suspend
//上面一段是外设的中断;

__Vectors_End
//段结束标志;
__Vectors_Size  EQU  __Vectors_End - __Vectors
//还在这里装模做样搞些加加减减的计算;
//这部分内容主要是为后续的中断处理(异常处理)做准备;声明了一些标号.

使用特权

评论回复
12
明月小厨|  楼主 | 2013-1-2 16:15 | 只看该作者
本帖最后由 明月小厨 于 2013-1-2 16:17 编辑
明月小厨 发表于 2013-1-2 16:08
PRESERVE8
                THUMB
//8字节对齐;


有很多的中断估计都用不上,敢不敢把没有用的部分注释掉啊~~~~~~~~~~~
大牛们可以试试,好象后面还有中断编号的;然后计算对应的入口地址;会不会引起混乱?

使用特权

评论回复
13
明月小厨|  楼主 | 2013-1-2 16:18 | 只看该作者
                AREA    |.text|, CODE, READONLY

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
     IMPORT  __main
     IMPORT  SystemInit
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

使用特权

评论回复
14
明月小厨|  楼主 | 2013-1-2 16:31 | 只看该作者
本帖最后由 明月小厨 于 2013-1-3 11:39 编辑
明月小厨 发表于 2013-1-2 16:18
AREA    |.text|, CODE, READONLY

; Reset handler


PROC表明;Reset_Handler是一个可执行的函数;上电后的复位函数?
IMPORT  __main
IMPORT  SystemInit
这二句是说,有二个符号是在其它文件中定义的,在这里只是导入过来用用;
从名称上看,一个是系统初始化;另一个是__main;
如果你在main函数(用户的C语言主函数)开始执行前没有什么好做的;可以把SystemInit注释掉;
//估计写.S的人自己不小心,SystemInit一直都没有定义它;要不注释掉,要不你自己定义它;不然后面会提示出错;
否则你要自己用C写一个对应的函数,那怕是个空函数;我们通常习惯在C的main函数内完成初始化;所以这里可以直接注释掉;
__main是什么函数?记得好象和操作系统有关系;如果是裸机,是不是也可以咔嚓掉?

使用特权

评论回复
15
明月小厨|  楼主 | 2013-1-2 16:44 | 只看该作者
明月小厨 发表于 2013-1-2 16:18
AREA    |.text|, CODE, READONLY

; Reset handler


[WEAK]
第一次遇上这个词;英文的意思是说弱弱的;
在这里的意思是
Reset_Handler在这里先定义了,如果用户不满意自己可以定义一个,这个版本的自动作废;
和C语言的重载有些象;在这不是重载,直接作废;
后面一堆异常处理都是这样的;大家不用担心重复定义;
这样处理的好处是,有些马大哈只定义自己用到的,用不到的就忘记了;万一进入异常,会是什么结果?  
无论什么结果都不是你想要的;所以这里已经替你考虑到了;           

使用特权

评论回复
16
明月小厨|  楼主 | 2013-1-2 16:48 | 只看该作者
NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
...
                EXPORT  USBWakeUp_IRQHandler       [WEAK]
//前面已经解释过了;一长串的[WEAK]

使用特权

评论回复
17
明月小厨|  楼主 | 2013-1-2 16:51 | 只看该作者
本帖最后由 明月小厨 于 2013-1-3 11:43 编辑

先用了DCD声明这些标号(异常处理函数句柄(入口,地址))
然后用PROC实例化;
B       .
ENDP
//B是跳转到后面指示的位置执行;后面的位置是一个点:(;
//ENDP是说这段处理程序结束;
//我以为这是一个空函数,只执行返回指令;可是,它现在是"B       ."
//有些异常进入后要清理标志的;"B       ."能搞掂它吗?会有什么特殊技能?大家一起思考.
//有谁知道的说一声,在此多谢了;:handshake

使用特权

评论回复
18
明月小厨|  楼主 | 2013-1-2 16:57 | 只看该作者
本帖最后由 明月小厨 于 2013-1-3 11:44 编辑

......
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
......
USBWakeUp_IRQHandler
                B       .
                ENDP
//如果没有猜错,正是上面这一段生成了中断向量表;
//位置已经留出来了;弱弱的中断处理函数也有了;你如果自己重新定义一定也行;
//有兴趣的可以查看编译后生成的代码段,看看这里都是什么?;

使用特权

评论回复
19
明月小厨|  楼主 | 2013-1-2 17:01 | 只看该作者
                ALIGN

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
                 IF      :EF:__MICROLIB           
               
                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
               
                 ELSE
               
                 IMPORT  __use_two_region_memory
                 EXPORT  __user_initial_stackheap
                 
__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

使用特权

评论回复
20
明月小厨|  楼主 | 2013-1-2 17:17 | 只看该作者
LDR     R0, =  Heap_Mem
LDR     R1, =(Stack_Mem + Stack_Size)
LDR     R2, = (Heap_Mem +  Heap_Size)
LDR     R3, = Stack_Mem
BX      LR

//执行了几个伪指令,然后程序执行了返回指令;
//我发现STM8也是这样做的,并不是跳转到main;而是返回到main;
//返回可以从堆栈把程序入口找出来,比较灵活,能实现特技,当然也可能乱跑;其实用处不大,可能是习惯问题.
//而跳转则比较死,固化的单一模式,没有意外;

使用特权

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

本版积分规则

个人签名:爱你一万年

35

主题

1072

帖子

2

粉丝