景区门户网站建设,江苏建信建设集团网站,办公室装饰,最近国内新闻仅作为自我记录的一个demo 本次GPIO以微妙级别频率的反转实验有以下几个启示#xff1a;
一开始在应用层做延时#xff0c;来实现2微妙周期#xff0c;占空比50%的GPIO反转#xff0c;发现波形的频率一直上不去#xff0c;只能在25hz徘徊#xff0c;后来索性去掉延时
一开始在应用层做延时来实现2微妙周期占空比50%的GPIO反转发现波形的频率一直上不去只能在25hz徘徊后来索性去掉延时发现最高也就只能到发现只能到达6.5us周期一开始是认为system函数内有系统调用开销比较大但是后来一想再大应该超不过200ns后来向组内大佬请求帮助大佬说sleep函数会引起睡眠造成进程切换这个开销是很大的特别是us级别的延时得不偿失。另外一开始操作gpio是用system来执行echo操作gpio这个过程本质是execvp了进程也有一定开销。应该用file操作sysfs的文件。后来将延时操作迁移到linux内核驱动这次不加延时最高可以跑到120ns的周期我想应该还能跑到更高因为这个demo是开启一个内核线程去执行的。最后将延时操作换为对时间的读取使用gettimeofday函数这个函数的精度刚好是us级别通过在while循环里判断两次读取时间查是否大于等于1来反转gpio到这个做法好像不太行输出的波形不稳定频率在不断变化 放弃3中的做法后可以尝试的方法还有内核定时器udelay函数可以尝试。看看尝试了udelay的效果 效果还行最终就选择了这个方案。
#include linux/types.h
#include linux/errno.h
#include linux/ioport.h
#include linux/fcntl.h
#include linux/init.h
#include linux/proc_fs.h
#include linux/io.h
#include linux/uaccess.h
#include linux/mutex.h
#include linux/pagemap.h
#include linux/kthread.h
#include linux/kthread.h
#include linux/delay.h
#include linux/module.h#define ENTER() printk(KERN_DEBUG %s() Enter, __func__)
#define EXIT() printk(KERN_DEBUG %s() Exit, __func__)
#define ERR(fmt, args...) printk(KERN_ERR %s()-%d: fmt \n, __func__, __LINE__, ##args)
#define DBG(fmt, args...) printk(KERN_DEBUG %s()-%d: fmt \n, __func__, __LINE__, ##args)/** toggle the gpio output value every 1us
*/#define GPIO_PORTB_BASE 0xF244C000
#define GPIOB_DATA_OFF 0x0
#define GPIOB_DIR_OFF 0x4#define IOMUX_BASE 0xF0040500
#define DRIVER_ABLT_R2R_OFF 0x00
#define PINCTRL_OFF 0x2C
#define GPIO_FUNC_NUM 8
#define DRIVER_SET_VAL 1
#define GPIO_PIN_NUM 4
#define PIN_MUX_BIT_WIDTH 4
#define PIN_DRV_BIT_WIDTH 1#define TOGGLE_SPAN_IN_US 1static unsigned int *gpio_handler;
static unsigned int *iomux_handler;
static struct task_struct *test_kthread NULL; static void pinctrl(void *handler)
{unsigned int *pinctrl_banke (unsigned int *)(handler PINCTRL_OFF);unsigned int *driver_banke (unsigned int *)(handler DRIVER_ABLT_R2R_OFF);// PE4 set func 8*pinctrl_banke (unsigned int)(GPIO_FUNC_NUM (GPIO_PIN_NUM * PIN_MUX_BIT_WIDTH));// PE4 driver ability set 2ma*driver_banke (unsigned int)(DRIVER_SET_VAL (GPIO_PIN_NUM * PIN_DRV_BIT_WIDTH));
}static void gpio_cfg(void *handler)
{unsigned int *gpio_dir_base (unsigned int *)(handler GPIOB_DIR_OFF);//set gpiob1 direction output *gpio_dir_base 0x02;
}inline void gpio_set_high(void *handler)
{unsigned int * gpio_dat_base (unsigned int *)(handler GPIOB_DATA_OFF);//set gpiob1 output high*gpio_dat_base 0x02;
}inline void gpio_set_low(void *handler)
{unsigned int * gpio_dat_base (unsigned int *)(handler GPIOB_DATA_OFF);//set gpiob1 output low*gpio_dat_base 0x00;
}static int gpio_toggle_thread(void* data)
{static volatile unsigned int flg 0;ENTER(); gpio_handler ioremap(GPIO_PORTB_BASE, 8);iomux_handler ioremap(IOMUX_BASE, 50);pr_err(gpio_toggle_thread start \r\n);pinctrl(iomux_handler);gpio_cfg(gpio_handler);while(!kthread_should_stop()){if(flg 0){gpio_set_high(gpio_handler);flg 1;} else {gpio_set_low(gpio_handler);flg 0;}udelay(1);}EXIT();return 0;
}int __init gp_toggle_init(void)
{ENTER();test_kthread kthread_run(gpio_toggle_thread, NULL, gpio-toggle); if(!test_kthread) {ERR(kthread_run fail);return -ECHILD; }EXIT();return 0;
}void __exit gp_toggle_exit(void)
{ENTER();if (test_kthread) {DBG(kthread_stop);kthread_stop(test_kthread); //停止内核线程test_kthread NULL;}EXIT(); return;
}module_init(gp_toggle_init);
module_exit(gp_toggle_exit);
MODULE_LICENSE(GPL);