#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
/* 初始化设备号,定义设备名*/
int Major = 0;
#define CNAME "MyGpio"
/*
* LED基地址,以及虚拟弟子
*/
#define LED_OUTPUT 0x43810040
#define LED_MODE 0x43810054
unsigned int * LedOutPut = NULL;
unsigned int * LedMode = NULL;
struct class * Cls1;
struct device * Dev1;
/*
* 存储向应用从发送的数据
*/
char KBuf = 0;
ssize_t GpioWrite(struct file *file, const char __user *ubuf, size_t size, loff_t *offs)
{
int ret;
/*
* 调用函数将灯熄灭
*/
*(LedOutPut) &= ~(1<<4);
*(LedOutPut) &= ~(1<<12);
*(LedOutPut) &= ~(1<<13);
printk("this is write\n");
ret = copy_from_user(&KBuf,ubuf,1);
if(ret){
printk("copyfrom user error\n");
return -EINVAL;
}
printk("Kbuf:%c\n",KBuf);
switch(KBuf)
{
case '0':
*(LedOutPut) |= 1<<4;
break;
case '1':
*(LedOutPut) |= 1<<12;
break;
case '2':
*(LedOutPut) |= 1<<13;
break;
case '3':
*(LedOutPut) &= ~(1<<4);
*(LedOutPut) |= ~(1<<12);
*(LedOutPut) |= ~(1<<13);
break;
}
return size;
}
ssize_t ReadLed(struct file *file, char __user *ubuf,size_t size, loff_t *offs)
{
int ret;
char send[36]="\0";
sprintf(send,"green:%d blune:%d read:%d\n",(*LedOutPut & (1<<4)),(*LedOutPut & (1<<12)),(*LedOutPut & (1<<13)));
ret = copy_to_user(ubuf,send,size);
if(ret){
printk("copy to user error\n");
return -EINVAL;
}
return size;
}
const struct file_operations GPIO_LED = {
.write = GpioWrite,
.read = ReadLed,
};
static int __init GpioInit(void)
{
printk("LED start\n");
/*
* 注册自发设备驱动
*/
Major = register_chrdev(Major,CNAME,&GPIO_LED);
if(Major < 0){
printk("LED error\n");
return Major;
}
Cls1 = class_create(THIS_MODULE,CNAME);
if(IS_ERR(Cls1)){
printk("class_create err");
return PTR_ERR(Cls1);
}
Dev1 = device_create(Cls1,NULL,MKDEV(Major,0),NULL,CNAME);
if(IS_ERR(Dev1)){
printk("device create error\n");
return PTR_ERR(Dev1);
}
/*
* 物理地址转换为虚拟地址
*/
LedOutPut = ioremap(LED_OUTPUT,64);
if(LedOutPut == NULL){//转换失败提示
printk("red output error\n");
return -ENOMEM;
}
LedMode = ioremap(LED_MODE,64);
if(LedMode == NULL){//转换失败提示
printk("red mode error\n");
return -ENOMEM;
}
/*
* 将GPIO设置为输出
*/
*(LedMode) |= 1<<4;
*(LedMode) |= 1<<12;
*(LedMode) |= 1<<13;
/*
* 使GPIO输出高电平
*/
*(LedOutPut) |= 1<<4;
*(LedOutPut) |= 1<<12;
*(LedOutPut) |= 1<<13;
return 0;
}
static void __exit GpioExit(void)
{
device_destroy(Cls1,MKDEV(Major,0));
printk("LED exit\n");
iounmap(LedOutPut);
iounmap(LedMode);
/*
* 注销字符设备驱动
*/
unregister_chrdev(Major,CNAME);
}
/*
* 使用Linux内核提供的入口/出口API,调用自己写的入口/出口函数
* 添加许可证
*/
module_init(GpioInit);
module_exit(GpioExit);
MODULE_LICENSE("GPL");
MODULE_INFO(intree, "Y");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
/*
* 初始化设备号,定义设备名
*/
int Major = 0;
#define CNAME "TimeGpio"
/*
* LED基地址,以及虚拟地址
*/
#define LED_OUTPUT 0x43810040
#define LED_MODE 0x43810054
unsigned int * LedOutPut = NULL;
unsigned int * LedMode = NULL;
/*
* 创建设备节点变量
*/
struct class * Cls;
struct device * Dev;
/*
* 存储向应用从发送的数据
*/
char KBuf[25] = "\0";
int Freq=500;
int Numseg=500;
int Flag=0;
int Temp=500;
/*
* 定时器结构体
*/
struct hrtimer MyHrTimer;
ktime_t Kt;
void Mymemset(char * str){
while(*str)
*str++ = '\0';
}
int atoi(char * str){
int sum=0;
while(*str){
sum = sum*10 + *str - '0';
str++;
}
return sum;
}
/*
* 定时器中断函数,实现电平翻转功能
*/
static enum hrtimer_restart GpioLevelFlip(struct hrtimer * timer)
{
if(Numseg>0)
{
*(LedOutPut) ^= 1 << 4;
Flag ? Numseg--,Flag=0 : Flag++;
}
hrtimer_forward(timer,timer->base->get_time(),Kt);
return HRTIMER_RESTART;
}
ssize_t GpioWrite(struct file *file, const char __user *ubuf, size_t size, loff_t *offs)
{
int ret;
/*
* 调用函数将灯熄灭
*/
printk("this is write\n");
Mymemset(KBuf);
ret = copy_from_user(KBuf,ubuf,size);
if(ret){
printk("copyfrom user error\n");
return -EINVAL;
}
/*
* 解析传入数据
*/
switch(KBuf[0])
{
case '1':
Freq=atoi(&KBuf[1]);
break;
case '2':
Numseg=atoi(&KBuf[1]);
break;
}
/*
* 更改定时时间
*/
Kt = ktime_set(0,Freq * 500000);
Temp=Numseg;
printk("Kbuf:%s size:%d Freq:%dHz Numseg:%d\n",KBuf,(int)size,1000 / Freq,Numseg);
return size;
}
ssize_t ReadFreq(struct file *file, char __user *ubuf,size_t size, loff_t *offs)
{
int ret;
char send[36]="\0";
sprintf(send,"Freq:%d Hz,Numseg:%d",1000 / Freq,Temp-Numseg);
ret = copy_to_user(ubuf,send,size);
if(ret){
printk("copy to user error\n");
return -EINVAL;
}
return size;
}
const struct file_operations TIMER_LED = {
.write = GpioWrite,
.read = ReadFreq,
};
static int __init GpioInit(void)
{
/*
* 注册自发设备驱动
*/
Major = register_chrdev(Major,CNAME,&TIMER_LED);
if(Major < 0){
printk("LED error\n");
return Major;
}
Cls = class_create(THIS_MODULE,CNAME);
if(IS_ERR(Cls)){
printk("class_create err");
return PTR_ERR(Cls);
}
Dev = device_create(Cls,NULL,MKDEV(Major,0),NULL,CNAME);
if(IS_ERR(Dev)){
printk("Device create error\n");
return PTR_ERR(Dev);
}
/*
* 物理地址转换为虚拟地址
*/
LedOutPut = ioremap(LED_OUTPUT,64);
if(LedOutPut == NULL){//转换失败提示
printk("red output error\n");
return -ENOMEM;
}
LedMode = ioremap(LED_MODE,64);
if(LedMode == NULL){//转换失败提示
printk("red mode error\n");
return -ENOMEM;
}
/*
* 将GPIO设置为输出
*/
*(LedMode) |= 1<<4;
*(LedMode) |= 1<<12;
*(LedMode) |= 1<<13;
/*
* 初始化,将端口电平设置为0
*/
*(LedOutPut) &= ~(1<<4);
*(LedOutPut) &= ~(1<<12);
*(LedOutPut) &= ~(1<<13);
/*
* 定时器申请
*/
Kt = ktime_set(0,Freq * 500000);
hrtimer_init(&MyHrTimer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
hrtimer_start(&MyHrTimer,Kt,HRTIMER_MODE_REL);
MyHrTimer.function = GpioLevelFlip;
printk("LED start\n");
return 0;
}
static void __exit GpioExit(void)
{
device_destroy(Cls,MKDEV(Major,0));
class_destroy(Cls);
printk("LED exit\n");
iounmap(LedOutPut);
iounmap(LedMode);
/*
* 删除定时器
*/
hrtimer_cancel(&MyHrTimer);
/*
* 注销字符设备驱动
*/
unregister_chrdev(Major,CNAME);
}
/*
* 使用Linux内核提供的入口/出口API,调用自己写的入口/出口函数
* 添加许可证
*/
module_init(GpioInit);
module_exit(GpioExit);
MODULE_LICENSE("GPL");
MODULE_INFO(intree, "Y");