;******************************************************************************
;
; The NMI handler.
;
;******************************************************************************
NmiSR
if :def:_ENABLE_MOSCFAIL_HANDLER
;
; Grab the fault frame from the stack (the stack will be cleared by the
; processor initialization that follows).
;
ldm sp, {r4-r11}
mov r12, lr
;
; Initialize the processor.
;
bl ProcessorInit
;
; Branch to the SRAM copy of the NMI handler.
;
ldr pc, =NmiSR_In_SRAM
else
;
; Loop forever since there is nothing that we can do about a NMI.
;
b .
endif
;******************************************************************************
;
; The hard fault handler.
;
;******************************************************************************
FaultISR
;
; Loop forever since there is nothing that we can do about a hard fault.
;
b .
;******************************************************************************
;
; The update handler, which gets called when the application would like to
; start an update.
; 升级服务函数,当应用程序想要开始升级时,调用这个函数.
;
;******************************************************************************
UpdateHandler
;
; Initialize the processor. 初始化处理器
;
bl ProcessorInit ;调用子程序
;
; Branch to the SRAM copy of the update handler.
;
ldr pc, =UpdateHandler_In_SRAM
;******************************************************************************
;
; This portion of the file goes into the text section.
;
;******************************************************************************
align 4
area ||.text||, code, readonly, align=2
Reset_Handler_In_SRAM
;
; Call the user-supplied low level hardware initialization function
; if provided.
; 如果用户提供了底层硬件初始化函数,则调用这个函数
;
if :def:_BL_HW_INIT_FN_HOOK
import $_BL_HW_INIT_FN_HOOK
bl $_BL_HW_INIT_FN_HOOK
endif
;
; See if an update should be performed.
; 检查是否有升级请求
;
import CheckForceUpdate
bl CheckForceUpdate
cbz r0, CallApplication ;结果为零则转移(只能跳到下一行)
;
; Configure the microcontroller.
;
EnterBootLoader
if :def:_ENET_ENABLE_UPDATE
import ConfigureEnet
bl ConfigureEnet
elif :def:_CAN_ENABLE_UPDATE
import ConfigureCAN
bl ConfigureCAN
elif :def:_USB_ENABLE_UPDATE
import ConfigureUSB
bl ConfigureUSB
else
import ConfigureDevice
bl ConfigureDevice
endif
;
; Call the user-supplied initialization function if provided.
; 如果用户提供了初始化函数,则调用.
;
if :def:_BL_INIT_FN_HOOK
import $_BL_INIT_FN_HOOK
bl $_BL_INIT_FN_HOOK
endif
;
; Branch to the update handler.
; 进入升级处理程序
;
if :def:_ENET_ENABLE_UPDATE
import UpdateBOOTP
b UpdateBOOTP
elif :def:_CAN_ENABLE_UPDATE
import UpdaterCAN
b UpdaterCAN
elif :def:_USB_ENABLE_UPDATE
import UpdaterUSB
b UpdaterUSB
else
import Updater
b Updater
endif
;
; This is a second symbol to allow starting the application from the boot
; loader the linker may not like the perceived jump.
;
export StartApplication
StartApplication
;
; Call the application via the reset handler in its vector table. Load the
; address of the application vector table.
;
CallApplication
;
; Copy the application's vector table to the target address if necessary.
; Note that incorrect boot loader configuration could cause this to
; corrupt the code! Setting VTABLE_START_ADDRESS to 0x20000000 (the start
; of SRAM) is safe since this will use the same memory that the boot loader
; already uses for its vector table. Great care will have to be taken if
; other addresses are to be used.
; 如果必要的话,复制应用程序的向量表到目标地址.
; 请注意,不正确的boot loader配置会破坏整个程序!设置VTABLE_START_ADDRESS为
; 0x2000 0000(从SRAM启动)也是可以的,因为这将和boot loader使用同样的内存
;
if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS) ;看应用程序的起始地址是否和应用程序的向量表存储地址相同
movw r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw r1, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt r1, #(_APP_START_ADDRESS >> 16)
endif
;
; Calculate the end address of the vector table assuming that it has the
; maximum possible number of vectors. We don't know how many the app has
; populated so this is the safest approach though it may copy some non
; vector data if the app table is smaller than the maximum.
; 计算向量表的结束地址,假设向量表有最大数目. 我们不知道应用程序使用了多少
; 向量表,但这样是最安全的
;
movw r2, #(70 * 4)
adds r2, r2, r0
VectorCopyLoop
ldr r3, [r1], #4
str r3, [r0], #4
cmp r0, r2
blt VectorCopyLoop
endif
;
; Set the vector table address to the beginning of the application.
; 将向量表重定位到应用程序开始处
;
movw r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw r1, #(NVIC_VTABLE & 0xffff) ;向量表偏移寄存器
movt r1, #(NVIC_VTABLE >> 16)
str r0, [r1]
;
; Load the stack pointer from the application's vector table.
; 从应用程序向量表装载用户堆栈.
;
if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
movw r0, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt r0, #(_APP_START_ADDRESS >> 16)
endif
endif
ldr sp, [r0]
;
; Load the initial PC from the application's vector table and branch to
; the application's entry point.
;
ldr r0, [r0, #4]
bx r0
;******************************************************************************
;
; The update handler, which gets called when the application would like to
; start an update.
; 升级处理函数,当用户程序想要开始升级时,调用此函数
;
;******************************************************************************
UpdateHandler_In_SRAM
;
; Load the stack pointer from the vector table.
; 从boot loader向量表中装载堆栈指针
;
if :def:_FLASH_PATCH_COMPATIBLE
movs r0, #0x1000
else
movs r0, #0x0000
endif
ldr sp, [r0]
;
; Call the user-supplied low level hardware initialization function
; if provided.
; 调用用户提供的底层硬件初始化函数
;
if :def:_BL_HW_INIT_FN_HOOK
bl $_BL_HW_INIT_FN_HOOK
endif
;
; Call the user-supplied re-initialization function if provided.
; 调用用户提供的初始化函数
;
if :def:_BL_REINIT_FN_HOOK
import $_BL_REINIT_FN_HOOK
bl $_BL_REINIT_FN_HOOK
endif
;
; Branch to the update handler.
; 进入升级例程
;
if :def:_ENET_ENABLE_UPDATE
b UpdateBOOTP ;在bl_enet.c中
elif :def:_CAN_ENABLE_UPDATE
import AppUpdaterCAN
b AppUpdaterCAN
elif :def:_USB_ENABLE_UPDATE
import AppUpdaterUSB
b AppUpdaterUSB
else
b Updater
endif
;******************************************************************************
;
; The NMI handler.
; NMI异常服务例程,处理主振荡器失败
;
;******************************************************************************
if :def:_ENABLE_MOSCFAIL_HANDLER
NmiSR_In_SRAM
;
; Restore the stack frame.
;
mov lr, r12
stm sp, {r4-r11}
;
; Save the link register.
;
mov r9, lr
;
; Call the user-supplied low level hardware initialization function
; if provided.
;
if :def:_BL_HW_INIT_FN_HOOK
bl _BL_HW_INIT_FN_HOOK
endif
;
; See if an update should be performed.
;
bl CheckForceUpdate
cbz r0, EnterApplication
;
; Clear the MOSCFAIL bit in RESC.
;
movw r0, #(SYSCTL_RESC & 0xffff)
movt r0, #(SYSCTL_RESC >> 16)
ldr r1, [r0]
bic r1, r1, #SYSCTL_RESC_MOSCFAIL
str r1, [r0]
;
; Fix up the PC on the stack so that the boot pin check is bypassed
; (since it has already been performed).
;
ldr r0, =EnterBootLoader
bic r0, #0x00000001
str r0, [sp, #0x18]
;
; Return from the NMI handler. This will then start execution of the
; boot loader.
;
bx r9
;
; Restore the link register.
;
EnterApplication
mov lr, r9
;
; Copy the application's vector table to the target address if necessary.
; Note that incorrect boot loader configuration could cause this to
; corrupt the code! Setting VTABLE_START_ADDRESS to 0x20000000 (the start
; of SRAM) is safe since this will use the same memory that the boot loader
; already uses for its vector table. Great care will have to be taken if
; other addresses are to be used.
;
if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
movw r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw r1, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt r1, #(_APP_START_ADDRESS >> 16)
endif
;
; Calculate the end address of the vector table assuming that it has the
; maximum possible number of vectors. We don't know how many the app has
; populated so this is the safest approach though it may copy some non
; vector data if the app table is smaller than the maximum.
;
movw r2, #(70 * 4)
adds r2, r2, r0
VectorCopyLoop2
ldr r3, [r1], #4
str r3, [r0], #4
cmp r0, r2
blt VectorCopyLoop2
endif
;
; Set the application's vector table start address. Typically this is the
; application start address but in some cases an application may relocate
; this so we can't assume that these two addresses are equal.
;
movw r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw r1, #(NVIC_VTABLE & 0xffff)
movt r1, #(NVIC_VTABLE >> 16)
str r0, [r1]
;
; Remove the NMI stack frame from the boot loader's stack.
;
ldmia sp, {r4-r11}
;
; Get the application's stack pointer.
;
if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
movw r0, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt r0, #(_APP_START_ADDRESS >> 16)
endif
endif
ldr sp, [r0, #0x00]
;
; Fix up the NMI stack frame's return address to be the reset handler of
; the application.
;
ldr r10, [r0, #0x04]
bic r10, #0x00000001
;
; Store the NMI stack frame onto the application's stack.
;
stmdb sp!, {r4-r11}
;
; Branch to the application's NMI handler.
;
ldr r0, [r0, #0x08]
bx r0
endif
;******************************************************************************
;
; The default interrupt handler.
;
;******************************************************************************
IntDefaultHandler
;
; Loop forever since there is nothing that we can do about an unexpected
; interrupt.
;
b .
;******************************************************************************
;
; Provides a small delay. The loop below takes 3 cycles/loop.
; 提供一个小的延时函数. 循环一次需要3个时钟周期.
;
;******************************************************************************
export Delay
Delay
subs r0, #1
bne Delay
bx lr
;******************************************************************************
;
; This is the end of the file.
;
;******************************************************************************
align 4
end