#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#define SEC_TO_NS(x) (x * 1E9L)
#define MS_TO_NS(x) (x * 1E6L)
#define US_TO_NS(x) (x * 1E3L)
#define WRITE_REG(Addr, Value) ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr) (*(volatile unsigned int *)(Addr))
#define REG_USR_ADDR(RegAddr) *((volatile unsigned int *)(RegAddr))
#define GPIO_SEL_REG_BASE IO_ADDRESS(0x10203000)
#define GPIO5_2_SEL_REG (GPIO_SEL_REG_BASE + 0x078)
#define GPIO5_7_SEL_REG (GPIO_SEL_REG_BASE + 0x08c)
#define GPIO10_5_SEL_REG (GPIO_SEL_REG_BASE + 0x0ac)
#define GPIO5_5_SEL_REG (GPIO_SEL_REG_BASE + 0x84)
#define GPIO5_REG_BASE IO_ADDRESS(0x101E4000)
#define GPIO5_DATA (GPIO5_REG_BASE + 0x000)
#define GPIO5_DIR (GPIO5_REG_BASE + 0x400)
#define GPIO5_IS (GPIO5_REG_BASE + 0x404) //GPIO 中断触发寄存器
#define GPIO5_IBE (GPIO5_REG_BASE + 0x408) //GPIO 双沿触发中断寄存器
#define GPIO5_IEV (GPIO5_REG_BASE + 0x40C) //GPIO 触发中断条件寄存器
#define GPIO5_IE (GPIO5_REG_BASE + 0x410) //GPIO 中断屏蔽寄存器
#define GPIO5_RIS (GPIO5_REG_BASE + 0x414) //GPIO 原始中断状态寄存器
#define GPIO5_MIS (GPIO5_REG_BASE + 0x418) //GPIO 屏蔽状态中断寄存器
#define GPIO5_IC (GPIO5_REG_BASE + 0x41C) //GPIO 中断清除寄存器
#define GPIO10_REG_BASE IO_ADDRESS(0x101F0000)
#define GPIO10_DATA (GPIO10_REG_BASE + 0x000)
#define GPIO10_DIR (GPIO10_REG_BASE + 0x400)
static struct hrtimer hr_timer;
struct proc_dir_entry *gpio_proc_dir = NULL;
struct proc_dir_entry *stFileEntry = NULL;
static struct timer_list mytest_timer;
static ktime_t ktime;
static unsigned long delay_in_us = 15L;
void GPIO5_5_Pin_INIT(void)
{
unsigned int tmp = 1;
// 1. 设置GPIO5_5 为 gpio模式
WRITE_REG(GPIO5_5_SEL_REG, 0x00);
// 2. 设置 GPIO5_5 输出模式
tmp = READ_REG(GPIO5_DIR);
tmp |= (0x01<<5);
WRITE_REG(GPIO5_DIR, tmp);
}
void GPIO5_5WriteBit(void)
{
unsigned int GpioUsrAddr = GPIO5_REG_BASE;
unsigned int GpioBitNum = 5;
static unsigned char bHighVolt = 0;
if (bHighVolt)
{
REG_USR_ADDR(GpioUsrAddr + (4 << GpioBitNum)) = 1 << GpioBitNum;
}
else
{
REG_USR_ADDR(GpioUsrAddr + (4 << GpioBitNum)) = 0;
}
bHighVolt = !bHighVolt;
return;
}
enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer )
{
GPIO5_5WriteBit();
hrtimer_forward_now(timer, ktime);
return HRTIMER_RESTART;
}
void start_hard_timer(unsigned long arg)
{
hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );
return;
}
static int gpio_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
char *sub_str = NULL;
const char *start_string = "start";
int len = 0;
unsigned char pdata[100] = {0};
len = (count > 100) ? 100 : count;
memset(pdata,0,sizeof(pdata));
if(copy_from_user(pdata, buffer, len))
{
printk("Fail to get data from user space !\n");
return -1;
}
else
{
//printk("user space data: %s\n",pdata);
if(NULL != strstr((const char*)pdata,start_string))
{
GPIO5_5_Pin_INIT();
printk("HR Timer module installing\n");
ktime = ktime_set(0,US_TO_NS(delay_in_us));
hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
hr_timer.function = &my_hrtimer_callback;
printk( "Starting timer to fire in %ldus (%ld)\n", delay_in_us, jiffies );
init_timer(&mytest_timer);
mytest_timer.expires = jiffies + HZ;
mytest_timer.function = start_hard_timer;
mytest_timer.data = 0;
add_timer(&mytest_timer);
}
}
return 1;
}
static int __init ker_driver_init(void)
{
gpio_proc_dir = proc_mkdir("driver/gpio", NULL);
if(gpio_proc_dir == NULL)
{
printk("proc_mkdir driver/gpio fail\n");
goto err_dir;
}
stFileEntry = create_proc_entry("input", 0666, gpio_proc_dir);
if(stFileEntry == NULL)
{
printk("create_proc_entry driver/gpio/input fail\n");
goto err_sub_dir;
}
stFileEntry->write_proc = gpio_proc_write;
return 0;
err_sub_dir:
remove_proc_entry("input", gpio_proc_dir);
err_dir:
remove_proc_entry("driver/gpio", NULL);
return -1;
}
static int cleanup_proc_gpio(void)
{
if(NULL != stFileEntry)
remove_proc_entry("input", gpio_proc_dir);
if(NULL != gpio_proc_dir)
remove_proc_entry("driver/gpio", NULL);
stFileEntry = NULL;
gpio_proc_dir = NULL;
return 1;
}
static void __exit ker_driver_exit(void)
{
int ret;
cleanup_proc_gpio();
ret = hrtimer_cancel( &hr_timer );
if (ret)
printk("The timer was still in use...\n");
printk("HR Timer module uninstalling\n");
return;
}
module_init(ker_driver_init);
module_exit(ker_driver_exit);
MODULE_AUTHOR("cupidove@163.com");
MODULE_DESCRIPTION("Kernel driver");
MODULE_LICENSE("GPL");
hrtimer
最新推荐文章于 2023-07-06 15:26:45 发布