hisi_motor.c
#include <linux/module.h> //所有模块都需要的头文件 #include <linux/kernel.h> #include <linux/fs.h> //文件系统有关的,结构体file_operations也在fs头文件定义 #include <linux/init.h> //init和exit相关宏 #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> //linux中的用户态内存交互函数,copy_from_user(),copy_to_user()等 #include <asm/irq.h> //linux中断定义 #include <asm/io.h> #include <linux/sched.h> //声明printk()这个内核态的函数 #include <linux/interrupt.h> //包含与中断相关的大部分宏及结构体的定义,request_irq()等 #include <linux/device.h> // #include <linux/poll.h> #include <linux/slab.h> #include <linux/gfp.h> #include "hisi_motor.h" static struct hrtimer MotorTimer; ktime_t kt; static unsigned char motorr_timer_flag = 0; int major; static struct class *motordrv_class; static struct device *motordrv_dev; static struct fasync_struct *button_async; //定义一个结构 struct motor_desc{ //定义结构体 unsigned int mux_ofset_addr; //复用寄存器偏移地址 unsigned int mux_val; //复用寄存的设置值 unsigned int gpio_base_addr; //gpio寄存器基址 unsigned char bit; //对gpio寄存进行位操作时用,范围bit7~bit0 }; struct motor_desc led_motor_desc = {GPIO1_7_MUX_CTRL_REG_OFFSET, 0x00, GPIO01_BASE, 7}; struct motor_desc motors_desc[] = { //定义一个结构体数组 {GPIO7_5_MUX_CTRL_REG_OFFSET, 0x01, GPIO07_BASE, 5}, {GPIO7_4_MUX_CTRL_REG_OFFSET, 0x01, GPIO07_BASE, 4}, {GPIO7_3_MUX_CTRL_REG_OFFSET, 0x01, GPIO07_BASE, 3}, {GPIO7_2_MUX_CTRL_REG_OFFSET, 0x01, GPIO07_BASE, 2}, {GPIO2_0_MUX_CTRL_REG_OFFSET, 0x00, GPIO02_BASE, 0}, {GPIO2_1_MUX_CTRL_REG_OFFSET, 0x00, GPIO02_BASE, 1}, {GPIO2_2_MUX_CTRL_REG_OFFSET, 0x00, GPIO02_BASE, 2}, {GPIO2_3_MUX_CTRL_REG_OFFSET, 0x00, GPIO02_BASE, 3}, }; #if 0 {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 0, 1} #endif /*motorr pwm data CCW (nishizhen)*/ unsigned int CCW_data [8][4] = { {0, 0, 0, 1}, {0, 0, 1, 1}, {0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {1, 1, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 1} }; /*motorr pwm data CW (shunshizhen)*/ unsigned int CW_data [8][4] = { {0, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1} }; /********************************************************************************************************* *功能:设置引脚复用 *参数:无 *返回值:无 **********************************************************************************************************/ static void gpio_mux_ctrl_set(void) { unsigned int i; for(i=0; i<sizeof(motors_desc)/sizeof(motors_desc[0]); i++){ GPIOWRITEREG(MUX_CTRL_REG_BASE+motors_desc[i].mux_ofset_addr, motors_desc[i].mux_val); } } /********************************************************************************************************* *功能:GPIO相关寄存器设置 *参数:base_addr-->基地址, offset_addr-->偏移地址, bit-->位, val-->值 *返回值:无 **********************************************************************************************************/ static void gpio_reg_set(unsigned int base_addr, unsigned int offset_addr, unsigned char bit, unsigned char flag) { unsigned int value; unsigned int val = 0; unsigned int addr = 0; #if 0 if(val > 1){ printk("<val> input error!"); } if(bit > 7){ printk("<bit> input error!"); } value = ((GPIO_READ_REG(base_addr, offset_addr) & (~(1<<bit))) | (val<<bit)); GPIO_WRITE_REG(base_addr,offset_addr,value); #endif addr = GPIODATA(base_addr, bit); if(flag) { val = 1 << bit; } else { val = 0; } GPIOWRITEREG(addr,val); } /********************************************************************************************************* *功能:读取GPIO相关寄存器 *参数:base_addr-->基地址, offset_addr-->偏移地址, bit-->位, val-->值 *返回值:无 **********************************************************************************************************/ static void gpio_reg_read(unsigned int base_addr, unsigned int offset_addr, unsigned char bit) { unsigned int value; if(bit > 7){ printk("<bit> input error!"); } value = ((GPIO_READ_REG(base_addr, offset_addr) & (~(1<<bit)))); printk("gpio_reg_read value: %d\n",value); } /********************************************************************************************************* *功能:GPIO方向设置 *参数:base_addr-->基地址, offset_addr-->偏移地址, bit-->位, val-->值 0:输入 1:输出 *返回值:无 **********************************************************************************************************/ static void gpio_dir_set(unsigned int base_addr, unsigned int offset_addr, unsigned char bit, unsigned char flag) { //gpio_reg_set(base_addr,offset_addr,bit,val); unsigned int val = 0; unsigned int addr = 0; int ret; addr = GPIODIR(base_addr); val = GPIOREAD_REG(addr); if(flag) { val |= 1 << bit; } else { val &= ~(1 << bit); } GPIOWRITEREG(addr,val); } /********************************************************************************************************* *功能:GPIO相关寄存器组设置 *参数:无 *返回值:无 **********************************************************************************************************/ static void gpio_reg_group_set(void) { unsigned int i; for(i=0; i<sizeof(motors_desc)/sizeof(motors_desc[0]); i++){ gpio_dir_set(motors_desc[i].gpio_base_addr, GPIO_DIR, motors_desc[i].bit, 1); //0:输入 1:输出 printk("gpio_dir_set motors_desc[%d]: %x %x bit: %d value 1\n",i,motors_desc[i].gpio_base_addr,GPIO_DIR,motors_desc[i].bit); } } /********************************************************************************************************* *功能:设置引脚上的电平 *参数:base_addr-->基地址, offset_addr-->偏移地址, bit-->位, val-->值 0:低电平 1:高电平 *返回值:无 **********************************************************************************************************/ static void gpio_data_set(unsigned int base_addr, unsigned int offset_addr, unsigned char bit, unsigned char val) { gpio_reg_set(base_addr,offset_addr,bit,val); } /********************************************************************************************************* *功能:设置电机1正转 *参数: *返回值:无 **********************************************************************************************************/ static void set_motor1_ccw(void) { int i,j; for(i=0;i<8;i++) { for(j=0;j<4;j++) { gpio_data_set(motors_desc[j].gpio_base_addr,GPIO_DATA,motors_desc[j].bit,CCW_data[i][j]); printk("gpio_data_set %x %x %d %d\n",motors_desc[j].gpio_base_addr,GPIO_DATA,motors_desc[j].bit,CCW_data[i][j]); } } } #if 1 static int run_pats = 512; static unsigned int i = 0; static unsigned int j = 0; static struct hrtimer hr_timer; static struct work_struct wq_hrtimer; static ktime_t ktime; static unsigned int interval=5000; /* unit: us */ struct timespec uptimeLast; static unsigned int count=0; #define COUNT_INTERVAL 4000 unsigned long long diff_tv(struct timespec start, struct timespec end) { return (end.tv_sec-start.tv_sec)*1000000000+(end.tv_nsec-start.tv_nsec); } enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer ) { #if 1 if(run_pats > 0) { for (i=0; i<4; i++) { gpio_data_set(motors_desc[i].gpio_base_addr,GPIO_DATA,motors_desc[i].bit,CCW_data[j][i]); //printk("gpio_data_set %x %x %d %d\n",motors_desc[i].gpio_base_addr,GPIO_DATA,motors_desc[i].bit,CCW_data[j][i]); } } if (run_pats > 0 ) { j ++; if (j >= 8) { j = j - 8; } else { } //run_pats --; } #endif //kt = ktime_set(5, 1*1); /* 0 sec, 1 ms 定时1毫秒*/ kt = ktime_set( interval/1000000, (interval%1000000)*1000 ); schedule_work(&wq_hrtimer); return HRTIMER_NORESTART; } static void wq_func_hrtimer(struct work_struct *work) { struct timespec uptime; hr_timer.function = my_hrtimer_callback; ktime = ktime_set( interval/1000000, (interval%1000000)*1000 ); hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL ); /* print time every COUNT_INTERVAL*interval second*/ if(count%COUNT_INTERVAL==0) { do_posix_clock_monotonic_gettime(&uptime); printk(KERN_INFO"hrtimer:%9lu sec, %9lu ns, interval_delay=%lu ns\n", (unsigned long) uptime.tv_sec, uptime.tv_nsec, (unsigned long)(diff_tv(uptimeLast, uptime)-interval*1000*COUNT_INTERVAL) \ /COUNT_INTERVAL); uptimeLast=uptime; } count++; } static int motorr_timer_init( void ) { struct timespec uptime; printk(KERN_INFO"HR Timer module installing\n"); hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); ktime = ktime_set( interval/1000000, (interval%1000000)*1000 ); hr_timer.function = my_hrtimer_callback; hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL ); do_posix_clock_monotonic_gettime(&uptime); uptimeLast = uptime; printk(KERN_INFO"hrtimer:%9lu sec, %9lu ns\n", (unsigned long) uptime.tv_sec, uptime.tv_nsec ); INIT_WORK(&wq_hrtimer, wq_func_hrtimer); return 0; } #else /********************************************************************************************************* *功能:定时器中断函数 *参数:struct hrtimer *timer *返回值:0 **********************************************************************************************************/ static int run_pats = 512; static unsigned int i = 0; static unsigned int j = 0; static unsigned int interval=5000; enum hrtimer_restart motorr_timer_handler(struct hrtimer *timer) { //set_motor1_ccw(); #if 1 if(run_pats > 0) { for (i=0; i<4; i++) { gpio_data_set(motors_desc[i].gpio_base_addr,GPIO_DATA,motors_desc[i].bit,CCW_data[j][i]); //printk("gpio_data_set %x %x %d %d\n",motors_desc[i].gpio_base_addr,GPIO_DATA,motors_desc[i].bit,CCW_data[j][i]); } } if (run_pats > 0 ) { j ++; if (j >= 8) { j = j - 8; } else { } //run_pats --; } #endif //kt = ktime_set(5, 1*1); /* 0 sec, 1 ms 定时1毫秒*/ kt = ktime_set( interval/1000000, (interval%1000000)*1000 ); hrtimer_forward(timer, timer->base->get_time(), kt); printk(KERN_INFO"hrtimer handler!\n"); return HRTIMER_RESTART; } /********************************************************************************************************* *功能:定时函数初始化 *参数: *返回值:0 **********************************************************************************************************/ static int motorr_timer_init(void) { kt = ktime_set( interval/1000000, (interval%1000000)*1000 ); //kt = ktime_set(5, 1*1); /* 0 sec, 1 ms 定时1毫秒*/ hrtimer_init(&MotorTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_start(&MotorTimer, kt, HRTIMER_MODE_REL); MotorTimer.function = motorr_timer_handler;//hrtimer 的回调函数 ,这一句的逻辑应该是直接接在init后面吧 return 0; } #endif /********************************************************************************************************* *功能:模块打开函数 *参数: *返回值:无 **********************************************************************************************************/ static int motor_drv_open(struct inode *inode, struct file *file) { //gpio_reg_group_set(); //motorr_timer_init(); return 0; } /********************************************************************************************************* *功能:模块关闭函数 *参数: *返回值:无 **********************************************************************************************************/ int motor_drv_close(struct inode *inode, struct file *file) //出链,禁止中断 { return 0; } /********************************************************************************************************* *功能:模块异步通知函数 *参数: *返回值:无 **********************************************************************************************************/ static int motor_drv_fasync (int fd, struct file *filp, int on) { printk("driver: motor_drv_fasync\n"); //为了说明次函数被调用增加一条打印语句 return fasync_helper (fd, filp, on, &button_async); //初始化定义的结构体 } static struct file_operations motor_drv_fops = { .owner = THIS_MODULE, // 这是一个宏,推向编译模块时自动创建的__this_module变量 .open = motor_drv_open, .release = motor_drv_close, .fasync = motor_drv_fasync, //用户程序用异步通知的时候才会用到fasync }; /********************************************************************************************************* *功能:模块加载函数 *参数: *返回值:无 **********************************************************************************************************/ static int motor_drv_init(void) { gpio_mux_ctrl_set(); //引脚复用设置 gpio_reg_group_set(); motorr_timer_init(); #ifndef DEBUG gpio_data_set(led_motor_desc.gpio_base_addr,GPIO_DATA,led_motor_desc.bit,0); #endif major = register_chrdev(0, "motor_drv", &motor_drv_fops); //自动分配主设备号 motordrv_class = class_create(THIS_MODULE, "motor_drv"); motordrv_dev = device_create(motordrv_class, NULL, MKDEV(major, 0), NULL, "motor"); // 设备节点 /dev/buttons return 0; } static void motor_timer_exit(void) { //hrtimer_cancel(&MotorTimer); hrtimer_cancel(&hr_timer ); return; } /********************************************************************************************************* *功能:模块卸载函数 *参数: *返回值:无 **********************************************************************************************************/ static void motor_drv_exit(void) { unregister_chrdev(major, "motor_drv"); device_unregister(motordrv_dev); class_destroy(motordrv_class); motor_timer_exit(); printk("motor drive is rmmod!!\n"); } module_init(motor_drv_init); module_exit(motor_drv_exit); MODULE_DESCRIPTION("Motors Driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Hisilicon");
hisi_motor.h
#ifndef __BTN_DRV_H__ #define __BTN_DRV_H__ #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* __cplusplus */ /**************引脚复用寄存器************/ #define MUX_CTRL_REG_BASE 0x200F0000 #define GPIO7_2_MUX_CTRL_REG_OFFSET 0x0E8 #define GPIO7_3_MUX_CTRL_REG_OFFSET 0x0EC #define GPIO7_4_MUX_CTRL_REG_OFFSET 0x0F0 #define GPIO7_5_MUX_CTRL_REG_OFFSET 0x0F4 #define GPIO2_0_MUX_CTRL_REG_OFFSET 0x010 #define GPIO2_1_MUX_CTRL_REG_OFFSET 0x014 #define GPIO2_2_MUX_CTRL_REG_OFFSET 0x018 #define GPIO2_3_MUX_CTRL_REG_OFFSET 0x01C #define GPIO1_7_MUX_CTRL_REG_OFFSET 0x098 /***********GPIO基址********************/ #define GPIO13_BASE 0x20210000 #define GPIO12_BASE 0x20200000 #define GPIO11_BASE 0x201F0000 #define GPIO10_BASE 0x201E0000 #define GPIO09_BASE 0x201D0000 #define GPIO08_BASE 0x201C0000 #define GPIO07_BASE 0x201B0000 #define GPIO06_BASE 0x201A0000 #define GPIO05_BASE 0x20190000 #define GPIO04_BASE 0x20180000 #define GPIO03_BASE 0x20170000 #define GPIO02_BASE 0x20160000 #define GPIO01_BASE 0x20150000 #define GPIO00_BASE 0x20140000 /**************GPIO相关寄存器*************/ #define GPIO_DATA 0x000 #define GPIO_DIR 0x400 #define GPIO_IS 0x404 #define GPIO_IBE 0x408 #define GPIO_IEV 0x40c #define GPIO_IE 0x410 #define GPIO_RIS 0x414 #define GPIO_MIS 0x418 #define GPIO_IC 0x41c /*************GPIO中断号*****************/ #define GPIO02_7_DATA (GPIO02_BASE + GPIO_DATA) #define GPIO01_1_DATA (GPIO01_BASE + GPIO_DATA) #define GPIO02_3_DATA (GPIO02_BASE + GPIO_DATA) #define GPIO02_4_DATA (GPIO02_BASE + GPIO_DATA) #define GPIO11_0_DATA (GPIO11_BASE + GPIO_DATA) #define GPIO11_4_DATA (GPIO11_BASE + GPIO_DATA) #define GPIO11_7_DATA (GPIO11_BASE + GPIO_DATA) #define GPIO01_2_DATA (GPIO01_BASE + GPIO_DATA) #define GPIO09_2_DATA (GPIO09_BASE + GPIO_DATA) #define GPIO09_4_DATA (GPIO09_BASE + GPIO_DATA) //读写写寄存器 #define GPIODIR(gpio_group_reg_base) ((gpio_group_reg_base) + 0x400) #define GPIODATA(gpio_group_reg_base, gpio_offset) ((gpio_group_reg_base) + 0x000) + (1 << ((gpio_offset) + 2)) #define GPIOWRITEREG(addr, value) (*(volatile unsigned int *)((unsigned int)ioremap_nocache(addr,0x800)) = (value)) #define GPIOREAD_REG(base_addr) (*(volatile unsigned int *)((unsigned int)ioremap_nocache(base_addr,0x800))) #define GPIO_WRITE_REG(base_addr,offset_addr, value) (*(volatile unsigned int *)((unsigned int)ioremap_nocache(base_addr,0x800) + offset_addr) = (value)) #define GPIO_READ_REG(base_addr,offset_addr) (*(volatile unsigned int *)((unsigned int)ioremap_nocache(base_addr,0x800) + offset_addr)) #ifdef __cplusplus #if __cplusplus } #endif #endif /* __cplusplus */ #endif /* __BTN_DRV_H__ */
moto_drv_test.c
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> int fd; int main(int argc, char *argv[]) { int flag; fd = open("/dev/motor", O_RDWR); if (fd < 0) { printf("can't open!\n"); } while (1) { sleep(1000); } return 0; }