arm 裸板驱动入门-LED
2014-04-06 17:28
246 查看
1)系统的启动
PC-->BIOS-->引导操作系统--->识别分区 (c盘、d盘等)--->启动应用程序。
嵌入式Linux--->bootloader--->引导linux操作系统--->挂载根文件系统----->启动应用。
2)怎么生成一个可执行程序?
得到一个可执行程序的步骤无非是这么几步:
1> 编辑文件
2> 编译/链接
3> 烧写测试
在Windows下有很多的集成开发环境,如ADS.TAR.KEIL等,点点鼠标就帮我们生成了。
在Linux下也有一些GNU工具链,如gcc之类的,要我们用命令行来运行生成。最后的效果都是一样的。
3)应用程序与裸板程序的差别
以前一直没关心这个main()是怎么执行起来的,只知道一执行就从main()开始执行。然而,这个main函数也只是一个普通的函数而以,main它又被谁调用的呢?
它是被启动代码调用,裸板没有操作系统,如果我们要在裸板上跑程序的话,这个启动代码也要由我们自己来写。
启动代码要完成什么功能呢?
1>硬件相关的初始化。
2>调用C函数。
4)裸板点LED
一、写启动代码
1)硬件初始化
a、设置CPU
把外设的地址告诉处理器。
b、关看门狗
一般是3秒倒数,3秒一到就重启了(是为了防止死机)。
看一下,以下这是个完全汇编的代码例子:
1》mcr p15,0,r0,c15,c2,4 //协处理指令,告诉CPU 0x70000000~0x7fffffff是外设的地址。0x70000000是基地址,#0x13表示多大,从ARM11的手册
在arm1176jzfs.pdf中搜索 CP15可以找到
搜索这个 Peripheral Port Memory Remap Register,找到0x13 对应256M.
2》 ldr r0, =0x70000000 //‘=’表明这是条伪汇编指令,最终会被真正的汇编指令代替,用反汇编可以看到最终被mov指令代替。有些汇编指令内容比较复杂,arm一条处理不过来,就会把内容先放在内存哪一个地方,再用ldr从那里读出来。
代码写出来了,怎么编译出来放到板子上运行呢?
进行linux环境,执行#arm-linux-gcc -o start.o start.S -c -c是只编译不链接,把start.S 编译成 start.o。
#arm-linux-ld -Ttext 0 -o led.elf start.o -ld是链接,-Ttext 0 是代码段从0开始
#arm-linux-objcopy -O binary led.elf led.bin 再把.elf 格式的转换成.bin文件
ELF:可执行链接格式。其实就是Unix下的执行文件和动态库(*.so)和目标文件(*.o)文件格式。
不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。
上拉电阻:接到VCC。
下拉电阻:接到地。
2)调用C函数
上面一个程序是全汇编的,没有用到C的程序,汇编比较麻烦,下面我们来看看用C怎么写。
调用c函数前还要设置栈,因为子函数中的变量,参数都是存在栈中的。设置栈很简单,只要让这个sp寄存器指向某块不用的内存就可以了。
我们还要了解一个6410的内部结构,我们现在都是设置的从Nand flash启动。这样一上电,Nand flash前8k的内容就会原原本本的拷贝到内存中。我们的程序很小,暂时就把sp指向8k之上。
启动后就会调用C函数,一般是名为main,但是这个叫什么是没关系的,程序中我们就命名为ledBright.
bl长跳转,后把下条指令的地址存到lr寄存器中。恢复是用ldr pc,lr就可跳回来。
二、写c函数
1)ledBright中实现点灯:
2)汇编与C语言之间怎么传递参数
它们之间有一个规则,称为ATPCS规则。
第1个参数存在r0,第2、3、4个参数分别存在r1 r2 r3中。如果还有更多参数的话,就存在栈里面。如:
int ledBright(int start, int end, int a, int b, int c, int d) start存在r0,end a b 分别存在r1 r2 r3中,c d存在栈中。
PC-->BIOS-->引导操作系统--->识别分区 (c盘、d盘等)--->启动应用程序。
嵌入式Linux--->bootloader--->引导linux操作系统--->挂载根文件系统----->启动应用。
2)怎么生成一个可执行程序?
得到一个可执行程序的步骤无非是这么几步:
1> 编辑文件
2> 编译/链接
3> 烧写测试
在Windows下有很多的集成开发环境,如ADS.TAR.KEIL等,点点鼠标就帮我们生成了。
在Linux下也有一些GNU工具链,如gcc之类的,要我们用命令行来运行生成。最后的效果都是一样的。
3)应用程序与裸板程序的差别
以前一直没关心这个main()是怎么执行起来的,只知道一执行就从main()开始执行。然而,这个main函数也只是一个普通的函数而以,main它又被谁调用的呢?
它是被启动代码调用,裸板没有操作系统,如果我们要在裸板上跑程序的话,这个启动代码也要由我们自己来写。
启动代码要完成什么功能呢?
1>硬件相关的初始化。
2>调用C函数。
4)裸板点LED
一、写启动代码
1)硬件初始化
a、设置CPU
把外设的地址告诉处理器。
b、关看门狗
一般是3秒倒数,3秒一到就重启了(是为了防止死机)。
看一下,以下这是个完全汇编的代码例子:
.globl _start _start: /* 硬件相关的设置 */ /* Peri port setup */ ldr r0, =0x70000000 orr r0, r0, #0x13 mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) /* 关看门狗 */ /* 往WTCON(0x7E004000)写0 */ ldr r0, =0x7E004000 mov r1, #0 str r1, [r0] /* 设置GPMCON让GPM3作为输出引脚 */ ldr r1, =0x7F008820 mov r0, #0x1000 str r0, [r1] /* 设置GPMDAT让GPM3输出0 */ ldr r1, =0x7F008824 mov r0, #0 str r0, [r1] halt: b halt硬件代码实现点灯,汇编实现,_start开始,硬件相关设置---关看门狗---设置GPM3为输出,让它输出0。还要设置cpu,设定外设起始地址,(所谓外设地址就是gpio,uart等寄存器地址,从0x70000000~0x7fffffff)。
1》mcr p15,0,r0,c15,c2,4 //协处理指令,告诉CPU 0x70000000~0x7fffffff是外设的地址。0x70000000是基地址,#0x13表示多大,从ARM11的手册
在arm1176jzfs.pdf中搜索 CP15可以找到
搜索这个 Peripheral Port Memory Remap Register,找到0x13 对应256M.
2》 ldr r0, =0x70000000 //‘=’表明这是条伪汇编指令,最终会被真正的汇编指令代替,用反汇编可以看到最终被mov指令代替。有些汇编指令内容比较复杂,arm一条处理不过来,就会把内容先放在内存哪一个地方,再用ldr从那里读出来。
代码写出来了,怎么编译出来放到板子上运行呢?
进行linux环境,执行#arm-linux-gcc -o start.o start.S -c -c是只编译不链接,把start.S 编译成 start.o。
#arm-linux-ld -Ttext 0 -o led.elf start.o -ld是链接,-Ttext 0 是代码段从0开始
#arm-linux-objcopy -O binary led.elf led.bin 再把.elf 格式的转换成.bin文件
ELF:可执行链接格式。其实就是Unix下的执行文件和动态库(*.so)和目标文件(*.o)文件格式。
不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。
上拉电阻:接到VCC。
下拉电阻:接到地。
2)调用C函数
上面一个程序是全汇编的,没有用到C的程序,汇编比较麻烦,下面我们来看看用C怎么写。
.globl _start _start: /*设置CPU,把外设地址告诉CPU*/ /* Peri port setup */ ldr r0, =0x70000000 orr r0, r0, #0x13 mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) /*关看门狗*/ ldr r0, =0x7E004000 mov r1, #0 str r1, [r0] /*设置栈*/ ldr sp, =8*1024 bl ledBright halt: b halt
调用c函数前还要设置栈,因为子函数中的变量,参数都是存在栈中的。设置栈很简单,只要让这个sp寄存器指向某块不用的内存就可以了。
我们还要了解一个6410的内部结构,我们现在都是设置的从Nand flash启动。这样一上电,Nand flash前8k的内容就会原原本本的拷贝到内存中。我们的程序很小,暂时就把sp指向8k之上。
启动后就会调用C函数,一般是名为main,但是这个叫什么是没关系的,程序中我们就命名为ledBright.
bl长跳转,后把下条指令的地址存到lr寄存器中。恢复是用ldr pc,lr就可跳回来。
二、写c函数
1)ledBright中实现点灯:
void delay() { volatile int i = 0x10000; while (i--); } int ledBright() { int i = 0; volatile unsigned long *gpmcon = (volatile unsigned long *)0x7F008820; volatile unsigned long *gpmdat = (volatile unsigned long *)0x7F008824; /* gpm0,1,2,3设为输出引脚 */ *gpmcon = 0x1111; while (1) { *gpmdat = i; i++; if (i == 16) i = 0; delay(); } return 0; }pc:r15 lr:r14 ip: r12 fp:r 11
2)汇编与C语言之间怎么传递参数
它们之间有一个规则,称为ATPCS规则。
第1个参数存在r0,第2、3、4个参数分别存在r1 r2 r3中。如果还有更多参数的话,就存在栈里面。如:
int ledBright(int start, int end, int a, int b, int c, int d) start存在r0,end a b 分别存在r1 r2 r3中,c d存在栈中。
相关文章推荐
- ARM底层学习笔记-裸板实验程序解析-点亮LED
- Android驱动入门-LED--HAL硬件抽象层程序设计①
- 嵌入式ARM裸板程序——存储管理器驱动
- linux设备驱动入门,最简单的LED驱动,基于tq2440
- ARM嵌入式学习--OK6410裸板程序--2.GPIO控制LED跑马灯(从ARM汇编跳转到C语言)
- ARM+Linux驱动----点亮开发板的LED
- ARM嵌入式学习--OK6410裸板程序--1.GPIO控制LED
- 【iCore1S 双核心板_ARM】例程一:ARM驱动三色LED
- 纯led驱动-arm平台
- ARM之LED驱动
- ARM:裸板shell编程完善(匹配命令、修复bug)、G-Sensor重力传感器驱动基础
- 第008课 第1个ARM裸板程序及引申(点亮LED灯)
- Android驱动入门-Led控制+app+ndk库+底层驱动
- ARM-linux驱动学习:led驱动程序编写练习(2014-8-22)
- arm LED驱动小程序 可以通过modprobe 加载ko文件
- Android驱动入门-Led控制+app+ndk库+底层驱动
- ARM4412裸板驱动LED灯.按键,蜂鸣器的驱动
- 从ARM裸机看驱动之按键中断方式控制LED(二)
- 基于arm的一个简单的led驱动
- 用查询方式去控制led灯(ARM 驱动开发)