led驱动程序进阶-使用面向对象的思想完成led驱动程序

上一篇文章实现了一个led驱动程序的模板,该模板虽然只是用于led驱动程序的编写,但是对于其它任何设备的驱动程序编写,其面向对象的思想都是可以借鉴和参考的。任何看似高深的技巧,都是从简单出发的,逐步深入。独孤九剑的最高境界就是无剑、无招,所有高深的变化都是从最基本的原理出发!
本文基于正点原子的imx6ull开发板实现board.c,led电路原理图和所用的GPIO引脚、配置方法见《led驱动实例》那篇文章

点击查看代码
//board_imx6ull.c

#include "led_orp.h"
#include "asm/memory.h"
#include "asm/uaccess.h"
#include "linux/err.h"
#include "linux/export.h"
#include "linux/kdev_t.h"
#include "linux/printk.h"
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/printk.h>
#include <linux/init.h>
#include <asm/io.h>

static unsigned int *CCM_CCGR1;
static unsigned int *IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03;
static unsigned int *GPIO1_GDIR;
static unsigned int *GPIO1_DR;

int led_init(unsigned int which)
{
    unsigned int val;
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    /*
    在配置寄存器前先进行地址映射
    */
    if(!CCM_CCGR1 && which == 0)
    {
        CCM_CCGR1 = ioremap(0x20C406C, 4);
        IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = ioremap(0x20E0068, 4);
        GPIO1_GDIR = ioremap(0X209C004, 4);
        GPIO1_DR = ioremap(0X209C000, 4);
    }

    /*
    使能GPIO1_IO03时钟
    CCGR1[27:26] = b11
    20C_406Ch
    */
    val = *CCM_CCGR1;
    val |= (0x3 << 26);
    *(CCM_CCGR1) = val;

    /*
    配置IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03为GPIO模式
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03[3:0] = b0101
    20E_0068h

    IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03暂时不使用,这是配置引脚的模式,比如上升沿,上下拉电阻等
    */
    val = *IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03;
    val &= ~(0xF);  //低四位清零
    val |= (0x5);   //低四位赋值b0101
    *(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03) = val;

    /*
    配置GPIO1_GDIR寄存器使GPIO1_IO03配置为输出
    GPIO1_GDIR[3] = 1
    209_C004h
    */

    *(GPIO1_DR) |= (0x1 << 3);

    return 1;
}

int led_ctl(unsigned int which, char status)
{
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    /*
    根据status修改GPIO1_IO03的输出
    GPIO1_DR
    209_C000h
    */

    if(which == 0)
    {
        if(status)
        {
            *GPIO1_DR &= ~(1 << 3);

            printk("led on\n");
        }
        else {
            *GPIO1_DR |= (1 << 3);
            printk("led off\n");
        }
    }
    return 0;
}

static struct led_operations led_orp = {
    .init = led_init,
    .ctl = led_ctl,
};

struct led_operations* get_led_operations()
{
    return &led_orp;
}

基于上一篇文章中的模板,只需要实现board_imx6ull.c文件即可,其实就是实现led_orp.h头文件中的函数和结构体,从面向对象的角度来解释就是根据所用的开发板imx6ull创建一个led_orp对象,对象名board_imx6ull

posted @ 2024-04-19 16:24  tstars  阅读(111)  评论(0)    收藏  举报