程序用的韦东山的第七章的示例代码。这里总结下问题:
- 韦东山的代码写的挺好的。注释比较多,结合芯片手册以及920T内核手册页很容易看懂。
- 我用的JLINK直接在内存里调试裸机程序。因此不需要使用H-JTAG烧写nandflash,程序直接下载到内部ram里面运行。编译好的mmu.bin大小为3KB,内部ram为4KB。
- FL2440的几个led灯对应于GPB5,6,8,10.因此改了下leds.c的一些代码。如下:
/* * leds.c: 循环点亮4个LED * 属于第二部分程序,此时MMU已开启,使用虚拟地址 */ #define GPBCON (*(volatile unsigned long *)0xA0000010) // 物理地址0x56000010 #define GPBDAT (*(volatile unsigned long *)0xA0000014) // 物理地址0x56000014 #define GPB5_out (1<<(5*2)) #define GPB6_out (1<<(6*2)) #define GPB8_out (1<<(8*2)) #define GPB10_out (1<<(10*2)) /* * wait函数加上“static inline”是有原因的, * 这样可以使得编译leds.c时,wait嵌入main中,编译结果中只有main一个函数。 * 于是在连接时,main函数的地址就是由连接文件指定的运行时装载地址。 * 而连接文件mmu.lds中,指定了leds.o的运行时装载地址为0xB4004000, * 这样,head.S中的“ldr pc, =0xB4004000”就是跳去执行main函数。 */ //static inline void wait(volatile unsigned long dly) static inline void wait(unsigned long dly) { for(; dly > 0; dly--); } int main(void) { unsigned long i = 0; // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出 //GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out; GPBCON = GPB5_out|GPB6_out|GPB8_out|GPB10_out; // 将LED1-4对应的GPB5/6/8/10四个引脚设为输出 while(1){ wait(30000); //GPBDAT = (~(i<<5)); // 根据i的值,点亮LED1-4 GPBDAT = ((i&0x8?0:1)<<10) | ((i&0x4?0:1)<<8) | ((i&0x2?0:1)<<6) | ((i&0x1?0:1)<<5); if(++i == 16) i = 0; } return 0; }
- 在测试的时候遇到一个问题,那就是led不是按照我所预想的4个灯以i的值进行闪烁。而是常亮。
经过仔细对比前面章节的led实验,以及代码。发现:
objs := head.o init.o leds.o
mmu.bin : $(objs)
arm-linux-ld -Tmmu.lds -o mmu_elf $^
arm-linux-objcopy -O binary -S mmu_elf $@
arm-linux-objdump -D -m arm mmu_elf > mmu.dis
%.o:%.c
#arm-linux-gcc -Wall -nostdlib -O2 -c -o $@ $<
arm-linux-gcc -Wall -O2 -c -o $@ $<
#arm-linux-gcc -Wall -c -o $@ $<
%.o:%.S
#arm-linux-gcc -Wall -nostdlib -O2 -c -o $@ $<
#arm-linux-gcc -Wall -O2 -c -o $@ $<
arm-linux-gcc -Wall -c -o $@ $<
clean:
rm -f mmu.bin mmu_elf mmu.dis *.o
其中可以看出,对*.c 进行O2优化,因此在leds.c中wait函数中dly变量可能被优化。
将static inline void wait(unsigned long dly) 改为 static inline void wait(volatile unsigned long dly),防止编译进行优化操作。
这篇文章对编译器优化原因以及volatile关键字用法做了详细说明http://www.cnblogs.com/yc_sunniwell/archive/2010/06/24/1764231.html
或者我们将Makefile中的优化选项去除,同样能达到效果。有兴趣的同学可以试试。
arm-linux-gcc -Wall -c -o $@ $<