tiny 4412 led module

本文介绍了一个用于Tiny4412开发板上的LED控制驱动程序的设计与实现。该驱动通过直接操作GPIO寄存器来控制LED的状态,并提供ioctl接口供用户空间应用程序调用,以实现对LED的开关控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

led.c

#include <linux/init.h>  
#include <linux/kernel.h>  
#include <linux/module.h>  
#include <linux/io.h>  
#include <linux/fs.h>  
#include <linux/ioctl.h>  
#include <linux/miscdevice.h>  

#define DEVICE_NAME     "tiny4412-leds"  

#define GPM4CON     (0x11000000+0x02E0)  
#define GPM4DAT     (0x11000000+0x02E4)  

#define GPM4_0  0  
#define GPM4_1  1  
#define GPM4_2  2  
#define GPM4_3  3  

#define GPM4_ON     0  
#define GPM4_OFF    1  

//幻数  
#define LEDS_MAGIC  'a'  
#define LEDS_PGM4_0_ON      _IO(LEDS_MAGIC, 1)  
#define LEDS_PGM4_0_OFF _IO(LEDS_MAGIC, 2)  
#define LEDS_PGM4_1_ON      _IO(LEDS_MAGIC, 3)  
#define LEDS_PGM4_1_OFF _IO(LEDS_MAGIC, 4)  
#define LEDS_PGM4_2_ON      _IO(LEDS_MAGIC, 5)  
#define LEDS_PGM4_2_OFF _IO(LEDS_MAGIC, 6)  
#define LEDS_PGM4_3_ON      _IO(LEDS_MAGIC, 7)  
#define LEDS_PGM4_3_OFF _IO(LEDS_MAGIC, 8)  


unsigned int *gpm4_con = NULL;  
unsigned int *gpm4_dat = NULL;  


/* 设置IO口输出电平 */  
static void set_gmp4_out(unsigned char cpm4_n, unsigned char status)   
{  
    unsigned int temp;  

    temp = readl(gpm4_dat);  

    if (status == GPM4_ON)   
        temp &=  ~(0x1<<cpm4_n);   
    else  
        temp |= 0x1<<cpm4_n;  

    writel(temp, gpm4_dat);  
}  


static long tiny4412_leds_ioctl(struct file *file, unsigned int cmd,  
                unsigned long arg)  
{  
    switch (cmd) {  
    case LEDS_PGM4_0_ON:  set_gmp4_out(GPM4_0, GPM4_ON);  
        break;  
    case LEDS_PGM4_0_OFF: set_gmp4_out(GPM4_0, GPM4_OFF);  
        break;  
    case LEDS_PGM4_1_ON:  set_gmp4_out(GPM4_1, GPM4_ON);  
        break;  
    case LEDS_PGM4_1_OFF: set_gmp4_out(GPM4_1, GPM4_OFF);  
        break;  
    case LEDS_PGM4_2_ON:  set_gmp4_out(GPM4_2, GPM4_ON);  
        break;  
    case LEDS_PGM4_2_OFF: set_gmp4_out(GPM4_2, GPM4_OFF);  
        break;  
    case LEDS_PGM4_3_ON:  set_gmp4_out(GPM4_3, GPM4_ON);  
        break;  
    case LEDS_PGM4_3_OFF: set_gmp4_out(GPM4_3, GPM4_OFF);  
        break;  
    defautl :  
        break;  
    }  

    return 0;  
}  


static const struct file_operations tiny4412_leds_fops = {  
    .owner      = THIS_MODULE,  
    .unlocked_ioctl = tiny4412_leds_ioctl,  
};  


static struct miscdevice tiny4412_leds_miscdev = {  
    .minor = MISC_DYNAMIC_MINOR,  
    .name = DEVICE_NAME,  
    .fops = &tiny4412_leds_fops,  
};  


static int tiny4412_leds_init(void)   
{  
    unsigned int data;    
    unsigned int ret;  

    //IO初始化,将物理地址映射为虚拟地址  
    gpm4_con = ioremap(GPM4CON, 4);  
    gpm4_dat = ioremap(GPM4DAT, 4);  
    if (!gpm4_con || !gpm4_con) {  
        printk("ioremap faild!\n");  
        goto error1;   
    }  

    /* 将GPM4[0]-GPM4[3]设置为输出 */  
    data = readl(gpm4_con);    
    data &= ~((0xf<<12)|(0xf<<8)|(0xf<<4)|(0xf<<0));   
    data |=  (0x1<<12)|(0x1<<8)|(0x1<<4)|(0x1<<0);   
    writel(data, gpm4_con);   

    ret = misc_register(&tiny4412_leds_miscdev);  //注册混杂设备驱动  
    if (ret) {  
        printk("misc_register faild!\n");  
        goto error2;  
    }  

    printk("tiny4412_leds_init!\n");  

    return 0;  


error2:  
    iounmap(gpm4_con);  
    iounmap(gpm4_dat);  

error1:  
    return -ENOMEM;  

}  


static void tiny4412_leds_exit(void)  
{  
    unsigned int data;  

    misc_deregister(&tiny4412_leds_miscdev);  

    data = readl(gpm4_dat);  
    data |=  (0x1<<3)|(0x1<<2)|(0x1<<1)|(0x1<<0);   
    writel(data, gpm4_dat);  

    iounmap(gpm4_con);  
    iounmap(gpm4_dat);  
    printk("tiny4412_leds_exit!\n");  
}  


MODULE_LICENSE("GPL");  
MODULE_AUTHOR("ChunquanL");  


module_init(tiny4412_leds_init);  
module_exit(tiny4412_leds_exit);

led_test.c

#include <stdio.h>     
#include <sys/types.h>    
#include <sys/stat.h>  
#include <fcntl.h>  
#include <linux/ioctl.h>  

#define DEVICE_NAME     "/dev/tiny4412-leds"  

//幻数  
#define LEDS_MAGIC  'a'  
#define LEDS_PGM4_0_ON      _IO(LEDS_MAGIC, 1)  
#define LEDS_PGM4_0_OFF _IO(LEDS_MAGIC, 2)  
#define LEDS_PGM4_1_ON      _IO(LEDS_MAGIC, 3)  
#define LEDS_PGM4_1_OFF _IO(LEDS_MAGIC, 4)  
#define LEDS_PGM4_2_ON      _IO(LEDS_MAGIC, 5)  
#define LEDS_PGM4_2_OFF _IO(LEDS_MAGIC, 6)  
#define LEDS_PGM4_3_ON      _IO(LEDS_MAGIC, 7)  
#define LEDS_PGM4_3_OFF _IO(LEDS_MAGIC, 8)  


int main (int argc, char *argv[])   
{  
    int leds_fd = 0;  
    int cmd;  

    if  (argc < 2) {  
        printf("please entry the correct operation parameter! \n");  
        return 0;  
    }  

    leds_fd = open(DEVICE_NAME, O_RDWR);  
    if (leds_fd == -1) {  
        printf("open device faild! \n");  
        return 0;  
    }   

    cmd = atoi(argv[1]);        //把终端上收到的字符串命令转换成整型  
    //printf("argv:%s \n", argv[1]);  
        /* 执行 ./led_oper 11 点亮LED1 , 执行./led_oper 10 关闭LED1,其他LED灯以此类推 */  
    switch (cmd) {  
    case 10:  ioctl(leds_fd, LEDS_PGM4_0_OFF);  
        break;  
    case 11:  ioctl(leds_fd, LEDS_PGM4_0_ON);  
        break;  
    case 20:  ioctl(leds_fd, LEDS_PGM4_1_OFF);  
        break;  
    case 21:  ioctl(leds_fd, LEDS_PGM4_1_ON);  
        break;  
    case 30:  ioctl(leds_fd, LEDS_PGM4_2_OFF);  
        break;  
    case 31:  ioctl(leds_fd, LEDS_PGM4_2_ON);  
        break;  
    case 40:  ioctl(leds_fd, LEDS_PGM4_3_OFF);  
        break;  
    case 41:  ioctl(leds_fd, LEDS_PGM4_3_ON);  
        break;  
    defautl :  
        break;  
    }  

    close(leds_fd);  

    return 0;  
} 

Makefile

obj-m := led.o  

KDIR :=/home/can//linux/4412/linux-3.8  # arm  
all:  
    make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-   
    arm-linux-gcc -static led_test.c -o led_test

clean:  
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul* *oper  

编译此段代码与运行此段代码的内核需一致,否则将无法加载模块

使用uname -r 查看内核版本
uname 查看操作系统信息 r选项查看内核版本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值