1、ARM 应用系统设计启动代码佘黎煌东北大学信息科学与工程学院电子信息工程研究所0 x0000 00000 xFFFF FFFF用户程序中断服务程序异常向量表1.正在执行用户程序;2.外部中断0发生中断;3.AIC硬件将中断服务程序地址装入AIC_IPER寄存器;4.程序跳转至异常向量表中IRQ入口0 x0018处;5.执行指令跳转至AIC_IPER寄存器中的中断服务地址;6.中断服务程序执行完毕,返回被中断的用户程序继续执行被中断的代码。n图示IRQ中断的发生过程Vector.s(五种异常处理C函数)nAIC_IPEREQU0 xFFF8210C; Interrupt priority enc
2、oding register nAIC_EOSCREQU0 xFFF82130; End of service command register nIMPORTReset_Handler;init.snIMPORT Undefined_HandlernIMPORTSWI_HandlernIMPORTPrefetch_Handler nIMPORTAbort_HandlerVector.s (中断处理C函数)n nIMPORTWDT_Handler; Watch Dog Timer InterruptnIMPORTnIRQ0_Handler; External Interrupt 0nIMPOR
3、TnIRQ1_Handler; External Interrupt 1nIMPORTnIRQ2_Handler; External Interrupt 2nIMPORTnIRQ3_Handler; External Interrupt 3nIMPORTAC97_Handler; AC97 InterruptnIMPORTLCD_Handler; LCD Controller InterruptnIMPORTRTC_Handler; RTC Controller InterruptnIMPORTUART0_Handler; UART 0 InterruptnIMPORTUART1_Handle
4、r; UART 1 InterruptnIMPORTUART2_Handler; UART 2 InterruptnIMPORTUART3_Handler; UART 3 InterruptnIMPORTTIMER0_Handler; Timer Interrupt 0Vector.s (中断处理C函数)nIMPORTTIMER1_Handler; Timer Interrupt 1nIMPORTUSBH0_Handler; USB Host Interrupt 0nIMPORTUSBH1_Handler; USB Host Interrupt 1nIMPORTEMCTX_Handler; E
5、MC TX InterruptnIMPORTEMCRX_Handler; EMC RX InterruptnIMPORTGDMA0_Handler; GDMA Channel Interrupt 0nIMPORTGDMA1_Handler; GDMA Channel Interrupt 1nIMPORTSDIO_Handler; SDIO InterruptnIMPORTUSBD_Handler; USB Device InterruptnIMPORTSC0_Handler; SmartCard Interrupt 0nIMPORTSC1_Handler; SmartCard Interrup
6、t 1nIMPORTI2C0_Handler; I2C Interrupt 0nIMPORTI2C1_Handler; I2C Interrupt 1nIMPORTSSP_Handler; SPI InterruptnIMPORTPWM_Handler; PWM InterruptnIMPORTKPI_Handler; KPI InterruptnIMPORTPS2_Handler; PS2 InterruptnIMPORTIRQ45_Handler; IRQ45 Interrupt中断向量表的定义(vector.s)nAREA Vect, CODE, READONLYn ENTRYnstar
7、t n BReset_Handlern BUndefined_Addr n BSWI_Addrn BPrefetch_Addrn BAbort_Addrn B. n BIRQ_Addrn BFIQ_Addr异常的处理(vector.s)nUndefined_Addr ;未定义异常n STMFDSP!,R0-R12,lrn BLUndefined_Handlern LDMFDSP!,R0-R12,LR n SUBSPC, LR, #0 nSWI_Addr ;软件中断(管理模式)n STMFDSP!,R0-R12,lrn BLSWI_Handlern LDMFDSP!,R0-R12,LR n SU
8、BSPC, LR, #0nPrefetch_Addr ;预取指令异常n STMFDSP!,R0-R12,lrn BLPrefetch_Handlern LDMFDSP!,R0-R12,LR n SUBSPC, LR, #4nAbort_Addr ;中止异常n STMFDSP!,R0-R12,lrn BLAbort_Handlern LDMFDSP!,R0-R12,LR n SUBSPC, LR, #8异常的处理(vector.s)nIRQ_Addr ;IRQ异常n STMFDSP!,R0-R12,lr n LDRR0,=ISR_BASE n LDRR1,=AIC_IPERn LDRR2,R1n
9、 LDRPC,R2,R0 n nFIQ_Addr ;FIQ异常n STMFDSP!,R0-R12,lr n LDRR0,=ISR_BASE n LDRR1,=AIC_IPERn LDRR2,R1n LDRPC,R2,R0 中断向量表(vector.s)n ;interrupt service routine Entry_address definitionnISR_BASEnDCD_ISR_FAKE nDCD_ISR_INT1 nDCD_ISR_INT2 nDCD_ISR_INT3 nDCD_ISR_INT4 nDCD_ISR_INT5 nDCD_ISR_INT6nDCD_ISR_INT7nD
10、CD_ISR_INT8nDCD_ISR_INT9nDCD_ISR_INT10nDCD_ISR_INT11nDCD_ISR_INT12nDCD_ISR_INT13nDCD_ISR_INT14nDCD_ISR_INT15nDCD_ISR_INT16nDCD_ISR_INT17nDCD_ISR_INT18nDCD_ISR_INT19nDCD_ISR_INT20nDCD_ISR_INT21nDCD_ISR_INT22nDCD_ISR_INT23nDCD_ISR_INT24nDCD_ISR_INT25nDCD_ISR_INT26nDCD_ISR_INT27nDCD_ISR_INT28nDCD_ISR_I
11、NT29 nDCD_ISR_INT30nDCD_ISR_INT31 中断函数的设计(vector.s)n_ISR_FAKEn LDRR1,=AIC_EOSCRn STRR0,R1n LDMFD SP!,R0-R12,LRn SUBSPC, LR,#4n_ISR_INT1n BLWDT_Handler ; Watch Dog Timer Interruptn LDRR1,=AIC_EOSCRn STRR0,R1n LDMFD SP!,R0-R12,LR n SUBSPC, LR,#4 n_ISR_INT2n BLnIRQ0_Handler ; External Interrupt 0n LDRR
12、1,=AIC_EOSCRn STRR0,R1n LDMFD SP!,R0-R12,LR n SUBSPC, LR,#4 void nIRQ0_Handler(void)(init.s)启动代码(变量定义部分)nMode_USR EQU 0 x10nMode_FIQ EQU 0 x11nMode_IRQ EQU 0 x12nMode_SVC EQU 0 x13nMode_ABT EQU 0 x17nMode_UNDEF EQU 0 x1BnMode_SYS EQU 0 x1FnI_Bit EQU 0 x80 ; when I bit is set, IRQ is disablednF_Bit E
13、QU 0 x40 ; when F bit is set, FIQ is disablednRAM_Limit EQU 0 xffe02000 ; For unexpanded W90P710 boardnUND_Stack EQU RAM_LimitnAbort_Stack EQU RAM_Limit-256nIRQ_Stack EQU RAM_Limit-512 ; followed by IRQ stacknFIQ_Stack EQU RAM_Limit-768 ; followed by IRQ stacknSVC_Stack EQU RAM_Limit-1024 ; SVC stac
14、k at top of memorynUSR_Stack EQU 0 xffe01000 ; followed by USR(SYS) stack(1)初始化流程(init.s)n(禁止所有中断)nAREA Init, CODE, READONLYn ENTRYn EXPORTReset_HandlernReset_HandlernMRSr0, CPSRnORR r0, r0,#I_Bit nORRr0, r0,#F_BitnMSRCPSR_c, r0初始化流程(init.s)n LDRr0, =AIC_MDCR ;关闭所有中断源n LDRr1, =0 x7FFFEn STRr1, r0初始化
15、流程(init.s)n LDR r0,=REG_WTCR ;Disable watch dognMOV r1,#0nSTR r1,r0nnLDR r0,=REG_CAHCNF n;LDR r1,=0 x7 ;Enable write buffer and I/D_cachenMOV r1,#0 ;Disable write buffer and I/D_cache初始化流程(init.s)n IF RELEASEn;*n;Initalize the memoryn;FLASH4 M(base address 0 x00000000)n;SDRAM16M(base address 0 x0100
16、0000)n;*n LDR r0,=MemoryInitn LDMIA r0,r1-r6n LDR r0,=EBI_Ctrln STMIA r0,r1-r6初始化流程(init.s)n;*n;Self copy from FLASH to SDRAMn;*n LDRr0, =|Image$RO$Base| n LDRr1, =|Image$RO$Limit| n LDRr2, =|Image$RW$Base| n LDRr3, =|Image$RW$Limit| n SUB r1, r1, r0n SUBr3, r3, r2n ADDr1, r1, r3n LDRr2, =0 x1000000
17、 ;16MnSelfCopyn LDRr3, r0, #4n STRr3, r2, #4n SUBSr1, r1, #4n BNESelfCopyn ENDIF 初始化流程(init.s)n在一个简单的image里面:Image$RO$Base:是RO段的执行地址开始和装载地址开始,由-RO-BASE这个参数指定的Image$RO$Limit:是RO段的装载地址结束的后一个地址,也就是RW的装载地址的开始。n没运行:没运行:flash中的中的ro段是段是ro-base指定的地址指定的地址开始,等开始,等ro段完了后面紧接着就是段完了后面紧接着就是rw段段运行时:flash中的ro段地址没有动,
18、还是Image$RO$BaseImage$RO$limit-1,原来flash中的rw段移到了sdram中,地址为Image$RW$BaseImage$ZI$Base初始化流程(init.s)n;*n;remap the memoryn; FLASH 4 M(base address 0 x7F000000)n; SDRAM 16M(base address 0 x00000000)n;*n LDR r0,=MemoryRemapn LDMIA r0,r1-r6n LDR r0,=EBI_Ctrln STMIA r0,r1-r6(2)初始化流程(初始化各模式堆栈)n MSR CPSR_c,#M
19、ode_UNDEF:OR:I_Bit:OR:F_Bitn LDR SP, =UND_Stackn MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit n LDR SP, =Abort_Stackn MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bitn LDR SP, =IRQ_Stackn MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bitn LDR SP, =FIQ_Stackn MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bitn LDR SP, =SVC_Stack n MSR
20、 CPSR_c, #Mode_SYS:OR:I_Bit:OR:F_Bitn LDR SP, =USR_Stack(3)初始化流程(使能中断)nMSRCPSR_c, #Mode_USRnIMPORTMainnBMain nB.STMIA,LDMIA块拷贝 EXPORT MydataCopyMydataCopy MOVS R3,R2,LSL #3 BEQ copywords STMFD sp!,r4-r11Octcopy LDMIA R0!,R4-R11 STMIA R1!,R4-R11 SUBS R3,R3,#1 BNE Octcopy LDMFD sp!,r4-r11copywords AND
21、S R2,R2,#7 BEQ stopwordcopy LDR R3,R0,#4 STR R3,R1,#4 SUBS R2,R2, #1 BNE wordcopystop mov pc,lr END Swi异常的处理nSwi_handlerMRS R0,SPSR ;读取SPSR_SVCD到R0TST R0,#0X20 ;判断标志T是否置位LDRNEH R0,LR,-2 ;读取LR-2地址的半字到R0BICNE R0,0XFF00 ;取THUMB指令的低8位为 ;软中断号LDREQ R0,LR,#-4 ;读取LR-4地址的字到R0BICEQ R0,0XFF000000;取ARM指令的低24位为
22、软中断号程序状态寄存器2731N Z C V Q2867I F T mode162381554024fsxc U n d e f i n e dJn后缀后缀sn数据处理指令可以选择s后缀,以影响状态标志。但是比较指令(cmp、cmn、tst和teq)不需要后缀s,它们总会直接影响cpsr中的状态标志。n在数据处理指令中,除了比较指令以外,其它的指令如果带有s后缀,同时又以pc为目标寄存器进行操作,则操作的同时从spsr恢复cpsr。比如:nmovs pc, #0 xff/* cpsr = spsr; pc = 0 xff */nadds pc, r1, #0 xffffff00 /* cpsr
23、 = spsr; pc = r1 + 0 xffffff00 */nands pc, r1, r2/* cpsr = spsr; pc = r1 & r2; */n如果在user或者system模式下使用带有s后缀的数据处理指令,同时以pc为目标寄存器,那么会产生不可预料的结果。因为user和system模式下没有spsr。2731N Z C V Q2867I F T mode162381554024fsxc U n d e f i n e dJn注意:只有在特权模式下才能修改状态寄存器的控制域7:0,以实现处理器模式转换,或设置开/关异常中断 。程序中不能通过MSR指令直接修改CPSR中的T
24、控制位来实现ARM状态Thumb状态的切换,必须使用BX指令完成处理器状态的切换。用户模式下不能对CPSR23:0做修改。n例例nMRS R0,CPSRnBIC R0, R0, #0 x1F ; R0后5位清0 nORR R0, R0, #0 x1F ; R0后5位赋值为0b11111nMSR CPSR, R0 ;根据模式位4 : 0切换工作模式到系统模式nMOV R13, #1nMOV R14, #2nMRS R0,CPSR nBIC R0, R0, #0 x1F ; R0后5位清0nORR R0, R0, #0 x11 ; R0后5位赋值为0b10001nMSR CPSR, R0 ;根据模
25、式位4 : 0切换工作模式到FIQ模式nMOV R13, #33nMOV R14, #44nMRS R0,CPSR nBIC R0, R0, #0 x1F ; R0后5位清0 nORR R0, R0, #0 x10 ; R0后5位赋值为0b10000nMSR CPSR, R0 ;根据模式位4 : 0切换工作模式到用户模式n(四)一些基本的(四)一些基本的ARM指令功能段指令功能段n4.1 算数逻辑运算指令的应用n例1: 实现乘法的指令段MOV R0,R0,LSL #n ;R0=R0b) a=a-b; else b=b-a; return a; v对应的ARM代码段。(代码执行前R0中存放a,R
26、1中存放b;代码执行后R0中存放最大公约数。gcbCMP R0,R1 ;比较a和b的大小SUBGT R0,R0,R1 ;if(ab) a=a-bSUBLT R1,R1,R0 ;if(ba) b=b-aBNE gcb ;if(a!=b)跳转到gcb继续执行MOV PC,LR ;子程序结束,返回n例3:循环语句n下面代码段实现了程序循环执行。 MOV R0,#loopcount ;初始化循环次数 loop ;循环体 SUBS R0,R0,#1 ;循环计数器减1,设置条件标志 BNE loop ;循环计数器不为0,跳到loop继续执行 ;循环计数器为0,程序继续执行程序状态寄存器2731N Z C
27、V Q2867I F T mode162381554024fsxc U n d e f i n e dJ程序状态寄存器NZCV IM0M1M2M3M4TF. . .31 30 29 28 27 26 8 7 6 5 4 3 2 1 0条件代码标志保留控制位溢出标志进位或借位扩展零负或小于IRQ禁止FIQ禁止状态位模式位NZCVITFCPSR寄存器的格式大多数大多数“数值处理指令数值处理指令”可以可以选择是否影响条件代码标志位(指选择是否影响条件代码标志位(指令带令带S S后缀);但有些指令执行总是后缀);但有些指令执行总是影响条件代码标志。影响条件代码标志。 所有所有ARMARM指令都可按条件
28、来执指令都可按条件来执行,而行,而ThumbThumb指令中只有分支指令指令中只有分支指令可按条件执行。可按条件执行。运算结果的最高位反映在该运算结果的最高位反映在该标志位。对于有符号二进制补码,标志位。对于有符号二进制补码,结果为负数时结果为负数时N=1N=1,结果为正数,结果为正数或零时或零时N=0N=0;指令结果为指令结果为0 0时时Z=1Z=1(表示比(表示比较结果较结果“相等相等”),否则),否则Z=0Z=0;当进行加法运算,并且最高位产生进位时C=1,否则C=0。当进行减法运算,并且最高位产生借位时C=0,否则C=1。对于移位操作指令,C为从最高位最后移出的值,其它指令C通常不变;
29、 当进行加法当进行加法/减法运算,减法运算,并且发生有符号溢出时并且发生有符号溢出时V=1,否则,否则V=0,其它指,其它指令令V通常不变。通常不变。最低最低8 8位为控制位,当发生异常时,这些位为控制位,当发生异常时,这些位被硬件改变。当处理器处于一个特权模式位被硬件改变。当处理器处于一个特权模式时,可用软件操作这些位。时,可用软件操作这些位。保留位被保留将来使用。为了提高程序的可保留位被保留将来使用。为了提高程序的可移植性,当改变移植性,当改变CPSRCPSR标志和控制位时,请不要标志和控制位时,请不要改变这些保留位。另外,请确保您程序的运行改变这些保留位。另外,请确保您程序的运行不受保留
30、位的值影响,因为将来的处理器可能不受保留位的值影响,因为将来的处理器可能会将这些位设置为会将这些位设置为1 1或者或者0 0。 操作码条件助记符标志含义0000EQZ=1相等0001NEZ=0不相等0010CS/HSC=1无符号数大于或等于0011CC/LOC=0无符号数小于0100MIN=1负数0101PLN=0正数或零0110VSV=1溢出0111VCV=0没有溢出1000HIC=1,Z=0无符号数大于1001LSC=0,Z=1无符号数小于或等于1010GEN=V有符号数大于或等于 1011LTN!=V有符号数小于 1100GTZ=0,N=V有符号数大于 1101LEZ=1,N!=V有符号
31、数小于或等于 1110AL任何无条件执行 (指令默认条件) 1111NV任何从不执行(不要使用) 指令条件码表CPSR模式位设置表M4:0模式模式M4:0模式模式10000用户用户10111中止中止10001快中断快中断11011未定义未定义10010中断中断11111系统系统10011管理管理注意:不是所有模式位的组合都定义了有效的处理器模式,如果使用了错误的设置,将引起一个无法恢复的错误。Memory (contd)nMemory unitnAddressnDatanControl signalsnReadnWriteMemory (contd)nRead cycle1. Place ad
32、dress on the address bus2. Assert memory read control signal3. Wait for the memory to retrieve the datanIntroduce wait states if using a slow memory4. Read the data from the data bus5. Drop the memory read signalnIn Pentium, a simple read takes three clocks cyclesnClock 1: steps 1 and 2nClock 2: ste
33、p 3nClock 3 : steps 4 and 5Memory (contd)nWrite cycle1.Place address on the address bus2.Place data on the data bus3.Assert memory write signal4.Wait for the memory to retrieve the datanIntroduce wait states if necessary5. Drop the memory write signalnIn Pentium, a simple write also takes three cloc
34、ksnClock 1: steps 1 and 3nClock 2: step 2nClock 3 : steps 4 and 5ARM7TDMI指令集编码1.存储器从存储器从0 x400000开始的开始的100个单元中存放着个单元中存放着ASCII码,编写程序,将其所有的小写字母转换码,编写程序,将其所有的小写字母转换成大写字母,对其它的成大写字母,对其它的ASCII码不做变换。码不做变换。 (0 x610 x7a为小写为小写,0 x410 x5a为相应的大写为相应的大写,转换只需把处于转换只需把处于0X610X71中的数减去中的数减去0 x20,在写回存储器即刻在写回存储器即刻)2.编写程
35、序,比较存储器中编写程序,比较存储器中0 x400000和和0 x400004两无符号字数据的大小,并且将比较两无符号字数据的大小,并且将比较结果存于结果存于0 x400008的字中,若两数相等其结果的字中,若两数相等其结果记为记为0,若前者大于后者其结果记为,若前者大于后者其结果记为1,若前者,若前者小于后者其结果记为小于后者其结果记为-1。编写一程序,存储器中从编写一程序,存储器中从0 x400200开始有一个开始有一个64位数。(位数。(1)将取反,再存回原处;()将取反,再存回原处;(2)求)求其补码,存放到其补码,存放到0 x400208处处 。n编写一简单编写一简单ARM汇编程序段
36、,实现汇编程序段,实现1+2+100的运算。的运算。1 LDR伪指令与伪指令与LDR加载指令的功能和应用有何区加载指令的功能和应用有何区别别,举例说明?举例说明?2 编写一简单编写一简单ARM汇编程序段,实现汇编程序段,实现1+2+100的运算。的运算。3 编写程序,比较存储器中编写程序,比较存储器中0 x400000和和0 x400004两无符号字数据的大小,并且将比较两无符号字数据的大小,并且将比较结果存于结果存于0 x400008的字中,若两数相等其结果的字中,若两数相等其结果记为记为0,若前者大于后者其结果记为,若前者大于后者其结果记为1,若前者小,若前者小于后者其结果记为于后者其结果
37、记为-1。 4 将存储器中将存储器中0 x400000开始的开始的200字节的数据,字节的数据,传送到传送到0 x400800开始的区域。开始的区域。5 编写一程序,存储器中从编写一程序,存储器中从0 x400200开始有一个开始有一个64位数。(位数。(1)将取反,再存回原处;()将取反,再存回原处;(2)求)求其补码,存放到其补码,存放到0 x400208处处 。阶段测验阶段测验嵌入系统的构成D#include n#include n n#if CONFIG_MODVERSIONS=1n#define MODVERSIONSn#include n#endifn#include n#incl
38、ude n#include n#include n#include n#ifndef KERNEL_VERSIONSn#define KERNEL_VERSIONS(a,b,c) (a)*65536+(b)*256+(c)n#endifn n#if LINUX_VERSION_CODE KERNEL_VERSION(2,2,0)n#include n#endifn D#define SUCCESS 0n#define DEVICE_NAME char_driver_testn#define BUF_LEN 80nstatic char MessageBUF_LEN;Dstatic int de
39、vice_open(struct inode *inode, struct file *file)nnMOD_INC_USE_COUNT;nreturn SUCCESS;nnstatic int device_release(struct inode *inode, struct file *file)nnMOD_DEC_USE_COUNT;nreturn 0;nnstatic ssize_t device_write(struct file *file,const char *buffer,size_t length,loff_t *offset)nncopy_from_user(Messa
40、ge,buffer,length);nprintk(device writenr);nreturn length;nnstatic ssize_t device_read(struct file *file, char *buffer, size_t length, loff_t *offset)nncopy_to_user(buffer,Message,length); nreturn length;nDstatic int Major;nstruct file_operations Fops=nllseek:NULL,nread:device_read,nwrite:device_write,nreaddir:NULL,n/select:NULL,nioctl:NULL,nmmap:NULL,nopen:device_open,nrelease:device_releasen;Dint init_module()nn/int ret_val;nMajor=register_chrdev(0,DEVICE_NAME,&Fops);nreturn 0;nnvoid cleanup_module()nnint ret;nret=unregister_chrdev(Major,DEVICE_NAME);n