Linux内核驱动开发-符设备开发-001Led驱动
/*************************************************************************
> File Name: led.c
> Author: yas
> Mail: rage_yas@hotmail.com
> Created Time: 2024年04月21日 星期日 16时20分42秒
************************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#if 0
/*数据类型重定义*/
typedef unsigned char u8;
typedef unsigned int u32;
#endif
#define DEVICE_MAJOR 200
#define DEVICE_NAME "led_device"
/*寄存器地址映射*/
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
/**/
unsigned int *regGPBCON;
unsigned int *regGPBDAT;
/*led函数声明*/
void led_init(void);
void led_off(void);
void led_on(u8 n);
void led_on_off(u8 n);
void delay_nms(u32 t);
/*驱动函数声明*/
void r_ioremap(void);
static int __init led_driver_init(void);
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static void __exit led_driver_exit(void);
int led_driver_open(struct inode *node, struct file *fp);
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
int led_driver_close(struct inode *node, struct file *fp);
/*定义结构体变量*/
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = led_driver_open,
.read = led_driver_read,
.write = led_driver_write,
.release = led_driver_close
};
#if 1
/*******************************************************************************
* 函 数 名 : r_ioremap
* 函数功能 : 寄存器映射
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void r_ioremap(void)
{
/*寄存器映射*/
regGPBCON = ioremap(GPBCON, 4);//【源地址】【需要映射的地址大小】<返回目标地址>
regGPBDAT = ioremap(GPBDAT, 4);
}
#endif
#if 0
static int __init led_driver_init(void)
{
unsigned int t;
/*注册字符设备*/
register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);
/*寄存器映射*/
regGPBCON = ioremap(GPBCON, 4);//【源地址】【需要映射的地址大小】<返回目标地址>
regGPBDAT = ioremap(GPBDAT, 4);
t = *regGPBCON;
t &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
t |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
*regGPBCON = t;
printk("led_driver_init OK\n");
return 0;
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : led_driver_init
* 函数功能 : led驱动初始化
* 输 入 :无
* 输 出 :无
*******************************************************************************/
static int __init led_driver_init(void)
{
/*注册字符设备*/
register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);
/*寄存器映射*/
r_ioremap();//每次调用led函数都要先调用寄存器映射函数?
/*led初始化*/
led_init();
printk("led_driver_init OK\n");
return 0;
}
#endif
#if 1
int led_driver_open(struct inode *node, struct file *fp)
{
return 0;
}
#endif
#if 1
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{
return 0;
}
#endif
#if 0
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
char n;
unsigned int t;
copy_from_user(&n, user_buffer, 1);
n &= 0x0F;
t = *regGPBDAT;
t &= ~(0x0F << 5);
t |= n << 5;
*regGPBDAT = t;
return 1;
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : led_driver_write
* 函数功能 : led驱动写数据
* 输 入 :
* fp:
* user_buffer:
* offset:
* 输 出 :无
*******************************************************************************/
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
char n;
copy_from_user(&n, user_buffer, 1);
led_on(n);
return 1;
}
#endif
#if 1
int led_driver_close(struct inode *node, struct file *fp)
{
return 0;
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : led_driver_exit
* 函数功能 : 退出led驱动
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
static void __exit led_driver_exit(void)
{
unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);
printk("led_driver_exit OK\n");
}
#endif
/*=========================led配置函数=========================*/
/*******************************************************************************
* 函 数 名 : led_init
* 函数功能 : LED初始化
* 输 入 :无
* 输 出 :无
*******************************************************************************/
//LED1-GPB5,LED2-GPB6,LED3-GPB7,LED4-GPB8
void led_init(void)
{
u32 t=0;
t=*regGPBCON;//思考点:这里为何要使用中间变量配置寄存器?
t&=~((3<<10)|(3<<12)|(3<<14)|(3<<16));//LED控制引脚清0
t|=(1<<10|1<<12|1<<14|1<<16);//LED控制引脚配置-输出状态
*regGPBCON=t;//配置端口B引脚
led_off();//初始化LED为关闭
}
/*******************************************************************************
* 函 数 名 : led_on
* 函数功能 : 打开指定的LED
* 输 入 :
n:打开第几个LED
* 输 出 : 无
*******************************************************************************/
void led_on(u8 n)
{
u8 i=0;
for(i=0;i<n;i++)
{
*regGPBDAT&=~(1<<(4+n));//配置端口B的数据寄存器
}
// *regGPBDAT&=~(1<<5);//配置端口B的数据寄存器
}
/*******************************************************************************
* 函 数 名 : led_on_off
* 函数功能 : 指定的LED闪烁
* 输 入 :
n:第几个LED闪烁
* 输 出 : 无
*******************************************************************************/
void led_on_off(u8 n)
{
led_on(n);
delay_nms(2000);
led_off();
delay_nms(2000);
}
/*******************************************************************************
* 函 数 名 : led_off
* 函数功能 : 关闭LED
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void led_off(void)
{
*regGPBDAT|=(1<<5|1<<6|1<<7|1<<8);//配置端口B的数据寄存器
}
/*******************************************************************************
* 函 数 名 : delay_nms
* 函数功能 : 延时nms
* 输 入 :
* t:延时时间
* 输 出 : 无
*******************************************************************************/
void delay_nms(u32 t)
{
u32 i=0;
u32 j=0;
for(i=0;i<t;i++)
{
for(j=0;j<100;j++);
}
}
module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");