BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #8376同步于 2010/4/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

arm学习笔记(1)

mybays
2010/4/22镜像同步7 回复
开发环境的建立: 手里几块开发板,arm7,arm9,Intel IXP-425,还有过几天就会寄来的Cortex-M0,真不知道用哪块好,决定采用QQ2440V3作为开发学习平台,原因很简单,附带的光盘里资料收集的很全,不用自己费那么大的力气到网上一点一点的找. 本来是打算到http://www.kegel.com/crosstool/上下载配置文件自己重新编译交叉编译工具链,但是想到最近unixcenter挂了,找不着合适的socket代理下那么多的源码,暂时作罢. 编译器暂时采用光盘自带的三个版本3.4.1,3.3.2,2.95.3,真不知道为什么要弄这么多版本. 3.3.2版本是用来编译Qtopia/Embedded的,2.95.3版本是用来编译VIVI的,3.4.1版本是用来编译内核的. 就采用3.4.1版本来编译应用程序吧. 没有把编译器放在系统目录下,统统放在了/home/$USER/arm/crosstool/里,需要设置的时候,用以下命令导入环境变量: export PATH=$PATH:/home/$USER/arm/crosstool/3.4.1/bin 如果需要用其它两个版本,就把3.4.1改为其它两个版本号就行. 再设置一下调试和下载平台: 本来自己画了一块USB-prog的板子,打算用这个调ARM,但是不舍得花加急费,等到现在还没来,估计下周一会到.所以前几天到淘宝上买了一块Open-jtag,花了170人民币.现在正在熟悉linux下的使用,有感兴趣的同学可以站内我,我给推荐. 调试软件采用的是openocd,现在用的openocd版本是买jtag时里面附带的,有时间我会编译一个适合自己使用的. 我的工作空间设置为/home/$USER/arm/qq2440v3 把openocd权限设置为可执行,放在系统路径里,然后openocd.cfg复制到工作空间里,打开终端,进入这个目录. 然后开始设置硬件,把QQ2440V3开发板接上电源,插上JTAG线,并把JTAG插入电脑USB接口,执行命令lsusb,可以看到一项: Bus 004 Device 006: ID 1457:5118 First International Computer, Inc. OpenMoko Neo1973 Debug board (V2+) 表明JTAG已经被系统识别. 把QQ2440V3开发板系统启动跳线调到NAND一边,然后打开开关,因为在调试中发现如果跳线在NOR一端不能得到预期的结果. 然后在工作目录下输入sudo openocd,在弹出来的信息中能看到JTAG已经能够识别出目标板: JTAG device found: 0x07fd047d (Manufacturer: 0x23e, Part: 0x7fd0, Version: 0x0) 0x07fd047d就是ARM9TDMI的标识码. 然后在工作目录打开一个新终端,查看openocd.cfg内的信息: 第一行telnet_port 4444,说明我们能够通过telnet进入openocd命令界面: telnet 127.0.0.1 444 输入命令poll来查看系统的状况: > poll target state: running 通过halt来暂停板子的执行: > halt waiting for target halted... target state: halted target halted in ARM state due to debug request, current mode: Supervisor cpsr: 0x20000093 pc: 0xc002ea0c MMU: enabled, D-Cache: enabled, I-Cache: enabled 从上面可以看到板子的MMU和D-cache已经使能,可以通过下面的命令来禁止MMU和D-cache: > arm920t cp15 2 0 2: 00000000 然后加载程序: > load_image /home/mybays/arm/qq2440v3/leds/leds_elf 168 byte written at address 0x00000000 downloaded 168 byte in 0.012190s 让我郁闷的是竟然不支持相对路径,每次都要输入绝对路径,这程序写的真伤感情. 然后开始执行: > resume 0x0 就能够看到板子上的4个led灯飞快的跑个不停. 然后停止执行: > halt target state: halted target halted in ARM state due to debug request, current mode: Supervisor cpsr: 0x20000093 pc: 0x00000028 MMU: disabled, D-Cache: disabled, I-Cache: disabled 可以看到MMU和D-Cache已经被禁止了. 下面我们来看看leds程序部分: 先看看编译部分吧: mybays@spaceship:~/arm/qq2440v3/leds$ make arm-linux-gcc -Wall -Wstrict-prototypes -g -fomit-frame-pointer -ffreestanding -c -o crt0.o crt0.S arm-linux-gcc -Wall -Wstrict-prototypes -g -fomit-frame-pointer -ffreestanding -c -o leds.o leds.c arm-linux-ld -Tleds.lds crt0.o leds.o -o leds_elf arm-linux-objcopy -O binary -S leds_elf leds.bin arm-linux-objdump -D -m arm leds_elf > leds.dis 然后就是源码部分: @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, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K bl main @ 调用C程序中的main函数 halt_loop: b halt_loop @crt0.S结束部分 //leds.c开始部分 #define GPBCON (*(volatile unsigned long *)0x56000010) #define GPBDAT (*(volatile unsigned long *)0x56000014) #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(unsigned long dly) { for(; dly > 0; dly--); } int main(void) { unsigned long i = 0; GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out; // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出 while(1){ wait(300000); GPBDAT = (~(i<<5)); // 根据i的值,点亮LED1-4 if(++i == 16) i = 0; } return 0; } //leds.c结束部分 //leds.lds开始部分 SECTIONS { . = 0x00; .text : { *(.text) } .rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) } .bss ALIGN(4) : { *(.bss) *(COMMON) } } //leds.lds结束部分 #Makefile开始部分 CFLAGS := -Wall -Wstrict-prototypes -g -fomit-frame-pointer -ffreestanding all : crt0.S leds.c arm-linux-gcc $(CFLAGS) -c -o crt0.o crt0.S arm-linux-gcc $(CFLAGS) -c -o leds.o leds.c arm-linux-ld -Tleds.lds crt0.o leds.o -o leds_elf arm-linux-objcopy -O binary -S leds_elf leds.bin arm-linux-objdump -D -m arm leds_elf > leds.dis clean: rm -f leds.dis leds.bin leds_elf *.o #Makefile结束部分 要记得在编译前导入环境变量,否则系统会提示找不到arm-linux-gcc
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
hang1989机器人#1 · 2010/4/23
原创么~? 大赞啊~ [em68]
hobby机器人#2 · 2010/4/23
感谢分享~! vivi没用过,跟u-boot差不多吧,u-boot里面是可以定义环境变量的,这样就不用每次敲很长的命令了
ssailing机器人#3 · 2010/4/23
大赞~ 会自己写链接脚本的都是牛人啊 有几个问题请教下啊 1) > halt waiting for target halted... target state: halted target halted in ARM state due to debug request, current mode: Supervisor cpsr: 0x20000093 pc: 0xc002ea0c MMU: enabled, D-Cache: enabled, I-Cache: enabled 从上面可以看到板子的MMU和D-cache已经使能,可以通过下面的命令来禁止MMU和D-cache: PC指针0xc002ea0c貌似是内核的地址啊 你板子里面是不是已经有程序在跑了? open-jtag这个仿真器可以支持Linux内核调试么? 2) > load_image /home/mybays/arm/qq2440v3/leds/leds_elf 168 byte written at address 0x00000000 从上述指令看 哪个地方指定了将leds_elf加载到0地址了呢 load_image加载的必须是elf格式的映像么 对于2440来说 0地址是内部SRAM么 什么时候SRAM会映射到0地址呢 或者是SDRAM重映射到这了? 3) //leds.lds开始部分 SECTIONS { . = 0x00; .text : { *(.text) } .rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) } .bss ALIGN(4) : { *(.bss) *(COMMON) } } 程序链接的基地址是0 一部来说你的程序必须加载到0位置的 但是你目前程序里面没有任何全局变量的访问 汇编代码和C代码都是相对寻址 你能试试把程序加载到其他非0的RAM地址上 看看能不能跑? 再加上全局变量 然后再试试把程序加载到其他非0的RAM地址上 还能不能正常运转
Journal机器人#4 · 2010/4/27
期待回答
mybays机器人#5 · 2010/4/28
早就给三楼站内了,在这发一下吧: : 1.能调内核的可能性很大,但是具体我没有验证,你可以google一下,或看openocd的手册 : 2.可以是bin格式的,openocd会自动识别. : 关于地址映射问题,我也想搞明白,不过最近事情比较杂,没时间深究,大家可以交流.
foreveryou机器人#6 · 2010/5/4
【 在 mybays 的大作中提到: 】 : 开发环境的建立: : 手里几块开发板,arm7,arm9,Intel IXP-425,还有过几天就会寄来的Cortex-M0,真不知道用哪块好,决定采用QQ2440V3作为开发学习平台,原因很简单,附带的光盘里资料收集的很全,不用自己费那么大的力气到网上一点一点的找. : 本来是打算到http://www.kegel.com/crosstool/上下载配置文件自己重新编译交叉编译工具链,但是想到最近unixcenter挂了,找不着合适的socket代理下那么多的源码,暂时作罢. : ................... 好东西 刚安装完crosstool就看这个帖子 真是幸福 可以练练了!
letu机器人#7 · 2010/5/11
nb