以移植自己制作的驱动,学习内核移植中的驱动移植,及 驱动程序的动态编译和静态编译
硬件环境:
Linux 内核版本:Linux 3.14
主机:Ubuntu 12.04发行版
目标机:FS4412平台
交叉编译工具:arm-none-linux-gnueabi-gcc
一、静态编译
1、添加驱动文件
将写好的实验代码fs4412_led_drv.c 拷贝到 drivers/char 下
fs4412_led_drv.c 如下:
#include #include #include #include #include #include MODULE_LICENSE("Dual BSD/GPL"); #define LED_MAGIC 'L' /* * need arg = 1/2 */ #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_regionn"); return ret; } cdev_init(&cdev, &s5pv210_led_fops); cdev.owner = THIS_MODULE; ret = cdev_add(&cdev, devno, LED_NUM); if (ret < 0) { printk("cdev_addn"); goto err1; } gpx2con = ioremap(FS4412_GPX2CON, 4); if (gpx2con == NULL) { printk("ioremap gpx2conn"); ret = -ENOMEM; goto err2; } gpx2dat = ioremap(FS4412_GPX2DAT, 4); if (gpx2dat == NULL) { printk("ioremap gpx2datn"); ret = -ENOMEM; goto err3; } writel((readl(gpx2con) & ~(0xf << 28)) | (0x1 << 28), gpx2con); writel(readl(gpx2dat) & ~(0x1<<7), gpx2dat); printk("Led initn"); 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 exitn"); } module_init(s5pv210_led_init); module_exit(s5pv210_led_exit); 2、修改drivers/char/Kconfig 在menu "Character devices"下面添加如下内容: 可以看到 配置界面里已经有该配置选项 打开help看一下,和我们写的都一样 3、修改 drivers/char/Makefile 在文件最后添加如下代码 4、将 fs4412_led_app.c 拷贝到linux 下任意目录下并交叉编译测试程序 具体代码如下: #include #include #include #include #include #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; } 5、静态编译LED驱动 a -- 配置内核时按“空格”选择,配置完成后保存退出 注意:这里是 * 号,是Y,要编进内核的 b -- 保存退出,重新编译后把 uImage 拷贝到tftpboot 下 make uImage cp arch/arm/boot/uImage /tftpboot 重启开发板,加载内核并运行,在终端下执行下面操作 c -- 创建设备节点 mkdnod /dev/ledc 5000 注:设备号 cat/proc/devices 查看 d -- 运行测试程序并观察现象 ./fs4412_led_test 二、动态编译 1、配置内核时按“空格”选择,配置完成后保存退出 注意:这里选择是M,编成模块。 2、保存退出,重新编译后把uImage 拷贝到tftpboot下,把驱动模块拷贝到 /nfsroot/rootfs 下 make uImage modules cp arch/arm/boot/uImage /tftpboot cp drivers/char/fs4412_led_drv.ko /nfsroot/rootfs 重新启动开发板,linux运行起来后在终端下操作 a -- 创建设备节点 mknod dev/ledc 5000 b -- 加载LED驱动模块 insmod fs4412_led_drv.ko c -- 运行测试程序并观察现象 ./fs4412_led_app
上一篇:Exynos4412 内核移植(六)—— 设备树解析
下一篇:Exynos4412 Uboot 移植(四)—— Uboot引导内核过程分析
推荐阅读最新更新时间:2024-11-21 09:51