1. 构建S3C6410裸机开发环境,并使用GPIO控制LED灯
开发环境:
软件环境:Ubuntu12.04
硬件环境:Tiny6410 + Jlink
一、安装Jlink
在linux下面可用的Jlink为V4.22版本的,SEGGER官网上好像有最新版本linux下面的Jlink,但是没有尝试过,听过升级了最新版本的固件之后山寨的Jlink就用不了了。
JLink_Linux_V422下载地址在我的网盘上:http://yun.baidu.com/s/1c027ogK
使用方法见README:
Requirements ============ Please make sure that you have installed libusb as this is necessary for the J-Link to work via USB. You can install it the following way for all apt-able Linux derivates: apt-get -update apt-get -install libusb This will update the apt-get package resources and download and install libusb. Please unplug and replug your J-Link after successful libusb installation. You also need to make sure the libreadline is installed on your system. This library is needed by the JLinkExe utility. Installing the shared library ============================= To install the delivered shared library in a system directory perform the following steps as root: - Copy the library in a system directory for example /usr/lib cp libjlinkarm.so.* /usr/lib - Update the cache of dynamic loader and setup symbolic links by running: ldconfig Running JLinkExe with standard user rights ========================================== In order to run JLinkExe with standard user rights you have to do the following: - Place the rule file "45-jlink.rules" provided with this J-Link software package at /etc/udev/rules.d/ - Make sure that you are member of the group "plugdev" - If the group "plugdev" does not exist, you have to create it: Command line: groupadd plugdev // Creates new group "plugdev" usermod -a -G plugdev <Username> // Appends user <Username> to the group "plugdev" - Restart your system
二:编写裸机程序的方法
裸机程序由两部分组成: 启动代码 + 应用程序
启动代码的作用: 初始化硬件
6410最简单的启动代码由两部分组成:
设置外设寄存器地址的范围
/* peripheral port register address range set */
ldr r0, =0x70000000@the base address of peripheral port is 0x70000000
orr r0, #0x13@address range is 256M, 0x7000 0000 -- 0x7FFF FFFF
mcr p15,0,r0,c15,c2,4
关看门狗
/* disable the watchdog */
ldr r0, =0x7E004000 @看门狗控制寄存器
mov r1, #0
str r1, [r0]
由于6410将地址划分为两部分,内存地址(0x0000 0000 -- 0x6FFF FFFF) 和 外设寄存器地址(0x7000 0000 -- 0x7FFF FFF)。
而CPU访问这两种地址是通过不同的总线完成的。所以需要通过指令告诉CPU外设寄存器地址的范围。这条指令是通过协处理器完成的。
因为6410上电时默认是使能看门狗的,所以需要关掉。
看门狗的控制寄存器起WTCON 0x7E004000
(对于2410来说就不需要第一步,因为2410访问内存和外设寄存器地址都是使用的相同的方式。)
三: LED电路图的分析:
由GPK控制:
GPK4 ---- LED1
GPK5 ---- LED2
GPK6 ---- LED3
GPK7 ---- LED4
GPIO由两部分组成。分别是alive part和off part.
其中alive part在sleep 模式仍然会被供电, 但是off part在sleep模式中就不会被供电。
控制GPIO的寄存器主要有控制寄存器 数据寄存器 上/下拉寄存器 Sleep模式配置寄存器 Sleep模式上/下拉配置寄存器
其中控制GPK的寄存器有:
GPKCON0 0x7F00 8800
GPKCON1 0x7F00 8804
GPKDAT 0x7F00 8808
GPKPED 0x7F00 880C
GPKCON0 控制GPK0 -- GPK7 每个引脚占用4Bit
GPKCON1 控制GPK8 -- GPK15 可以设置引脚为GPIO输出或者输入, 或者是其他的功能。
如果Bit[31:28]=0001,那么GPK7设置为输出。
四:编写链接文件lds
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 OUTPUT_ARCH(arm) 3 OUTPUT(led) 4 5 ENTRY(_start) 6 SECTIONS 7 { 8 . = 0x0c000000; 9 . = ALIGN(4); 10 .text : 11 { 12 *(.text) 13 } 14 15 . = ALIGN(4); 16 .data : 17 { 18 *(.data) 19 } 20 21 . = ALIGN(4); 22 bss_start = .; 23 .bss : 24 { 25 *(.bss) 26 } 27 bss_end = .; 28 }
五:编写Makefile文件:
1 CROSS_COMPILE=arm-linux-gnueabi- 2 #CROSS_COMPILE=arm-linux- 3 4 OBJ=led 5 6 AS=$(CROSS_COMPILE)as 7 LD=$(CROSS_COMPILE)ld 8 OBJCOPY=$(CROSS_COMPILE)objcopy 9 OBJDUMP=$(CROSS_COMPILE)objdump 10 AS_FLAGS=-march=armv6 -mcpu=arm1176jzf-s -mfloat-abi=softfp -mfpu=vfp 11 LD_FLAGS=-Bstatic -T $(OBJ).lds 12 13 14 $(OBJ).bin:$(OBJ).o 15 $(LD) -o $(OBJ) $(LD_FLAGS) $^ 16 $(OBJCOPY) -O binary $(OBJ) $@ 17 $(OBJDUMP) -D $(OBJ) > $(OBJ).dis 18 19 $(OBJ).o:$(OBJ).S 20 $(AS) $(AS_FLAGS) $< -o $@ 21 22 .PHONY:clean 23 clean: 24 rm -f $(OBJ).o $(OBJ) $(OBJ).bin $(OBJ).dis
六:编写LED的汇编代码
这是采用的AT&T风格的汇编代码,
.global定义了一个全局标号,可以被外部文件引用,相当与extern的作用。
.section是用来定义段的,.text表示代码段
1 .global _start 2 .section .text 3 4 _start: 5 6 /* 7 * set the CPU to SVC32 mode 8 */ 9 mrs r0,cpsr 10 bic r0,r0,#0x1f @ clear the last 5 bits 11 orr r0,r0,#0xd3 @ 0b11010011, set the svc mod, and disable fiq irq 12 msr cpsr,r0 13 14 /* 15 * flush v4 I/D cahces 16 */ 17 mov r0,#0 18 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 19 mcr p15, 0, r0, c8, c7, 0 /* flush the v4 TLB */ 20 21 /* 22 * disable MMU stuff and caches 23 */ 24 mrc p15, 0, r0, c1, c0, 0 25 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 26 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 27 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 28 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 29 mcr p15, 0, r0, c1, c0, 0 30 31 /* peripheral port register address range set */ 32 ldr r0, =0x70000000 @the base address of peripheral port is 0x70000000 33 orr r0, #0x13 @address range is 256M, 0x7000 0000 -- 0x7FFF FFFF 34 mcr p15,0,r0,c15,c2,4 35 36 /* disable the watchdog */ 37 ldr r0, =0x7E004000 38 mov r1, #0 39 str r1, [r0] 40 41 b user_program 42 43 /* 44 * LED1 <----> GPK4 45 * LED2 <----> GPK5 46 * LED3 <----> GPK6 47 * LED4 <----> GPK7 48 */ 49 user_program: 50 /************** control the led ***************/ 51 /* control led1 GPK4 */ 52 ldr r0, =0x7F008800 53 ldr r1, =0x00100000 54 str r1, [r0] /* set GPK5 as output*/ 55 56 ldr r0, =0x7F008808 57 ldr r1, [r0] 58 bic r1, #0x20 /* clear the bit 5 */ 59 str r1, [r0] 60 b loop 61 62 loop: 63 b loop 64 65 .end
七:安装交叉编译工具链
我使用的是ELDK5.2,可以在DENX的官网下载,地址ftp://ftp.denx.de/pub/eldk/
当前最新的版本是5.5
具体安装方法参考denx的网站的Documents
也可以使用其他的交叉编译工具,比如FriendlyARM提供的arm-linux-gcc-4.5.1-v6-vfp-20101103.tgz,可以到我的网盘下载http://pan.baidu.com/s/1hqge03i
八:编译
导入环境变量,我的ELDK安装的路径是/opt/eldk-5.2.1
source /opt/eldk-5.2.1/armv6/environment-setup-armv6-vfp-linux-gnueabi
Make:
caodan@caodan-Ubuntu:~/code/asm/S3C6410/led1$ make
arm-linux-gnueabi-as -march=armv6 -mcpu=arm1176jzf-s -mfloat-abi=softfp -mfpu=vfp led.S -o led.o
arm-linux-gnueabi-ld -o led -Bstatic -T led.lds led.o
arm-linux-gnueabi-objcopy -O binary led led.bin
arm-linux-gnueabi-objdump -D led > led.dis
其中生成的led.bin是要下载到CPU中运行的二进制代码。
九:下载运行
由于tiny6410的启动方式的NANDFlash启动,所以上电的时候会自动加载NANDFLASH中的前4K内容加载到SteppingStone区域(0x0c000000这个地址),SteppingStone是一个内部的SRAM,所以是可读写的。同事SteppingStone又会自动被映射到0地址处,这就是NANDFLASH启动的原理。
可以利用这个特性,直接将刚才编译生成的代码下载到SteppingStone中运行。
启动Jlink
caodan@caodan-Ubuntu:~/code/asm/S3C6410/led1$ jlink SEGGER J-Link Commander V4.22 ('?' for help) Compiled Dec 17 2010 17:41:09 DLL version V4.22, compiled Dec 17 2010 17:41:06 Firmware: J-Link ARM V8 compiled Dec 16 2010 20:21:29 Hardware: V8.00 S/N: 20100213 Feature(s): RDI,FlashDL,FlashBP,JFlash,GDBFULL VTarget = 3.248V Info: TotalIRLen = 9, IRPrint = 0x0011 Found 2 JTAG devices, Total IRLen = 5: #0 Id: 0x2B900F0F, IRLen: 04, IRPrint: 0x0, ARM ETB #1 Id: 0x07B76F0F, IRLen: 05, IRPrint: 0x1, ARM1176 Core ARM11 identified. JTAG speed: 100 kHz J-Link>
加载程序到0x0c000000
J-Link>loadbin /home/caodan/code/asm/S3C6410/led1/led.bin 0c000000 Loading binary file... [/home/caodan/code/asm/S3C6410/led1/led.bin] Writing bin data into target memory @ 0x0C000000. J-Link: ARM11 CP15 Settings changed: 0x00450078 from 0x00001002, MMU Off, ICache Off, DCache Off Info: CP15.0.0: 0x410FB766: ARM, Architecture Unknown architecture Info: CP15.0.1: 0x1D152152: ICache: 16kB (4*128*32), DCache: 16kB (4*128*32) DIDR: 6 Breakpoints available and 2 Watchpoints available.
设置PC指针,并跳转到0x0c000000处运行
J-Link>setpc 0x0c000000
J-Link>g
此时就可以看到核心板上的LED2亮起来了。