GBLL THUMBCODE ;设置一个全局逻辑变量 [ {CONFIG} = 16 ;if config==16 这里表示你的目前处于领先地16位编译方式 CONFIG的意义。。? THUMBCODE SETL {TRUE} ;置THUMBCODE为真 CODE32 ;且执行CODE32 | THUMBCODE SETL {FALSE};否则THUMBCODE为假 ] [ THUMBCODE ;如果THUMBCODE为真 CODE32 ;for start-up code for Thumb mode ] |
1.1中断向量表、中断处理
中断向量表
;******************************************************* ;异常向量表 ;******************************************************* b ResetHandler ;复位 b UndefHandler ;未定义 b SWIHandler ;软中断 b PabtHandler ;预取指中止 b DabtHandler ;数据中止 NOP ;空 b IRQHandler ;IRQ b FIQHandler ;FIQ ;******************************************************* ;中断向量表(矢量中断方式) ;*******************************************************
ldr pc , =HandlerEINT0 ldr pc , =HandlerEINT1 ldr pc , =HandlerEINT2 ldr pc , =HandlerEINT3 ldr pc , =HandlerEINT4567 ldr pc , =HandlerTICK b. b. ldr pc , =HandlerZDMA0 ldr pc , =HandlerZDMA1 ldr pc , =HandlerBDMA0 ldr pc , =HandlerBDMA1 ldr pc , =HandlerWDT ldr pc , =HandlerUERR01 b. b. ldr pc , =HandlerTIMER0 ldr pc , =HandlerTIMER1 ldr pc , =HandlerTIMER2 ldr pc , =HandlerTIMER3 ldr pc , =HandlerTIMER4 ldr pc , =HandlerTIMER5 b. b. ldr pc , =HandlerURXD0 ldr pc , =HandlerURXD1 ldr pc , =HandlerIIC ldr pc , =HandlerSIO ldr pc , =HandlerUTXD0 ldr pc , =HandlerUTXD1 b. b. ldr pc , =HandlerRTC b. b. b. b. b. b. b. ldr pc , =HandlerADC b. b. b. b. b. b. b. ldr pc , =EnterPWDN ;掉电模式,引用方法? |
异常矢量:
异常:需要中止指令正常执行的任何情形,如ARM内核产生复位、取指或存储器访问失败、遇到未定义的指令、执行了软件中断指令、出现了一个外部中断。
异常处理:就是出现异常之后对应的一个软件的异常处理程序。每种异常都导致内核进入一种特定的模式,此外可以通过编程改变cpsr,进入任何ARM处理器模式,用户和管理模式是仅有可以不通过异常进入的2种模式。
相关知识:
MACRO、MEND 语法格式: $标号 宏名 $参数1,$参数2,…… 指令序列 MEND MACRO、MEND 伪指令可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码。其中,$标号在宏指令被展开时,标号会被替换为用户定义的符号,宏指令可以使用一个或多个参数,当宏指令被展开时,这些参数被相应的值替换。宏指令的使用方式和功能与子程序有些相似,子程序可以提供模块化的程序设计、节省存储空间并提高运行速度。但在使用子程序结构时需要保护现场,从而增加了系统的开销,因此,在代码较短且需要传递的参数较多时,可以使用宏指令代替子程序。包含在MACRO 和MEND 之间的指令序列称为宏定义体,在宏定义体的第一行应声明宏的原型(包含宏名、所需的参数),然后就可以在汇编程序中通过宏名来调用该指令序列。在源程序被编译时,汇编器将宏调用展开,用宏定义中的指令序列代替程序中的宏调用,并将实际参数的值传递给宏定义中的形式参数。 MACRO、MEND 伪指令可以嵌套使用。 |
在设置各种中断跳转子程序时,使用MACRO定义宏指令来跳转。
Eg1:
;使用MACRO来定义一个宏指令,便用操作 MACRO $HandlerLabel HANDLER $HandleLabel ; HandlerLabel是标号 HANDLER是宏指令名 ; 第二个HandlerLabel是参数 $HandlerLabel ;标号 sub sp,sp,#4 ;sp=sp-4 ;decrement sp(to store jump address)储存跳转地址 stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address) ;只用到了r0,所以只保存r0 ldr r0,=$HandleLabel ;参数 ;load the address of HandleXXX to r0 ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX str r0,[sp,#4];在这里,把跳转地址放在堆栈里 ;store the contents(ISR) of HandleXXX to stack ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR) MEND |
Eg2:
MACRO $Label HANDLER $Vector $Label sub lr, lr, #4 ;lr为r14,即联接寄存器,这个语句不能适应所有异常处理,只能应用于FIQ,IRQ,预取指中止。 stmfd sp!, {r0-r3, lr} ;在sp后使用!,表示SP的值也随着更新 ldr r0, =$Vector ldr pc, [r0] ldmfd sp!, {r0-r3, pc}^ MEND |
IMPORT 语法格式: IMPORT 标号{[WEAK]} IMPORT 伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中。标号在程序中区分大小写,[WEAK]选项表示当所有的源文件都没有定义这样一个标号时,编译器也不给出错误信息,在多数情况下将该标号置为0,若该标号为B 或BL 指令引用,则将B 或BL指令置为NOP 操作。 使用示例: AREA Init,CODE,READONLY IMPORT Main ;通知编译器当前文件要引用标号Main,但Main 在其他源文件中 定义 …… END |
矢量处理
;******************************************************* ;异常模式处理 ;******************************************************* UndefHandler HANDLER UndefHandle ;调用HANDLER的宏指令,使程序 ;跳转到UnderfHandle这个地址运 SWIHandler HANDLER SWIHandle ;行,这个地址会在后面列出的一个 ;表中给出 DabtHandler HANDLER DabtHandle PabtHandler HANDLER PabtHandle IRQHandler HANDLER IRQHandle FIQHandler HANDLER FIQHandle |
中断处理:
同异常处理,也是引用HANDLER。
非矢量中断:
在非矢量中断中判断中断源使用下面的方法:
使用I_ISPR寄存器来判断。
虽然INTPND也能判断哪个中断有请求,但它显示的是所有的中断请求,而I—ISPR只显示产生中断服务的中断源。
IsrIRQ ;using I_ISPR register. sub sp,sp,#4 ;reserved for PC stmfd sp!,{r8-r9} ;IMPORTANT CAUTION ;if I_ISPC isn't used properly, I_ISPR can be 0 in this routine. ldr r9,=I_ISPR ldr r9,[r9] ;装载I_ISPR mov r8,#0x0 ;把r8做为偏移地址量 0 ;局部标号 movs r9,r9,lsr #1 ;r9每次左移,且更新CPRS bcs %F1 ;当r9有1时,向下找1 add r8,r8,#4 ;没有则r8+4 b %B0 ;向上找0 1 ldr r9,=HandleADC add r9,r9,r8 ldr r9,[r9] str r9,[sp,#8] ldmfd sp!,{r8-r9,pc} |