嵌入式實驗一:LED燈點亮


實驗一:LED燈程序

一、 實驗環境

開發機環境

​ 操作系統:ubuntu 12.04

​ 交叉編譯環境:arm-linux-gcc 4.3.2

​ 6410板子內核源碼:linux-3.0.1

目標板環境:OK6410-A linux-3.0.1

二、 實驗原理

image.png

圖1-OK6410LED原理圖

image.png

圖2-LED原理圖

從上面的原理圖可以得知,LED與CPU引腳的連接方法如下,低電平點亮。

LED1 -GPM0

LED2 -GPM1

LED3 -GPM2

LED4 -GPM3

image.png

通過上面可以得知,需要先將GPM0設置為輸出方式。將相應的寄存器進行配置。然后將GPMDAT寄存器的第0位置0燈亮,置1燈滅。

三、 實驗代碼

1.編寫驅動程序

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* copy_to_user,copy_from_user */
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-m.h>
#include <plat/gpio-cfg.h>

#define LED_MAJOR 240

int led_open(struct inode *inode, struct file *filp)

{
	unsigned tmp;
	tmp = readl(S3C64XX_GPMCON);
	tmp = (tmp & ~(0x7U << 1)) | (0x1U);
	writel(tmp, S3C64XX_GPMCON);
	printk("#########open######\n");
	return 0;
}

ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	printk("#########read######\n");
	return count;
}

ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	char wbuf[10];
	unsigned tmp;
	printk("#########write######\n");
	copy_from_user(wbuf, buf, count);
	switch (wbuf[0])
	{
	case 0: //off
		tmp = readl(S3C64XX_GPMDAT);
		tmp |= (0xfU);
		writel(tmp, S3C64XX_GPMDAT);
		break;
	case 1: //on
		tmp = readl(S3C64XX_GPMDAT);
		tmp &= ~(0xfU);
		writel(tmp, S3C64XX_GPMDAT);
		break;
	default:
		break;
	}
	return count;
}

int led_release(struct inode *inode, struct file *filp)
{
	printk("#########release######\n");
	return 0;
}

struct file_operations led_fops = {
	.owner = THIS_MODULE,
	.open = led_open,
	.read = led_read,
	.write = led_write,
	.release = led_release,
};

int __init led_init(void)
{
	int rc;
	printk("Test led dev\n");
	rc = register_chrdev(LED_MAJOR, "led", &led_fops);
	if (rc < 0)
	{
		printk("register %s char dev error\n", "led");
		return -1;
	}
	printk("ok!\n");
	return 0;
}

void __exit led_exit(void)
{
	unregister_chrdev(LED_MAJOR, "led");
	printk("module exit\n");
	return;
}

module_init(led_init);
module_exit(led_exit);

2.編寫Makefile文件

ifneq ($(KERNELRELEASE),)
obj-m := driver_led.o
else 
KDIR := /work/linux-3.0.1
all:
	make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif

3.編寫測試文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (void)
{
	int fd;
	char buf[10]={0,1,0,1};
	fd = open("/dev/my_led",O_RDWR);
	if (fd < 0)
	{
		printf ("Open /dev/my_led file error\n");
		return -1;
	}	
	while(1)
	{
		write(fd,&buf[0],1);
		sleep(1);
		write(fd,&buf[1],1);
		sleep(1);

	}
	close (fd);
	return 0;

}

四、 實驗步驟

1、編譯驅動程序和測試程序

在終端中運行:#make命令,編譯成功生生下列文件

在終端中運行:#arm-linux-gcc test.c -o test,編譯成功生成文件

2、將文件拷貝到SD卡

3、將SD卡插入到OK6410開發板中

4、在OK6410終端中運行程序

加載驅動:#insmod sdcard/driver_led.ko

創建設備文件:# mknod /dev/my_led c 240 0

運行測試文件:#./sdcard/test

卸載驅動程序:#rmmod sdcard/driver_led.ko

5、運行結果

此時可以看到OK6410開發板的4個LED燈一直同時點亮,然后熄滅。

6、更改驅動程序里的代碼可實現不同的功能

五、 實驗總結

本次實驗主要是熟悉交叉編譯,測試的步驟,理解驅動程序和測試代碼之間的關系,為后續更復雜的程序開發做准備。理解代碼的實際意義,可以對代碼進行二次開發。在實驗過程中遇到的困難:Makefile文件命名要正確,文件內容格式要正確,注意Tab鍵的使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM