现在的位置: 首页 > 综合 > 正文

GNU-ARM程序开发(二)—-GNU下的跑马灯

2013年10月18日 ⁄ 综合 ⁄ 共 2681字 ⁄ 字号 评论关闭

我们一般在Windows下的MDK环境或者是ADS环境下开发裸机程序

下面来体验一下Linux下GNU-ARM的裸奔程序开发

GNU ARM裸奔程序的开发步骤如下:
1)编写程序(汇编/C程序)
2)编写链接脚本
3)编译、汇编程序文件,生产目标文件(.o)
4)利用链接脚本链接目标文件,生产可执行文件(elf格式)
5)利用格式转换工具(objcopy)将elf格式文件转换为bin格式
6)烧写

 

这里汇编指令就略过了。

汇编行结构
[标号:]  汇编语句 @注释
标号
标号只能由a~z,A~Z,0~9,“.”,“_”等字符组成;
“.” 标号 :特殊的标
“_”表示当前位置的运行地址 ;
注释
@   从符合开始到行结尾
#  整行注释

汇编程序中的分段
汇编系统预定义的段名
.text   @代码段
.data   @已经初始化的全局变量和静态变量

.bss   @是未初始化的全局变量和静态变量

自定义一个段
.section  自定义段名 

汇编程序中的关键字
.extern symbol
声明symbol的定义在其他源文件中
.global symbol
声明symbol是全局可见的
.include "filename"
在当前源文件中插入filename的内容
.set symbol, expression
设置symbol的值为expression

GNU的伪指令跟MDK的伪指令不同;但是两个编译器都能够识别ARM指令;
GNU编译环境下的伪操作可分为以下几类:
常量编译控制伪操作
汇编程序代码控制伪操作
宏及条件编译控制伪操作
其他伪操作

 常量编译控制伪操作

汇编程序代码控制伪操作

 

宏及条件编译控制伪操作

其他伪操作

连接脚本文件

elf格式文件:
GNU编译器生成的目标文件缺省为elf格式;
elf文件由若干段(section)组成;
目标代码中包含如下段:
.text: 包含程序的指令代码;
.data: 包含固定的数据,如常量、字符串;
.bss: 包含未初始化的变量、数组等;
连接器的任务就是将多个目标文件的.text、.data和.bss等段连接在一起,而连接脚本文件是告诉连接器从什么地址开始放置这些段。

链接脚本
内置缺省连接脚本:
如果采用缺省脚本,则生成的目标代码需要操作系统才能加载运行(操作系统上的应用程序采用缺省脚本)。
自定义链接脚本:
为了能在嵌入式系统上直接运行,需要编写自己的连接脚本文件。

链接脚本格式
链接器脚本由一系列命令组成;
“SECTIONS”命令:描述输出文件的内存布,SECTIONS段的基本格式如下:
 SECTIONS
 {
 段名 : {段内容}
 }
ENTRY(symbol) :设置入口点,参数是一个符号名;
OUTPUT_FORMAT(bfdname):输出文件的BFD格式;
OUTPUT_ARCH(bfdarch) :指定平台架构;
对于ARM,bfdname=elf32-littlearm,bfdarch=arm

LED跑马灯程序链接脚本:

led.lds:

      1 OUTPUT_FORMAT(elf32-littlearm)
      2 OUTPUT_ARCH(arm)
      3 ENTRY(_start)
      4 
      5 SECTIONS
      6 {
      7 >---. = 0x0;
      8 >---. = ALIGN(4);
      9 >---.text : {
     10 >--->---led.o (.text)
     11 >--->---delay.o (.text)
     12 >---}
     13 
     14 >---. = ALIGN(4);
     15 >---.data : {
     16 >--->---*(.data)
     17 >---}
     18 >---
     19 >---. = ALIGN(4);
     20 >---.bss : {
     21 >--->---*(.bss)
     22 >---}
     23 
     24 }

编译链接过程

Arm-linux-ld –Txxx.lds xx.o –o xxxx.elf
–T 直接指定代码段
xxx.lds 为连接脚本
arm-linux-objcopy被用来复制一个目标文件的内容到另一个文件中,可用于不同源文件的之间的格式转换
Arm-linux-objcopy –O binary –S elf_file bin_file
-O bfdname 输出的格式
-F bfdname 同时指明源文件,目的文件的格式
-R sectionname 从输出文件中删除掉所有名为sectionname的段
-S 不从源文件中复制重定位信息和符号信息到目标文件中
-g 不从源文件中复制调试符号到目标文件中

makefile:

      1 led.bin:led.o delay.o led.lds
      2 >---arm-linux-ld -Tled.lds led.o delay.o -o led.elf
      3 >---arm-linux-objcopy -O binary -S led.elf led.bin
      4 
      5 led.o:led.s
      6 >---arm-linux-gcc -c led.s -o led.o>
      7 
      8 delay.o:delay.s
      9 >---arm-linux-gcc -c delay.s -o delay.o
     10 
     11 clean:-
     12 >---rm -rf *.o *.elf *.bin
     13 

led.s:

.text
.extern delay
.global _start
_start:
	@set GPBCON
	ldr r0,=0x56000010
	ldr r1,[r0]
	bic r1,r1,#0xc00
	orr r1,r1,#0x15400
	str r1,[r0]
	@set GPBUP
	ldr r0,=0x56000018
	ldr r1,[r0]
	orr r1,r1,#0x20
	str r1,[r0]
loop:

    ldr r0,=0x56000014

    ldr r3,=0x1e0
    str r3,[r0]

    bl delay

    ldr r3,=0xfd0
    str r3,[r0]

    bl delay

    ldr r3,=0xfb0
    str r3,[r0]

    bl delay

    ldr r3,=0xf70
    str r3,[r0]

    bl delay

    ldr r3,=0xef0
    str r3,[r0]

    bl delay
	b loop


.end

delay.s:

      1 
      2 .text
      3 .global delay
      4 delay:
      5 >---ldr r2,=0x2000000
      6 delay_loop:
      7         sub r2,r2,#1
      8         cmp r2,#0x0
      9         bne delay_loop
     10         mov pc,lr
     11 
     12 .end

最后,把make出来的bin烧到板上。

假如用jtag可以烧到0地址。此时cup频率是12mhz,delay.s下的ldr r2,=0x20000,此时开发板上的bootloader已经挂了,所以不推荐用这种方法。

假如用dnw下到内存里运行,此时的cup频率是400mhz,delay.s下的ldr r2,=0x2000000,ok

 

抱歉!评论已关闭.