(出处: OpenEdv-开源电子网)
原子的开发板,用跑马灯程序的工程来改的,DOWNLOAD和DEBUG效果都能跑起来,当然这只是用个简单小程序试试,我也就抛砖引玉,了解MDK启动代码的前辈也来讨论讨论最好。
话说启动代码,没什么神秘的,往简单里说不外乎3个功能部分
1,做个AREA放置向量表,异常/中断跳转的地址表。
2,初始化SP的值,初始化内核的状态(比如工作在用户模式或超级模式,STM启动默认在高权限模式)
3,如果使用的是简单的分散加载,IMAGE(映像文件)也就由1个RO,1个RW,1个ZI组成,并且RO的load region和execution region相同,那么只需要COPY RW区到RAM,然后再RW区后面创建ZI区,只部分可以用汇编代码自己实现。当然库里的__main函数就包含这些功能,但是如果不用__main,那就要自己写这部分了。
何为简单的分散加载?
MDK的HELP文档里有很详细的说明。
首先编译器设置要改
要是勾了,编译器要报错,问你启动库函数找不到。
勾了就是使用默认的分散加载描述文本,.SCT文件是不让改的,所以想改就不要勾。
贴上启动代码,我用红字做解释,后面有附近下载的。
IMPORT |Image$$ER_IROM1$$RO$$Base|
IMPORT |Image$$ER_IROM1$$RO$$Limit|
IMPORT |Image$$RW_IRAM1$$RW$$Base|
IMPORT |Image$$RW_IRAM1$$RW$$Limit|
IMPORT |Image$$RW_IRAM1$$ZI$$Base|
IMPORT |Image$$RW_IRAM1$$ZI$$Limit|
上面这几个符号并不神秘,他们是编译器根据分散加载描述文本产生的全局标号,在.MAP文件里能找到他们对应的值,因此我们可以用IMPORT来引用他们,注意名字不能乱起,这个是根据你的.SCT文件产生的标号
LR_IROM1 0x08000000 0x00020000 { ; load region size_region
ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
* (+RO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
* (+RW +ZI)
}
}
这就是我的.SCT文本 记得MDK原.SCT文本里含有 *(InRoot$$Sections) 一定要删掉 这个是根段,有很多启动库函数包在里面的
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, CODE, READONLY
Vectors DCD 0x20005000 ; Top of Stack 我就直接赋值给SP了
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMAChannel1_IRQHandler ; DMA Channel 1
DCD DMAChannel2_IRQHandler ; DMA Channel 2
DCD DMAChannel3_IRQHandler ; DMA Channel 3
DCD DMAChannel4_IRQHandler ; DMA Channel 4
DCD DMAChannel5_IRQHandler ; DMA Channel 5
DCD DMAChannel6_IRQHandler ; DMA Channel 6
DCD DMAChannel7_IRQHandler ; DMA Channel 7
DCD ADC_IRQHandler ; ADC
DCD USB_HP_CAN_TX_IRQHandler ; USB High Priority or CAN TX
DCD USB_LP_CAN_RX0_IRQHandler ; USB Low Priority or CAN RX0
DCD CAN_RX1_IRQHandler ; CAN RX1
DCD CAN_SCE_IRQHandler ; CAN SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT main
LDR r0, =|Image$$ER_IROM1$$RO$$Limit|
LDR r1, =|Image$$RW_IRAM1$$RW$$Base|
LDR r3, =|Image$$RW_IRAM1$$ZI$$Base|
Init_RW
CMP r1, r3
LDRCC r2, [r0],#4
STRCC r2, [r1],#4
BCC Init_RW
LDR r1, =|Image$$RW_IRAM1$$ZI$$Limit|
MOV r2, #0
Init_ZI
CMP r3, r1
STRCC r2, [r3],#4
BCC Init_ZI
上面的粗体就是自己写的 COPY RW区和创建ZI区的汇编代码,其实是我从ADS1.2下的S3C44B0X启动程序改过来的,大体不变,
那几个标号
=|Image$$ER_IROM1$$RO$$Limit|
=|Image$$RW_IRAM1$$RW$$Base|
=|Image$$RW_IRAM1$$ZI$$Base|
=|Image$$RW_IRAM1$$ZI$$Limit|
是什么意思,怎么用?这个我就不多解释了吧,.MAP文件里有他们的真相,HELP文档里也有他们的详细解释。
LDR R0, =main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC
EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMPER_IRQHandler [WEAK]
EXPORT RTC_IRQHandler [WEAK]
EXPORT FLASH_IRQHandler [WEAK]
EXPORT RCC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMAChannel1_IRQHandler [WEAK]
EXPORT DMAChannel2_IRQHandler [WEAK]
EXPORT DMAChannel3_IRQHandler [WEAK]
EXPORT DMAChannel4_IRQHandler [WEAK]
EXPORT DMAChannel5_IRQHandler [WEAK]
EXPORT DMAChannel6_IRQHandler [WEAK]
EXPORT DMAChannel7_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT USB_HP_CAN_TX_IRQHandler [WEAK]
EXPORT USB_LP_CAN_RX0_IRQHandler [WEAK]
EXPORT CAN_RX1_IRQHandler [WEAK]
EXPORT CAN_SCE_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM1_BRK_IRQHandler [WEAK]
EXPORT TIM1_UP_IRQHandler [WEAK]
EXPORT TIM1_TRG_COM_IRQHandler [WEAK]
EXPORT TIM1_CC_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK]
EXPORT TIM3_IRQHandler [WEAK]
EXPORT TIM4_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK]
EXPORT USART3_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTCAlarm_IRQHandler [WEAK]
EXPORT USBWakeUp_IRQHandler [WEAK]
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMAChannel1_IRQHandler
DMAChannel2_IRQHandler
DMAChannel3_IRQHandler
DMAChannel4_IRQHandler
DMAChannel5_IRQHandler
DMAChannel6_IRQHandler
DMAChannel7_IRQHandler
ADC_IRQHandler
USB_HP_CAN_TX_IRQHandler
USB_LP_CAN_RX0_IRQHandler
CAN_RX1_IRQHandler
CAN_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTCAlarm_IRQHandler
USBWakeUp_IRQHandler
B .
ENDP
ALIGN
END
后面都没什么改动了,删掉了MDK的库函数,总之原版的向量表我是不敢动的
用原子的跑马灯试验试了下,OK,没问题,只是有个小纠结,看看.MAP文件里
MDK啊 你妹的还要坑我96字节啊。