程序在nor flash中可以運行,但是是有限制的,它不能像RAM那樣隨意的寫(盡管它可以隨意的讀)。在norflash上,不能運行寫存儲器的指令,不過排除寫的地方是RAM類。實驗中的三個文件如下所示:
Makefile如下:
led_on.bin : crt0.S leds.c
arm-linux-gcc -g -c -O2 -o crt0.o crt0.S
arm-linux-gcc -g -c -O2 -o leds.o leds.c
arm-linux-ld -Ttext 0x0 crt0.o leds.o -o led_on_elf
arm-linux-objcopy -O binary -S led_on_elf led_on.bin
arm-linux-objdump -D -m arm led_on_elf > led_on.dis
clean:
rm -f led_on.dis led_on_elf *.o led_on.bin
arm-linux-gcc -g -c -O2 -o crt0.o crt0.S
arm-linux-gcc -g -c -O2 -o leds.o leds.c
arm-linux-ld -Ttext 0x0 crt0.o leds.o -o led_on_elf
arm-linux-objcopy -O binary -S led_on_elf led_on.bin
arm-linux-objdump -D -m arm led_on_elf > led_on.dis
clean:
rm -f led_on.dis led_on_elf *.o led_on.bin
crt0.S如下:
@******************************************************************************
@ File:crt0.S
@ 功能:通過它轉入C程序
@*****************************************************************************
.text
. global _start
_start:
ldr r0, = 0x53000000 @ WATCHDOG寄存器地址
mov r1, # 0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, = 0x00001000
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
leds.c如下所示:
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
/*
* LED1,LED2,LED4對應GPB5、GPB6、GPB7、GPB8
*/
#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))
void wait( volatile unsigned long dly)
{
for(; dly > 0; dly--);
}
int main( void)
{
unsigned long i = 0;
// LED1,LED2,LED4對應的4根引腳設為輸出
GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out;
while( 1){
wait( 30000);
GPBDAT = (~(i<< 5)); // 根據i的值,點亮LED1,2,3,4
if(++i == 16)
i = 0;
}
return 0;
}
@ File:crt0.S
@ 功能:通過它轉入C程序
@*****************************************************************************
.text
. global _start
_start:
ldr r0, = 0x53000000 @ WATCHDOG寄存器地址
mov r1, # 0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, = 0x00001000
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
leds.c如下所示:
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
/*
* LED1,LED2,LED4對應GPB5、GPB6、GPB7、GPB8
*/
#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))
void wait( volatile unsigned long dly)
{
for(; dly > 0; dly--);
}
int main( void)
{
unsigned long i = 0;
// LED1,LED2,LED4對應的4根引腳設為輸出
GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out;
while( 1){
wait( 30000);
GPBDAT = (~(i<< 5)); // 根據i的值,點亮LED1,2,3,4
if(++i == 16)
i = 0;
}
return 0;
}
實驗結果:這樣的代碼編譯出來的程序在steppingstone(SRAM)中可以運行,但是下載到norflash中不能運行。
修改代碼:
crt0.S如下:
@******************************************************************************
@ File:crt0.S
@ 功能:通過它轉入C程序
@*****************************************************************************
.text
. global _start
_start:
ldr r0, = 0x53000000 @ WATCHDOG寄存器地址
mov r1, # 0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, = 0x40001000
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
@ File:crt0.S
@ 功能:通過它轉入C程序
@*****************************************************************************
.text
. global _start
_start:
ldr r0, = 0x53000000 @ WATCHDOG寄存器地址
mov r1, # 0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, = 0x40001000
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
實驗結果:這樣的代碼編譯出來的程序在norflash中可以運行。
原因分析:
由於要跳轉到main()函數中去執行,即C函數中去,就需要使用堆棧。代碼“ldr sp, =0x00001000”由於使用堆棧的地址位於norflash中,而當跳轉到main()函數中去執行時,就會寫norflash,而norflash不能像RAM那樣隨意寫,所以不能成功執行。代碼“ldr sp, =0x40001000”由於使用堆棧的地址是0x40001000,使用的是(0x40000000—0x40001000),即是S3C2440的片內SRAM。這樣跳轉到main()函數時,用到的 就是片內SRAM,所以能夠成功執行。
寫內存的時機:
程序在運行過程中大多時候是在讀內存,例如取指令、加載數據等等,寫內存的時機大概這么幾種情況:
1.寫特殊功能寄存器(其實這個可以排除出去)
2.修改全局變量的值
3.講數據壓入堆棧保存。