平台总线(三)
来源:互联网 发布:java自动代码生成器 编辑:程序博客网 时间:2024/04/26 09:26
平台总线:用于平台升级的
三星:
s3c2410 --------------- s3c6410 ----------- s5pv210
gpio控制器 gpio控制器gpio控制器
uart
i2c
spi
控制逻辑方法相同:1,配置gpio寄存器
2.读写数据
地址会不同
三元素:
总线: 开机的时候就已经创建了,不需要我们创建
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
device对象:
struct platform_device {//是一个名字,描述设备属性
const char * name; //用于匹配
int id;
struct device dev; //继承父类
u32 num_resources;
struct resource* resource; // 描述设备的资源---地址和中断
};
struct resource {
resource_size_t start; //起始位置
resource_size_t end; //结束位置
const char *name; //自定义
unsigned long flags;//区分是地址还是中断资源:IORESOURCE_IRQ, IORESOURCE_MEM
}
driver对象
struct platform_driver {
int (*probe)(struct platform_device *);//表示匹配成功之后被调用
int (*remove)(struct platform_device *);
struct device_driver driver;//继承父类
const struct platform_device_id *id_table;//用于匹配
};
pdrv中获取资源:
/**
* 参数1: pdev
* 参数2: 获取的是中断资源还是内存资源
* 参数3: 同种资源中第几个
*/
struct resource * platform_get_resource(struct platform_device * dev,unsigned int type,unsigned int num)
在probe方法中:
1,申请主设备号 register_chrdev_region (与内核相关)
2,注册字符设备驱动 cdev_alloc cdev_init cdev_add (与内核相关)
3,利用udev/mdev机制创建设备文件(节点) class_create, device_create (与内核相关)
4,实现操作硬件方法 xxx_open,xxx_read,xxxx_write...(与硬件相关)
5,硬件初始化
最重要的:
三星:
s3c2410 --------------- s3c6410 ----------- s5pv210
gpio控制器 gpio控制器gpio控制器
uart
i2c
spi
控制逻辑方法相同:1,配置gpio寄存器
2.读写数据
地址会不同
三元素:
总线: 开机的时候就已经创建了,不需要我们创建
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
device对象:
struct platform_device {//是一个名字,描述设备属性
const char * name; //用于匹配
int id;
struct device dev; //继承父类
u32 num_resources;
struct resource* resource; // 描述设备的资源---地址和中断
};
struct resource {
resource_size_t start; //起始位置
resource_size_t end; //结束位置
const char *name; //自定义
unsigned long flags;//区分是地址还是中断资源:IORESOURCE_IRQ, IORESOURCE_MEM
}
driver对象
struct platform_driver {
int (*probe)(struct platform_device *);//表示匹配成功之后被调用
int (*remove)(struct platform_device *);
struct device_driver driver;//继承父类
const struct platform_device_id *id_table;//用于匹配
};
pdrv中获取资源:
/**
* 参数1: pdev
* 参数2: 获取的是中断资源还是内存资源
* 参数3: 同种资源中第几个
*/
struct resource * platform_get_resource(struct platform_device * dev,unsigned int type,unsigned int num)
在probe方法中:
1,申请主设备号 register_chrdev_region (与内核相关)
2,注册字符设备驱动 cdev_alloc cdev_init cdev_add (与内核相关)
3,利用udev/mdev机制创建设备文件(节点) class_create, device_create (与内核相关)
4,实现操作硬件方法 xxx_open,xxx_read,xxxx_write...(与硬件相关)
5,硬件初始化
最重要的:
获取到资源,利用资源进行硬件初始化
/* led_test.c */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main(void){int fd;int on;fd = open("/dev/led0", O_RDWR);while (1) {on = 1;write(fd,&on, 4);sleep(1);on = 0;write(fd,&on, 4);sleep(1);}close(fd);return 0;}
/* plat_led_dev.c */#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#define GPC0CON 0xE0200060#define GPC_SIZE 24//用于演示,没有实际设备对应#define GPA0CON 0xE0200000#define GPA_SIZE 24struct resource led_res[] = {/*实际所用到的*/[0] = {.start = GPC0CON,.end = GPC0CON + GPC_SIZE - 1,.flags = IORESOURCE_MEM,},/*假如有其他的资源,比如有中断*/[1] = {.start = 888,.end = 1212,.flags = IORESOURCE_IRQ,},[2] = {.start = GPA0CON,.end = GPA0CON + GPC_SIZE - 1,.flags = IORESOURCE_MEM,},};struct platform_device led_pdev = {.name = "s5pv210_led",.id = -1,.num_resources = ARRAY_SIZE(led_res),.resource = led_res,};static int __init plat_led_dev_init(void){/*注册一个平台设备*/ printk("------*_^%s--------\n",__FUNCTION__); return platform_device_register(&led_pdev);}static void __exit plat_led_dev_exit(void){/*注销平台设备*/platform_device_unregister(&led_pdev); printk("------*_^%s--------\n",__FUNCTION__);}module_init(plat_led_dev_init);module_exit(plat_led_dev_exit);MODULE_LICENSE("GPL");
/* plat_led_drv.c */#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/fs.h>#include <linux/slab.h>#include <asm/uaccess.h>#include <asm/io.h>/*设计一个对象,表示一个全局的设备对象*/struct samsung_led{int dev_major;struct class *cls;struct device *dev;struct resource *res;void *reg_addr; //虚拟地址};struct samsung_led * led_dev;int led_pdrv_open(struct inode *inode, struct file *filp){printk("-------^_* %s-----------\n", __FUNCTION__);return 0;}ssize_t led_pdrv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos){int value;int ret;ret = copy_from_user(&value, buf, count);if (ret > 0) {printk("copy_from_user error\n");return -EFAULT;}if (value) {//点灯__raw_writel(__raw_readl(led_dev->reg_addr + 4) | (0x3<<3), led_dev->reg_addr + 4);}else{__raw_writel(__raw_readl(led_dev->reg_addr + 4) & ~(0x3<<3), led_dev->reg_addr + 4);}return count;}int led_pdrv_close(struct inode *inode, struct file *filp){printk("-------^_* %s-----------\n", __FUNCTION__);return 0;}struct file_operations led_fops = {.open = led_pdrv_open,.write = led_pdrv_write,.release = led_pdrv_close,};int led_pdrv_probe(struct platform_device *pdev){/*需要向应用空间提供接口1,申请设备号2,创建文件*/printk("-------^_* %s-----------\n", __FUNCTION__);/*申请空间*/led_dev = kzalloc(sizeof(struct samsung_led), GFP_KERNEL); /*动态申请设备*/led_dev->dev_major = register_chrdev(0, "led_drv", &led_fops);/*创建设备类*/led_dev->cls = class_create(THIS_MODULE, "led_cls");/*创建字符设备*/led_dev->dev = device_create(led_dev->cls,NULL, MKDEV(led_dev->dev_major, 0), NULL, "led%d", 0);led_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//可以进行映射led_dev->reg_addr = ioremap(led_dev->res->start, resource_size(led_dev->res));//获取中断int irqno = platform_get_irq(pdev, 0);printk("irqno = %d\n", irqno );// 配置gpio为输出unsigned int temp = __raw_readl(led_dev->reg_addr);temp &= ~(0xff<<12);temp |= (0x11<<12);__raw_writel(temp,led_dev->reg_addr);return 0;}int led_pdrv_remove(struct platform_device *pdev){iounmap(led_dev->reg_addr);device_destroy(led_dev->cls,MKDEV(led_dev->dev_major, 0));class_destroy(led_dev->cls);unregister_chrdev(led_dev->dev_major,"led_drv");kfree(led_dev);return 0;}/*用于匹配*/const struct platform_device_id led_id_table[] = {{"s3c2410_led", 1111},{"s3c6410_led", 2222},{"s5pv210_led", 3333},};struct platform_driver led_drv = {.probe = led_pdrv_probe,.remove = led_pdrv_remove,.driver = {.name = "s5pv210_led"// 随便写,用于匹配,/sys/bus/platform/drivers/samsung_led_drv},.id_table = led_id_table,//优先匹配列表中的名字,如果没有列表,就匹配父类中name};static int __init plat_led_drv_init(void){/*注册一个平台驱动*/ printk("------*_^%s--------\n",__FUNCTION__); return platform_driver_register(&led_drv);}static void __exit plat_led_drv_exit(void){/*注销平台驱动*/platform_driver_unregister(&led_drv);printk("------*_^%s--------\n",__FUNCTION__);}module_init(plat_led_drv_init);module_exit(plat_led_drv_exit);MODULE_LICENSE("GPL");
# MakefileROOTFS_DIR = /opt/filesystemMODULE_NAME = plat_led_devMODULE_NAME2 = plat_led_drvAPP_NAME = led_testCROSS_COMPILE = arm-cortex_a8-linux-gnueabi-CC = $(CROSS_COMPILE)gccifeq ($(KERNELRELEASE), )KERNEL_DIR = /home/linux-3.0.8CUR_DIR = $(shell pwd)all :make -C $(KERNEL_DIR) M=$(CUR_DIR) modules$(CC) $(APP_NAME).c -o $(APP_NAME)clean :make -C $(KERNEL_DIR) M=$(CUR_DIR) cleanrm -rf $(APP_NAME)install:cp -raf *.ko $(APP_NAME) $(ROOTFS_DIR)/drv_moduleelseobj-m = $(MODULE_NAME).oobj-m += $(MODULE_NAME2).oendif
0 0
- 平台总线(三)
- 平台总线(一)
- 平台总线(二)
- SOI总线(三)
- 统一数据交换平台(服务总线)的三大特点
- 平台总线
- 平台总线
- 平台总线
- CAN总线基础知识(三)
- CAN总线基础知识(三)
- CAN总线基础知识(三)
- CAN总线基础知识(三)
- CAN总线基础知识(三)
- CAN总线基础知识(三)
- CAN总线基础(三)
- CAN总线基础知识(三)
- can总线协议(三)
- 09-S3C2440驱动学习(三)嵌入式linux-platform平台总线驱动程序及分离分层构建驱动框架
- OSI,TCP/IP,五层协议的体系结构,以及各层协议
- C++中sprintf()函数的使用详解
- 二叉树的建立与遍历
- MySQL练习题
- 【深入Java虚拟机】之四:类加载机制
- 平台总线(三)
- HDU 3622 Bomb Game【2-SAT + tarjan】
- ASSERT(断言)的用法
- 关于基于51单片机的MP3的总体设计
- 浅谈C++多态性
- 【深入Java虚拟机】之五:多态性实现机制——静态分派与动态分派
- JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
- [LeetCode]24. Swap Nodes in Pairs
- 「iOS 100天学习计划」第二十天