itop4412驱动笔记1

2018-08-04  本文已影响0人  嵌入式工作

总纲

image.png

1. 物理地址找到虚拟地址方法(ioremap)

2.cpu性能

-ARM7 处理速度为0.9MIPS/MHz, 常见的主时钟一般为20MHz-133MHz
– ARM9 处理速度为1.1MIPS/MHz, 常见的主时钟一般为100MHz-233MHz
– CORTEX-A9 处理速度2.5 MIPS/MHz ,主时钟一般为1000MHz-1600MHz

3.最简Linux驱动

• Linux头文件位置
include <linux/module.h>
include <linux/init.h>

– 入口函数module_init(x)
– 出口函数module_exit(x)

– MODULE_LICENSE("Dual BSD/GPL")添加遵循GPL协议,必须的!
– MODULE_AUTHOR(“kerwin”)代码作者
打印信息

printk(KERN_EMERG "Hello World enter!\n");

Makefile编写

#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件itop4412_hello.o
obj-m += mini_linux_module.o 

#源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

#当前目录变量
PWD ?= $(shell pwd)

#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:
    make -C $(KDIR) M=$(PWD) modules
        
#make clean执行的操作是删除后缀为o的文件
clean:
    rm -rf *.o

4,kconfig makefile

4.1kconfig文件,配置宏vim drivers/char/Kconfig

config LEDS_CTL
        bool "Enable LEDS config"
        default y
        help
          Enable LEDS config

4.2makeconfig文件,根据宏,添加源码

vim drivers/char/Makefile

obj-$(CONFIG_LEDS_CTL)          += itop4412_leds.o

5.总线设备驱动注册流程

一般的驱动是先注册设备再注册驱动
热插拔的设备是先注册驱动后注册设备

查看总线 ls /sys/bus 里面可以看到platform 总线
查看设备号 cat /proc/devices

5.1.设备注册方法

vim include/linux/platform_device.h

struct platform_device {
        const char      * name;
        int             id;
        struct device   dev;
        u32             num_resources;
        struct resource * resource;

        const struct platform_device_id *id_entry;

        /* MFD cell pointer */
        struct mfd_cell *mfd_cell;

        /* arch specific additions */
        struct pdev_archdata    archdata;
};

#define platform_get_device_id(pdev)    ((pdev)->id_entry)

#define to_platform_device(x) container_of((x), struct platform_device, dev)

extern int platform_device_register(struct platform_device *);
extern void platform_device_unregister(struct platform_device *);

注册设备。将设备结构体放到平台文件中,会自动注册设备,不用去调
用注册设备的函数

vim arch/arm/mach-exynos/mach-itop4412.c

#ifdef CONFIG_HELLO_CTL
struct platform_device s3c_device_hello_ctl =
{
.name = "hello",
.id = -1,
};
#endif

注册完之后在虚拟平台总线下可以查到注册的设备
– ls /sys/devices/platform/

5.2.驱动注册方法

驱动注册使用结构体platform_driver,该结构体在头文件“vim
include/linux/platform_device.h”中

struct platform_driver {
        int (*probe)(struct platform_device *);
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
        const struct platform_device_id *id_table;
};

extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *);

probe函数
– platform_match函数匹配之后,驱动调用的初始化函数
• remove函数
– 移除驱动函数
• suspend函数
– 悬挂(休眠)驱动函数
device_driver数据结构的两个参数
– name和注册的设备name要一致
– owner一般赋值THIS_MODULE

#include <linux/init.h>
#include <linux/module.h>


/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>

#define DRIVER_NAME "hello"  //必须和设备注册的一致

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");


int hello_probe(struct platform_device *pdev)
{
  printk(KERN_EMERG "hello_probe call \n");
  return 0;
  
}

int hello_remove(struct platform_device *pdev)
{
    printk(KERN_EMERG"remove call \n");
    return 0;
}
void hello_shutdown(struct platform_device *pdev)
{
   printk(KERN_EMERG"shutdown call \n");
}
int hello_suspend(struct platform_device *pdev, pm_message_t state)
{
     printk(KERN_EMERG"suspend call \n");
    return 0;
}
int hello_resume(struct platform_device * pdev)
{
    
     printk(KERN_EMERG"resume call \n");
    return 0;
}

struct platform_driver  stu_hello={
        .probe=hello_probe,
        .remove=hello_remove,
        .shutdown=hello_shutdown,
        .suspend=hello_suspend,
        .resume=hello_resume,
       .driver={
           .name = DRIVER_NAME,
           .owner = THIS_MODULE,
       },
    
};

static int hello_init(void)
{
    int err;
    printk(KERN_EMERG "hello world enter\n");
    err=platform_driver_register(&stu_hello);
     printk(KERN_EMERG "register result:%d\n",err);
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "hello world exit\n");
    platform_driver_unregister(&stu_hello);

}
module_init(hello_init);
module_exit(hello_exit);



上一篇下一篇

猜你喜欢

热点阅读