海思步进电机驱动

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;
}





猜你喜欢

转载自blog.csdn.net/qq_29214249/article/details/78951407