嵌入式课程:实验1——OK6410开发之点亮LED
实验一:OK6410开发之点亮LED
一、实验目的
1. 掌握开发板Linux的烧录过程,感受与单片机烧录程序的不同
2. 熟悉Linux开发环境,学习Linux系统指令
3.从初步的点灯开始对ARM底层编写进行更深入了解
二、实验设备
开发机环境 操作系统:ubuntu 20.04
交叉编译环境:arm-linux-gcc 4.3.2 6410
板子内核源码:linux-3.0.1
目标板环境:OK6410-A linux-3.0.1
编译驱动之前要先在 ubuntu 下编译开发板的内核,这里用的内核版本是 linux-3.0.1 如何编译内核,具体见上一篇实验内容:
三、实验内容(原理)
1. 通过SD卡一键烧录Linux到OK6410开发板上
SW2引脚号 | Pin 8 | Pin 7 | Pin 8 | Pin 8 | Pin 8 | Pin 8 | Pin 2 | Pin 1 |
---|---|---|---|---|---|---|---|---|
引脚定义 | SELNAND | OM4 | OM3 | OM2 | OM1 | GPN15 | GPN14 | GPN13 |
Nandflash 启动 | 1 | 0 | 0 | 1 | 1 | x | x | x |
SD卡启动 | x | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
注:
(1)SW2开关ON时为”1”;OFF时为”0”,”X”为高电平或者低电平
(2)OK6410开发板出厂默认设置为NAND FLASH启动方式
从这里我们可以知道如何进行SD卡启动进行烧录。
2. 在Linux上编写LED驱动文件,Makefile文件,测试文件并拷贝到开发板上进行测试运行
2.1 硬件部分:
我们先看硬件电路:
3.3v已经硬件接在PN结正极,输出端接负极。说明当输出端输出低电平时LED即可导通被点亮。以下是对应引脚:
LED1 -GPM0
LED2 -GPM1
LED3 -GPM2
LED4 -GPM3
2.2 寄存器部分
我们看ARM芯片手册,注意操作哪些寄存器可以完成LED的点亮,这里主要关注的就是芯片的GPIO章节,具体关注的就是怎么操作GPM0-GPM3 四个引脚,先来截一个图,清楚的看到GPM的三个寄存器:控制寄存器、数据寄存器、上拉下拉寄存器,此外还给出的寄存器的地址和初始值,这里重点关注下配置寄存器和数据寄存器的地址,等下我们要通过这个地址来操作。
接下来再看下GPMCON寄存器中的每一位的作用,这里只截取了GPM0-GPM3,从下表中可以看出GPMCON寄存器的每四位对应一个GPM引脚的状态,当设置为0000时为输入模式,当设置为0001时为输出模式……………其余的暂时不管。这里很明显我们需要设置为输出模式。
接着就是GPMDAT寄存器,这里描述的很清楚,当端口被配置为输入模式时,我们可以直接从端口引脚独处相应的状态,当端口被配置为输出模式时,端口引脚的状态就会根据我们是定的值而发生改变,这里我们肯定是要GPM0-GPM3都输出低电平。
看完这些我们就基本知道点灯的基本步骤了,后面程序会体现:
步骤1:
配置GPMCON寄存器为0x0001使LED0引脚为输出模式(0x1111就是四个LED引脚为输出模式)
步骤2:
配置GPMDAT寄存器位为0x0U输出低电平使LED导通点亮
四、实验步骤
1.SD卡一键Linux烧录开发板
1.1 准备文件
准备好上一个实验配置好的文件:
mmc.bin (/root/forlinx/uboot1.1.6)
uboot.bin (/root/forlinx/uboot1.1.6)
zImage (/root/forlinx/linux-3.0.1/arch/arm/boot)
mkyaffs2image-nand2g (/root/forlinx)
1.2 制作SD系统卡
首先格式化SD卡
然后以管理员身份运行SD_Writer软件,正常情况下应该是这样的:
我一开始没有Format这个选项,后面查了下发现需要右键属性在兼容性里勾上这个“以兼容模式运行这个程序”
?
点击"Scan"软件会自动扫描SD卡位置,我的是H。"SD_Type"选择"Auto","OS_Type"选“Linux||Android”。
最后点击"Select Boot",把制作好的"mmc.bin"放进去,点击"Program"。出现"It's OK"就说明系统卡制作完成。
Quit退出。
1.3 烧录Linux到开发板上
将准备好的四个文件(其实三个就行,mmc.bin已经不需要了)拷贝到SD上
将SD卡插到开发板SD卡槽里,拨码开关拨成0x1f,打开电源,可以看到四盏LED均被点亮,系统正在烧录。

烧录完成后的界面如下:

此时会出现蜂鸣器响和流水灯提示烧录完成,有些板子蜂鸣器坏了可能不会响。
关闭电源,将拨码开关拨成0x19,重启就可以看到系统已经在板子上运行了。

2. LED程序编写
2.1 driver_led.c 驱动文件编写
主要是如实验原理说的GPMCON寄存器与GPMDAT寄存器的配置
2.1.1 GPMCON寄存器配置
//GPMCON寄存器配置
unsigned tmp;
tmp = readl(S3C64XX_GPMCON);
tmp = (tmp & ~(0x7U<<1))|(0x1U);
writel(tmp, S3C64XX_GPMCON);
先读取GPMCON寄存器的值,将tmp变成0x01再写到GPMCON寄存器上,使LED0的GPM端为输出模式。
2.1.2 GPMDAT寄存器配置
//GPMDAT寄存器
void Led_on(unsigned LEDx)?
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp &=~ (LEDx);
writel(tmp,S3C64XX_GPMDAT);
}
void Led_off(unsigned LEDx)
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp |= (LEDx);
writel(tmp,S3C64XX_GPMDAT);
}
也是一样,先读取GPMDAT寄存器的值,将tmp变成设置值再写到GPMDAT寄存器上。
这里我写了开关函数控制led开关。
2.1.3 led_write函数
//led_write函数
ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
char wbuf[10];
printk("#########write######\n");
copy_from_user(wbuf,buf,count);
switch(wbuf[0])
{
case 0:
Led_on(LED0);
break;
case 1:
Led_on(LED1);
break;
case 2:
Led_on(LED2);
break;
case 3:
Led_on(LED3);
break;
case 4:
Led_off(LED0);
break;
case 5:
Led_off(LED1);
break;
case 6:
Led_off(LED2);
break;
case 7:
Led_off(LED3);
break;
}
我这里是写了一个流水灯,其实这里是一个类似于重载函数的函数,会重载这个源码文件的write函数,下面test.c文件会体现。
2.2 test函数编写
//轮询函数
while(1)
{
for(i=0;i<8;++i)
{
write(fd,&buf[i],1);
sleep(1);
}
}
这里的write其实是之前驱动文件的led_write函数,会按顺序实现led_write里流水灯的功能,copy_from_user(wbuf,buf,count);就是去打开文件重载。
2.3 Makefile文件编写
这里不赘述了,主要关注这个:
KDIR := /root/forlinx/linux-3.0.1
这里是把驱动文件包含的意思,导入这里的驱动文件。
3. 编译程序
Linux下打开自己写的led程序位置
cd led
make
arm-linux-gcc test.c -o test
编译好后大致这个样子,我之前已经编译过了,第一次的make会长一点。

4. 运行程序
将led程序make跟gcc编译后所有文件拷贝到SD卡,再将SD卡插到开发板上。
打开开发板上的终端
然后在里面输入
cd sdcard/ #打开SD卡文件夹
insmod driver_led.ko #加载驱动
mknod /dev/my_led c 240 0 #创建设备文件
./test #运行测试
我们就可以看到流水灯了。
五、实验程序(包括流程图)
5.1 流程图

5.2 实验代码
具体实验代码文件见我的github:
实验代码
六、实验演示
6.1 点灯演示:

6.2 流水灯演示:
视频我也在GitHub上传了:
流水灯
七、心得体会
此次实验无论是从硬件驱动底层还是上位机系统管理都有了很深刻的学习,简单的点灯让我熟悉了Linux开发环境,简单学习Linux系统指令,同时对ARM的底层有了学习,总之学到很多,收获颇丰。