Skip to content

Instantly share code, notes, and snippets.

@creamidea
Created April 18, 2013 07:49
Show Gist options
  • Save creamidea/5410963 to your computer and use it in GitHub Desktop.
Save creamidea/5410963 to your computer and use it in GitHub Desktop.
led.c arm入门练习 交叉编译
#include "led.h"
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h> /* Param header */
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <asm/uaccess.h> /* 资源控制 */
#include <linux/sched.h> /* 进程控制 */
#include <asm/io.h> /* 内存读写方法
* read: ioread32
* write: iowrite32*/
#define DRIVER_AUTHOR "icecream <[email protected]>"
#define DRIVER_DESC "A sample driver"
/* 引入两个变量 */
module_param(mymajor, int, 0644);
module_param(name, charp, 0644);
/* 自己封装,以自己需求 */
struct led_dev {
struct cdev cdev;
unsigned int* caddr; /* 代表ARM中的控制寄存器 0x56000010 */
unsigned int* daddr; /* 代表ARM中的数据寄存器 0x56000014 */
};
struct led_dev* led_dev; /* 全局指针,方便后面的引用 */
/* 读写操作 */
/* inode描述节点,file描述的是系统中的 */
static int led_open(struct inode* inode, struct file* file)
{
struct led_dev* led_dev;
/* 根据结构体中的一个成员来获取到整个结构体的内容: struct led_dev, cdev */
/* inode 代表一个设备, 后面获取的结构体会放到其中*/
led_dev = container_of(inode->i_cdev, struct led_dev, cdev);
/* 保存led灯的私有数据,让灯与灯之间数据私有 */
file->private_data = led_dev;
/* ACCMODE当前文件权限 */
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
file->f_pos = 0; /* 保证每次写数据从起始写到最后 */
printk ("open suc[w]\n");
}
return 0;
}
static int led_close(struct inode* inode, struct file* file)
{
/* 系统会帮忙清理,这里只是简单的打印提示 */
printk ("led_close Close\n");
return 0;
}
/* 控制灯 */
static void setup(unsigned long num, int p)
{
unsigned int v = *(led_dev->daddr); /* 获取内容 */
if (p) {
/* 灯亮 */
/* 为何+4, 难道是移动到下一个位?0x56000010 */
unsigned int t = ~(0x01 << (num + 4));
v &= t; /* clear 0 */
} else {
/* 灯灭 */
unsigned int t = (0x01 << (num+4));
v |= t; /* set 1 */
}
/* 写回数据寄存器 */
iowrite32(v, led_dev->daddr);
}
/* */
//arg: 第几个灯
//cmd: LED_ON(1), LED_OFF(0)
static int led_ioctl(struct inode* inode, struct file* file
, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case LED_ON:
setup(arg, 1);
break;
default:
setup(arg, 0);
break;
}
return 0;
}
static const struct file_operations fops = {
.open = led_open,
.release = led_close,
.ioctl = led_ioctl,
/* .compat_ioctl = led_ioctl, */
.owner = THIS_MODULE
};
static int __init led_init(void)
{
int ret;
dev_t devno;
unsigned int out = 0;
devno = MKDEV(mymajor, 0);
ret = register_chrdev_region(devno, 1, name);
if (ret < 0) {
alloc_chrdev_region(&devno, 0, 1, name);
mymajor = MAJOR(devno);
}
printk ("Major: %d, Minor: %d\n", mymajor, MINOR(devno));
/* request memory */
led_dev = (unsigned int*)kmalloc(sizeof(led_dev), GFP_KERNEL);
if (led_dev) {
printk ("Get memory successfully!\n");
} else {
printk ("Get memory error!\n");
return ENOMEN;
}
/* 对硬件到初始化 */
/* 从内存空间映射的上层虚拟空间, 4:映射长度 */
led_dev->caddr = (unsigned int*)ioremap(0x56000010, 4);
led_dev->daddr = (unsigned int*)ioremap(0x56000014, 4);
out = *(led_dev->caddr);
/* GPB5/6/7/8 --> 10,11;12,13;14,15;16,17 */
/* 01 01 01 01 */
/* 01 输出 */
out |= 0x01 << 10;
out |= 0x01 << 12;
out |= 0x01 << 14;
out |= 0x01 << 16;
iowrite32(out, led_dev->caddr);
/* iowrite8(): 每次写入8字节 */
/* iowrite16() 半字*/
/* iowrite32() 1个字*/
/* init cdev structor */
cdev_init(&led_dev->cdev, &fops);
led_dev->cdev.owner = THIS_MODULE;
led_dev->cdev.ops = &fops;
if ((cdev_add(&led_dev->cdev, devno, 1))) {
printk ("add successfully!\n");
} else {
printk ("add error!\n");
}
return 0;
}
static void __exit led_exit(void)
{
dev_t devno = MKDEV(mymajor, 0);
cdev_del(&led_dev->cdev);
/* 解除两个映射 */
iounmap(&led_dev->caddr);
iounmap(&led_dev->daddr);
/* 释放空间 */
kfree(led_dev);
led_dev = NULL;
/* 卸载设备 */
unregister_chrdev_region(devno, 1);
printk("Exit the driver module!\n");
}
module_init(led_init); /* enter */
module_exit(led_exit); /* out */
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("Linux Module");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment