天天看點

Linux系統移植實驗---LED驅動的移植實驗六  LED驅動的移植

實驗六  LED驅動的移植

【實驗目的】

1. 驅動程式的編譯

2. 應用程式如何打開/操作裝置

【實驗環境】

• 主機:ubuntu 12.04發行版

• 目标機:FS4412平台

• 交叉編譯工具:arm-none-linux-gnueabi-gcc

【實驗步驟】

1. 添加驅動檔案

将實驗代碼Led_test/fs4412_led_drv.c拷貝到drivers/char下

2. 修改drivers/char/Kconfig

在menu "Character devices"下面

添加如下内容:

config  FS4412_LED

tristate "FS4412  LED  Device Support"

  depends  on  ARCH_EXYNOS4

    help

   support  led  device  on  FS4412  develop  board

3. 修改drivers/char/Makefile

在檔案最後添加如下代碼

obj-$(CONFIG_FS4412_LED) += fs4412_led_drv.o

4. 将s5pv210_led_app.c拷貝到Linux任意目錄下并交叉編譯測試程式

$ arm-none-linux-gnueabi-gcc  fs4412_led_app.c  –o  fs4412_led_app  

sudo  cp  fs4412_led_app   /source/rootfs

5. 編譯LED驅動到核心中

Ø 配置核心時按“空格”選擇,配置完成後儲存退出

$ make menuconfig

Device Drivers  --->  

Character devices  --->  

<*> FS4412  LED  Device Support

Ø 儲存退出,重新編譯後把uImage拷貝到tftpboot下

$ make  uImage

$ cp  arch/arm/boot/uImage  /tftpboot

重新啟動開發闆,加載核心并運作。在終端下執行下面操作

Ø 建立裝置節點

# mknod  /dev/led  c  500  0

Ø 運作測試程式并觀察現象

# ./fs4412_led_app

6. 編譯LED驅動為子產品

Ø 配置核心時按“空格”選擇,配置完成後儲存退出

$ make menuconfig

Device Drivers  --->  

Character devices  --->  

<M> FS4412  LED  Device  Support

Ø 儲存退出,重新編譯後把zImage拷貝到tftpboot下,把驅動子產品拷貝到/source/rootfs下

$ make  uImage  modules

$ cp  arch/arm/boot/uImage   /tftpboot/

$ cp  drivers/char/fs4412_led_drv.ko  /source/rootfs/

重新啟動開發闆,linux運作起來後在終端下操作

Ø 建立裝置節點

# mknod  /dev/led  c  500  0

Ø 加載LED驅動子產品

# insmod  fs4412_led_drv.ko

Ø 運作測試程式并觀察現象

# ./fs4412_led_app

fs4412_led_drv.c源代碼如下:

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/cdev.h>

#include <asm/io.h>

#include <asm/uaccess.h>

MODULE_LICENSE("Dual BSD/GPL");

#define LED_MAGIC 'L'

#define LED_ON _IOW(LED_MAGIC, 0, int)

#define LED_OFF _IOW(LED_MAGIC, 1, int)

#define LED_MA 500

#define LED_MI 0

#define LED_NUM 1

#define FS4412_GPX2CON 0x11000C40

#define FS4412_GPX2DAT 0x11000C44

static unsigned int *gpx2con;

static unsigned int *gpx2dat;

struct cdev cdev;

static int s5pv210_led_open(struct inode *inode, struct file *file)

{

return 0;

}

static int s5pv210_led_release(struct inode *inode, struct file *file)

{

return 0;

}

static long s5pv210_led_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

int nr;

switch (cmd) {

case LED_ON:

writel(readl(gpx2dat) | 1 << 7, gpx2dat);

break;

case LED_OFF:

writel(readl(gpx2dat) & ~(1 << 7), gpx2dat);

break;

}

return 0;

}

struct file_operations s5pv210_led_fops = {

.owner = THIS_MODULE,

.open = s5pv210_led_open,

.release = s5pv210_led_release,

.unlocked_ioctl = s5pv210_led_unlocked_ioctl,

};

static int s5pv210_led_init(void)

{

dev_t devno = MKDEV(LED_MA, LED_MI); 

int ret;

ret = register_chrdev_region(devno, LED_NUM, "newled");

if (ret < 0) {

printk("register_chrdev_region\n");

return ret;

}

cdev_init(&cdev, &s5pv210_led_fops);

cdev.owner = THIS_MODULE;

ret = cdev_add(&cdev, devno, LED_NUM);

if (ret < 0) {

printk("cdev_add\n");

goto err1;

}

gpx2con = ioremap(FS4412_GPX2CON, 4);

if (gpx2con == NULL) {

printk("ioremap gpx2con\n");

ret = -ENOMEM;

goto err2;

}

gpx2dat = ioremap(FS4412_GPX2DAT, 4);

if (gpx2dat == NULL) {

printk("ioremap gpx2dat\n");

ret = -ENOMEM;

goto err3;

}

writel((readl(gpx2con) & ~(0xf << 28)) | (0x1 << 28), gpx2con);

writel(readl(gpx2dat) & ~(0x1<<7), gpx2dat);

printk("Led init\n");

return 0;

err3:

iounmap(gpx2con);

err2:

cdev_del(&cdev);

err1:

unregister_chrdev_region(devno, LED_NUM);

return ret;

}

static void s5pv210_led_exit(void)

{

dev_t devno = MKDEV(LED_MA, LED_MI);

iounmap(gpx2dat);

iounmap(gpx2con);

cdev_del(&cdev);

unregister_chrdev_region(devno, LED_NUM);

printk("Led exit\n");

}

module_init(s5pv210_led_init);

module_exit(s5pv210_led_exit);

fs34412_led_app.c源碼如下:

#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/ioctl.h>

#define LED_MAGIC 'L'

#define LED_ON _IOW(LED_MAGIC, 0, int)

#define LED_OFF _IOW(LED_MAGIC, 1, int)

int main(int argc, char **argv)

{

int fd;

fd = open("/dev/led", O_RDWR);

if (fd < 0) {

perror("open");

exit(1);

}

while(1)

{

ioctl(fd, LED_ON);

usleep(100000);

ioctl(fd, LED_OFF);

usleep(100000);

}

return 0;

}

繼續閱讀