
本页内容发表于MCUZone,但不代表MCUZone的观点。
如果你对本页的技术内容有疑问,请到 MCUZone技术论坛 发帖。
如果你认为本页的内容侵害了你的权益,请与hotislandn@hotmail.com;hdapple_2000@hotmail.com 联系,我们会在确认后移除。
从AT91SAM7S64的数据手册看:
具体可以参考S64的完整数据手册:
由此,我们可以预测下面几种情况时,代码的执行速度:
| 代码运行模式 | 代码大小 | 执行速度 |
|---|---|---|
| ARM in Flash | 大 | 慢 |
| ARM in RAM | 大 | 最快 |
| Thumb in Flash | 小 | 较快 |
| Thumb in RAM | 小 | 快 |

用于armlink的scatter loader file。
main.c中包含的代码(测试代码)可以选择被放置于RAM或者Flash中。
; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* LR_IROM1 0x00100000 0x00010000 { ; load region ER_IROM1 0x00100000 { ; load address = execution address SAMboot.o (START, +First) SAMinit.o (+RO) ; unsmask the following two line to link code in Flash ; 打开下面两行将使得主要代码在Flash中运行 Main.o (+RO) * (+RO) } RAM_VECT 0x00200000 { ; RW data ram_vect.o (RAM_VECTOR, +First) ; unsmask the following two line to link code in RAM ; 打开下面两行将使得主要代码在RAM中运行 ;Main.o (+RO) ;* (+RO) } RW_IRAM1 +0 { ; RW data * (+RW +ZI) } }
简单的启动代码:
;/****************************************************************************************************************/ ;/********************* Startup code for AT91SAM7S ***************************************************************/ ;/ hotislandn@hotmail.com / ;/ WWW.MCUZONE.COM ;/ ;/ Rev 0.2 / ;/****************************************************************************************************************/ MODUSR EQU 0x10 MODSYS EQU 0x1F MODSVC EQU 0x13 MODABT EQU 0x17 MODUDF EQU 0x1B MODIRQ EQU 0x12 MODFIQ EQU 0x11 IRQBIT EQU 0x80 FIQBIT EQU 0x40 RAMEND EQU 0x00204000 ; S64 : 16KB RAM VECTSIZE EQU 0x100 ; 驻留RAM的向量区域定为256字节 UsrStkSz EQU 8 ; size of USR stack SysStkSz EQU 128 ; size of SYS stack SvcStkSz EQU 8 ; size of SVC stack UdfStkSz EQU 8 ; size of UDF stack AbtStkSz EQU 8 ; size of ABT stack IrqStkSz EQU 128 ; size of IRQ stack FiqStkSz EQU 16 ; size of FIQ stack PRESERVE8 AREA START, CODE, READONLY CODE32 ENTRY EXPORT RESET EXPORT SYSINIT RESET LDR PC,=SYSINIT ; Reset B UDFHANDLER ; UNDEFINED B SWIHANDLER ; SWI B PABTHANDLER ; PREFETCH ABORT B DABTHANDLER ; DATA ABORT B . ; RESERVED LDR PC,[PC,#-0xF20] B . ; ADD FIQ CODE HERE UDFHANDLER B . SWIHANDLER B . PABTHANDLER B . DABTHANDLER B . ;/****************************************************************************************************************/ SYSINIT ;设置各模式堆栈,关闭IRQ,FIQ MRS R0,CPSR BIC R0,R0,#0x1F MOV R2,#RAMEND ORR R1,R0,#(MODSVC :OR: IRQBIT :OR: FIQBIT) MSR cpsr_cxsf,R1 ; ENTER SVC MODE MOV sp,R2 SUB R2,R2,#SvcStkSz ORR R1,R0,#(MODFIQ :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER FIQ MODE MOV sp,R2 SUB R2,R2,#FiqStkSz ORR R1,R0,#(MODIRQ :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER IRQ MODE MOV sp,R2 SUB R2,R2,#IrqStkSz ORR R1,R0,#(MODUDF :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER UDF MODE MOV sp,R2 SUB R2,R2,#UdfStkSz ORR R1,R0,#(MODABT :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER ABT MODE MOV sp,R2 SUB R2,R2,#AbtStkSz ;ORR R1,R0,#(MODUSR :OR: IRQBIT :OR: FIQBIT) ;MSR CPSR_cxsf,R1 ; ENTER USR MODE ;MOV sp,R2 ;SUB R2,R2,#UsrStkSz ORR R1,R0,#(MODSYS :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER SYS MODE MOV SP,R2 ; 于SYS模式运行代码 ;/****************************************************************************************************************/ IMPORT S64Init LDR R0,=S64Init MOV LR,PC BX R0 ;/****************************************************************************************************************/ ; 复位后有16sec的时间禁止WDT ;/****************************************************************************************************************/ IMPORT |Image$$ER_IROM1$$Base| IMPORT |Image$$ER_IROM1$$Limit| IMPORT |Load$$RAM_VECT$$Base| IMPORT |Image$$RAM_VECT$$Base| IMPORT |Image$$RAM_VECT$$Limit| IMPORT |Image$$RAM_VECT$$Limit| IMPORT |Load$$RW_IRAM1$$Base| IMPORT |Image$$RW_IRAM1$$Base| IMPORT |Image$$RW_IRAM1$$Limit| IMPORT |Image$$RW_IRAM1$$ZI$$Base| IMPORT |Image$$RW_IRAM1$$ZI$$Limit| ;/****************************************************************************************************************/ ; copy vector to RAM LDR R0,=|Load$$RAM_VECT$$Base| LDR R1,=|Image$$RAM_VECT$$Base| LDR R2,=|Image$$RAM_VECT$$Limit| 1 CMP R1,R2 LDRLO R3,[R0],#4 STRLO R3,[R1],#4 BLO %B1 ;/****************************************************************************************************************/ ; RW , ZI 初始化 LDR R0,=|Load$$RW_IRAM1$$Base| LDR R1,=|Image$$RW_IRAM1$$Base| LDR R2,=|Image$$RW_IRAM1$$ZI$$Base| 1 CMP R1,R2 LDRLO R3,[R0],#4 STRLO R3,[R1],#4 BLO %B1 MOV R3,#0 LDR R1,=|Image$$RW_IRAM1$$ZI$$Limit| 2 CMP R2,R1 STRLO R3,[R2],#4 BLO %B2 ;/****************************************************************************************************************/ ;/****************************************************************************************************************/ ; 跳转到Main(!) IMPORT Main LDR R0,=Main MOV LR,PC BX R0 loop_here B . ;/****************************************************************************************************************/ __user_initial_stackheap LDR r0, =|Image$$RW_IRAM1$$ZI$$Limit| ;MOV pc, lr BX lr END
驻留在RAM中的异常向量。
这个文件目前没有完全实现,因为本例中并没有使用。
有些代码无意义
PRESERVE8
AREA RAM_VECTOR, CODE, READONLY
CODE32
IMPORT SYSINIT
VECTOR_IN_RAM
LDR PC,=SYSINIT ; Reset
B . ; UNDEFINED
B . ; SWI
B . ; PREFETCH ABORT
B . ; DATA ABORT
B . ; RESERVED
LDR PC,[PC,#-0xF20]
;B . ; ADD FIQ CODE HERE
ADD R0, R0,#1
BX LR
END
标准的器件初始化代码:
这个文件中的代码不能设置到在RAM中运行,因为在启动代码中,对这段代码的调用出现在复制代码到RAM之前。
#include "AT91SAM7S64.h" #include "SAMinit.h" //#include "SAMIsr.h" //unsigned int F_CPU=0; void S64Init(void) { AT91PS_PMC pPMC = AT91C_BASE_PMC; //* Set Flash Waite sate // Single Cycle Access at Up to 30 MHz, or 40 // if MCK = 47923200 I have 50 Cycle for 1 usecond ( flied MC_FMR->FMCN AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(48 <<16)) | AT91C_MC_FWS_0FWS ; //* Watchdog Disable AT91C_BASE_WDTC->WDTC_WDMR= AT91C_WDTC_WDDIS; //* Set MCK at 47 923 200 // 1 Enabling the Main Oscillator: // SCK = 1/32768 = 30.51 uSecond // Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms pPMC->PMC_MOR = ( (AT91C_CKGR_OSCOUNT) & (0x06 <<8)) | AT91C_CKGR_MOSCEN ; // Wait the startup time while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS)); // 2 Checking the Main Oscillator Frequency (Optional) // 3 Setting PLL and divider: // - div by 5 Fin = 3,6864 =(18,432 / 5) // - Mul 25+1: Fout = 95,8464 =(3,6864 *26) // for 96 MHz the erroe is 0.16% // Field out NOT USED = 0 // PLLCOUNT pll startup time estimate at : 0.844 ms // PLLCOUNT 28 = 0.000844 /(1/32768) pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x05) | (AT91C_CKGR_PLLCOUNT & (28<<8)) | (AT91C_CKGR_MUL & (25<<16))); // Wait the startup time while(!(pPMC->PMC_SR & AT91C_PMC_LOCK)); while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); // 4. Selection of Master Clock and Processor Clock // select the PLL clock divided by 2 pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 ; while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ; while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); // 5. ReMap //AT91C_BASE_MC->MC_RCR=1; // 6. IRQ //SAMIsrInit(); //F_CPU=XTAL/CKGR_DIV*CKGR_MUL/PCK_DIV; }
简单的循环。
#include <AT91SAM7S64.h> #include "lib_AT91SAM7S64.h" void delay(unsigned int len) { while(--len); } int Main(void) { AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, 0x07); AT91F_PIO_SetOutput(AT91C_BASE_PIOA, 0x07); AT91C_BASE_RSTC->RSTC_RMR=0xA5000001; // enable user reset while(1) { delay(1000); AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x01); delay(1000); AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x02); delay(1000); AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x04); delay(1000); AT91F_PIO_SetOutput(AT91C_BASE_PIOA, 0x07); } }
用于Keil的仿真器初始化文件。
开始debug时,PC位于0×00000000(复位后Flash被映射到0),而代码从0×100000开始link,因此只能看到反汇编,执行完第一条指令
LDR PC,=SYSINIT 后,PC就会跳到SYSINIT处(0×1000??,Flash的真实地址),即可看到源代码。
FUNC void RomStart(void) { PC=0x000000; } LOAD .\output\s64_scl.axf INCREMENTAL RomStart(); //g,Main
| 代码运行模式 | 代码大小(Byte) | IO输出信号频率(Hz) |
|---|---|---|
| ARM in Flash | 612 | 1152 |
| ARM in RAM | 612 | 1585 |
| Thumb in Flash | 556 | 1185 |
| Thumb in RAM | 556 | 1470 |
0x00200054 E3A00FFA MOV R0,#0x000003E8 6: while(--len); 7: } 8: 9: int Main(void) 10: { 11: AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, 0x07); 12: AT91F_PIO_SetOutput(AT91C_BASE_PIOA, 0x07); 13: 14: AT91C_BASE_RSTC->RSTC_RMR=0xA5000001; // enable user reset 15: 16: while(1) 17: { 18: delay(1000); 19: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x01); 0x00200058 E2500001 SUBS R0,R0,#0x00000001 0x0020005C 1AFFFFFD BNE 0x00200058 0x00200060 E3A00001 MOV R0,#0x00000001 0x00200064 E5810034 STR R0,[R1,#0x0034] 20: delay(1000); 21: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x02); 0x00200068 E3A00FFA MOV R0,#0x000003E8 0x0020006C E2500001 SUBS R0,R0,#0x00000001 0x00200070 1AFFFFFD BNE 0x0020006C 0x00200074 E3A00002 MOV R0,#0x00000002 0x00200078 E5810034 STR R0,[R1,#0x0034] 22: delay(1000); 23: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x04); 0x0020007C E3A00FFA MOV R0,#0x000003E8 6: while(--len); 7: } 8: 9: int Main(void) 10: { 11: AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, 0x07); 12: AT91F_PIO_SetOutput(AT91C_BASE_PIOA, 0x07); 13: 14: AT91C_BASE_RSTC->RSTC_RMR=0xA5000001; // enable user reset 15: 16: while(1) 17: { 18: delay(1000); 19: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x01); 20: delay(1000); 21: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x02); 22: delay(1000); 23: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x04); 0x00200080 E2500001 SUBS R0,R0,#0x00000001 0x00200084 1AFFFFFD BNE 0x00200080 0x00200088 E3A00004 MOV R0,#0x00000004 0x0020008C E5810034 STR R0,[R1,#0x0034] 24: delay(1000); 0x00200090 E3A00FFA MOV R0,#0x000003E8 0x00200094 E2500001 SUBS R0,R0,#0x00000001 0x00200098 1AFFFFFD BNE 0x00200094 0x0020009C E5812030 STR R2,[R1,#0x0030] 16: while(1) 0x002000A0 EAFFFFEB B 0x00200054
从测试结果看:
由此在实际应用中: