星空网 > 软件开发 > 操作系统

跟着韦老师学Linux学习笔记(一)

学编程,第一个程序肯定是“hello world”,学单片机或ARM,最初学的肯定是GPIO的操作。在这一节课里主要涉及到了点亮LED和按键控制LED。

1、要想点亮一个LED,分以下几个步:

①、了解相关硬件

②、配置Gpio的相关寄存器

③、编写相关代码

④、编译下载

2、一般来说,要想点亮LED,只需要控制相关的gpio口输出高电平或低电平就可以了。通过查看2440的原理图可以知道(如下图所示):

 跟着韦老师学Linux学习笔记(一)images/loading.gif' data-original="http://images2015.cnblogs.com/blog/844994/201702/844994-20170227093901313-163295042.png" width="250" height="151">跟着韦老师学Linux学习笔记(一)

3个LED的阴极经过1K的限流电阻连接到GPF4、GPF5和GPF6三个Gpio口上了。因此我们只要让PF4、GPF5和GPF6输出低电平,就能点亮LED,高电平熄灭LED。

3、查看2440的DataSheet 可以知道,Gpio主要有三个寄存器需要设置,再本篇中分别是GPFCON、GPFDAT和GPFUP。

 跟着韦老师学Linux学习笔记(一)

其中:

     GPFCON是控制寄存器,主要是控制GPIO的功能,主要有输入、输出和中断三个功能。其中每个GPIO口有寄存器的两位来控制,00:输入,01:输出,10:中断,10:保留。

     GPFDAT是数据寄存器,主要是控制GPIO输出高电平还是低电平,0:低电平,1:高电平。

     GPFUP 是设置内部上拉电阻的寄存器,0:不设置上拉电阻,1:设置上拉电阻。

4、编辑代码

在教程中的第一个代码使用汇编语言编写的,代码非常简单。如下:

 1 .text 2 .global _start 3 _start: 4 LDR  R0,=0x56000050 5 MOV R1,#0x00000400 6 STR  R1,[R0]   7 LDR  R0,=0x56000054   8 MOV  R1,#0x00000000 9 STR  R1,[R0]10 MAIN_LOOP:11   B    MAIN_LOOP

 

 

 下面主要分一下这个代码:

.text:这个是GCC编译器里面的一个关键词,它指定了后续编译出来的代码放在可执行代码段,是处理器开始执行代码的地方。

.global _start 告诉编译器后续跟的是一个全局可见的名字(可能是变量,也可以是函数名),.global让 _start 符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行。_start是一个函数的起始地址,也是编译、链接后程序的起始地址。由于程序是通过加载器来加载的,必须要找到 _start名字的函数,因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供其它程序寻找到。

_start是程序的起始地址

LDR R0,=0x56000050

MOV R1,#0x00000400

STR R1,[R0]

这三句主要实现了对GPFCON寄存器的设置,这里首先是把R0设为了GPFCON的寄存器地址,然后给R1赋值,最后把R1的值赋到以R0为地址的寄存器里,从而配置相应端口的功能。这里是0x00000400,正好是GPFCON的[11:10]设置为了01 ,即是GPF5位输出功能。

LDR R0,=0x56000054                

MOR R1,#0x00000000

STR R1,[R0]

这三句代码和上面类似,只要实现了GPFDAT输出低电平,这里是GPF5输出低电平,因为只有GPF5端口被设置为了输出功能。

MAIN_LOOP:

           B MAIN_LOOP

这句是个死循环没有什么太大意思。

5、编译下载

程序的编译命令时通过编写Makefile文件完成的。

1 led_on.bin : led_on.S2   arm-linux-gcc -g -c -o led_on.o led_on.S3   arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf4   arm-linux-objcopy -O binary -S led_on_elf led_on.bin5 clean:6   rm -f  led_on.bin led_on_elf *.o

 

arm-linux-gcc:

           -g:产生供gdb调试用的可执行文件

           -c:只编译不连接

           -o: 指定输出文件名。这里指定的是生成led_on.o

arm-linux-ld:      

           -o:指定输出文件名。这里生成lec_on.elf。

           -Ttext: 设置代码段的起始地址:0x0000000。

arm-linux-objcopy:

           -O: 输出的格式, binary指二进制文件。这里生成led_on.bin。

           -S: 不从源文件中复制重定位信息和符号信息到目标文件中

Clean:

           是清除命令,清除make生成的文件,这里指的是清除led_on.bin 、led_on_elf以及所有的.o文件。*是通配符。

然后我们linux环境下,执行make命令来编译文件生成可执行文件并下载到开发板上,可以观察到led2被点亮。开发板自带的有下载教程“如何烧写S3C2440裸板程序.pdf”。

 

 

在接下来的视频教程中,主要讲解了如何用c语言来编写程序点亮led灯。用c程序来操作gpio口,首先要设置相关硬件,关看门狗,设置栈,这些功能是在汇编文件里编写的。

 1 .text 2 .global _start 3 _start: 4         ldr    r0, =0x53000000 5         mov    r1, #0x0 6         str    r1,[r0]         7         ldr    sp, =1024*4 8         bl    main 9 halt_loop:10         b  halt_loop

 

 

代码和上面的类似:

ldr           r0, =0x53000000

mov           r1, #0x0

str           r1,[r0]   

这三句代码是通过写0关闭看门狗,否则CPU会不断地重启。

ldr           sp, =1024*4

设置我们的堆栈空间的大小,这里设置为4K,因为2440的内部RAM只有4K。

bl            main

调用我们写的c函数

接下来是个死循环。

C函数:

1 #define GPFCON (*(volatile unsigned long *) 0x56000050)2 #define GPFDAT (*(volatile unsigned long *) 0x56000054)3 int main()4 {5   GPFCON = 0x00000100;6   GPFDAT = 0x00000000;7   8   return 0;9 }

 

 

在这里最重要的是GPFCON和GPFDAT这两个宏的定义,这是指向这两个寄存器地址的指针。

例如:

int a;

int *p;

 

p=&a;

*p = 0x100;//这就是把变量a赋值为0x100

在我们的程序中:

地址是(volatile unsigned long *) 0x56000050,即是p=(volatile unsigned long *) 0x56000050,*p=(*(volatile unsigned long *) 0x56000050),GPFCON和GPFDAT两个宏的意思就是*p。

其他就是往寄存器里赋值就行。

编译下载:

1 led_on_c.bin : crt0.S led_on_c.c2   arm-linux-gcc -g -c -o crt0.o crt0.S3   arm-linux-gcc -g -c -o led_on_c.o led_on_c.c4   arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on_c.o -o led_on_c_elf5   arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin6   arm-linux-objdump -D -m arm led_on_c_elf > led_on_c.dis7 clean:8   rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o

 

这个Makefile只是比前面多了一句:

arm-linux-objdump -D -m arm  led_on_c_elf > led_on_c.dis

只一句是用来生成反汇编代码的语句,

           -D:反汇编所有代码。

           -m:反汇编目标文件时使用的架构。这里是arm架构。

下载如上。

 

接下来的流水灯实验和按键控制led的实验,本质上与上面的c程序类似,重要点主要是涉及的位操作。

 1 #define  GPF4_out  (1<<(4*2)) 2 #define  GPF5_out  (1<<(5*2)) 3 #define  GPF6_out  (1<<(6*2)) 4  5 #define  GPF4_msk  (3<<(4*2)) 6 #define  GPF5_msk  (3<<(5*2)) 7 #define  GPF6_msk  (3<<(6*2)) 8     // LED1,LED2,LED4对应的3根引脚设为输出 9     GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk); //对寄存器的相应位的清零操作。10     GPFCON |= GPF4_out | GPF5_out | GPF6_out;//对寄存器的相应位的赋值操作。

 

 

位操作的好处是,清零时只清零相应位,赋值时也只赋值相应位,对其他为不产生影响,防止破坏程序。

 

好了,第一节课的笔记到此为止,这也是第一次写博客,没什么太难的内容,只是上课的一些笔记(记性不好,还是写下来忘了方便查看)。再接再厉。

 




原标题:跟着韦老师学Linux学习笔记(一)

关键词:linux

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流