天嵌 ARM开发社区

 找回密码
 注册
查看: 2727|回复: 1

3358 timer3 实现 1 s 的定时

[复制链接]
qxj511 发表于 2016-6-29 11:12:04 | 显示全部楼层 |阅读模式
想用 timer3 实现 定时器的功能,自己去设置了几个寄存器之后,发现定时器完全没有启动。刚刚学习 TQ3358,对板子还不是和了解,希望有前辈可以帮忙一下。以下是代码清单:


#define TIMER3_IRQ_3358 69


#define TIMER0_BASE 0x44E05000
#define TIMER2_BASE 0x48040000

#define TIMER3_BASE 0x48042000   // 定时器基地址
#define CM_PER                 0x44E00000  // clock management
#define CM_DPLL         0x44E00500  // 锁相环,用于倍频
#define CM_WKUP     0x44E0_0400                 //  Clock Module Wakeup Registers








volatile unsigned long * IRQWAKEEN = NULL;

volatile unsigned long * IRQENABLE_SET = NULL;
volatile unsigned long * IRQENABLE_CLR = NULL;
volatile unsigned long * IRQSTATUS = NULL;



volatile unsigned long * CM_PER_TIMER3_CLKCTRL = NULL;

volatile unsigned long * CLKSEL_TIMER3_CLK = NULL;
volatile unsigned long * TIMET3_TLDR = NULL;

volatile unsigned long * TIMER3_TCLR = NULL;




#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))

static int timer_init(void);




long motor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{

        printk("%s,%d \n",__FUNCTION__,__LINE__);
        switch (cmd){
        case 0:
                printk("cmd = %d\n", cmd);
                break;
        case 1:
                printk("cmd = %d\n", cmd);
                break;
        }

        return 0;
}


/*
* motor open routine.
* do nothing.
*/
int motor_open(struct inode * inode, struct file * file)
{
        int ret;

        // 1、检测 GPIO 的合法性
        ret = gpio_is_valid(GPIO_TO_PIN(1,16));       
        if(ret < 0)        {               
                printk("failed gpio_is_valid GPIO_TO_PIN(1,16) \n");               
                return ret;
        }       
        else               
                printk("valid OK\n");

        // 2、注册/申请 GPIO
        ret = gpio_request(GPIO_TO_PIN(1, 16),"GPIO_OUT");
        if(ret < 0)        {               
                printk("failed gpio_request GPIO_TO_PIN(1,16)\n");               
                return ret;       
        }       
        else               
                printk("request gpio GPIO_TO_PIN(1,16) OK \n");

        // 3、设置为输出,且设置为低电平       
        gpio_direction_output(GPIO_TO_PIN(1, 16), 0);
        if(ret < 0)        {               
                printk("failed gpio_direction_output GPIO_TO_PIN(1,16)\n");               
                return ret;
        }       
        else               
                printk("gpio_direction_output(GPIO_TO_PIN(1, 16), 0) OK\n");

        // 4、设置 GPIO 为高电平
        gpio_set_value(GPIO_TO_PIN(1, 16), 1);


        // 定时器 初始化
        timer_init();


    return 0;
}

/*
* motor close routine.
* do nothing.
*/

int motor_close(struct inode * inode, struct file * file)
{
    return 0;
}

int motor_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{

        return 0;         
}


/*
*  The various file operations we support.
*/

static struct file_operations motor_fops = {
        .owner                    = THIS_MODULE,
        .unlocked_ioctl = motor_ioctl,
        .open                   = motor_open,
        .write                        = motor_write,
        .release                  = motor_close
};

static struct miscdevice motor_dev = {
        MISC_DYNAMIC_MINOR,
        "gpio_motor",
        &motor_fops,
};



static irqreturn_t timer_interrupt(int irq,void * dev_id)
{
       
        int step = 0;


        printk("%s,%d\n",__FUNCTION__,__LINE__);

        // 4097,capture、overflow、match 三种,都是什么定时器
        // 当中断发生的时候,就清除中断,
        if ( (readl(IRQSTATUS)) & 0x2 ){   
                // 200 us 到了
                writel(~0, IRQENABLE_CLR);   // 4099

                count++;
                step++;
        }
       
        gpio_set_value(GPIO_TO_PIN(1, 16), 1);

       
        if( count ==  2){
                gpio_set_value(GPIO_TO_PIN(1, 16), 0);
                count = 0;
        }
       

        // 中断函数处理完毕
        return IRQ_HANDLED;
}


// 硬件定时器的初始化
// 定时器选用 timer0,timer0 指定了时钟只能是 32KHz

static int timer_init(void)
{
        unsigned int val;
        int ret;

        printk("%s,%d\n",__FUNCTION__,__LINE__);
       
       
        // timer3   936   开启时钟模式
        // 1、允许我们去访问寄存器 ,// CM_PER_TIMER3_CLKCTRL
        val = 0x02;
        writel(val, CM_PER_TIMER3_CLKCTRL);
        printk("%s,%d\n",__FUNCTION__,__LINE__);

        // 2、关闭定时器
        val = 0x00;
        writel(val, TIMER3_TCLR);
        printk("%s,%d\n",__FUNCTION__,__LINE__);

       
        // 3、选择、设置、时钟,选择为 32 KHz,   // 1035,
        val = 0x02;
        writel(val, CLKSEL_TIMER3_CLK);
        printk("%s,%d\n",__FUNCTION__,__LINE__);
       


        // 4、装载初值 4104,也就是说,周期是 31.25 微秒
    // 32 KHz == 0.03125 * 10(-3) 毫秒, 那么 200 us -->> 200 / 31.25= 6.4
    // 4104   ,故意设置为 1 S,6.4 X = 1 000 000 ,X->> 32 000
    // 这个步骤要不要,貌似应该不用装载了吧,
        writel(32000, TIMET3_TLDR);    // timer load register,完成数值的加载,                                                       
        printk("%s,%d\n",__FUNCTION__,__LINE__);
       

        // 4100,中断唤醒使能,
        val = 0;
        val |= ((1<<2) | (1<<1) | (1<<0));
        writel(val, IRQWAKEEN);
        printk("%s,%d\n",__FUNCTION__,__LINE__);



        // 中断使能        4098
        val = 0;
        val |=   (1<<1);     //((1<<2) | (1<<1) | (1<<0));
        writel(val, IRQENABLE_SET);
        printk("%s,%d\n",__FUNCTION__,__LINE__);
         

                                               
        // 5、定时器开始,  4101
        val = 0x03;
        writel(val, TIMER3_TCLR);
        printk("%s,%d\n",__FUNCTION__,__LINE__);
       

        // 注册中断,213
        ret=request_irq(TIMER3_IRQ_3358,timer_interrupt,IRQF_SHARED,TIMER_NAME,(void*)&key_event);
        if(ret<0)
        {
                printk("IRQ %d can not request,ret = %d \n",TIMER3_IRQ_3358,ret);
                return ret;
        }
        printk("%s,%d\n",__FUNCTION__,__LINE__);
        return 0;
}
static int __init motor_init(void)
{  
    int ret = 0;

        //  
       
        //WKUP_TIMER0_CLKCTR = (volatile unsigned long *)ioremap(TIMER2_BASE + 0x10, 4);
       
        // 1、 时钟的使能,936
        // 1、 时钟的使能,936
        CM_PER_TIMER3_CLKCTRL = (volatile unsigned long *)ioremap(CM_PER + 0x84, 4);
        // 定时器的开关 4101
        TIMER3_TCLR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x38, 4);
        // 设置时钟,
        CLKSEL_TIMER3_CLK =(volatile unsigned long *)ioremap(CM_DPLL + 0x0c, 4);
       
        // 装载  ,要不要
        TIMET3_TLDR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x40, 4);

        // 中断请求
        IRQWAKEEN = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x34, 4);

        // 中断设置
        IRQENABLE_SET = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x2c, 4);

       
        IRQSTATUS = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x28, 4);
        IRQENABLE_CLR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x30, 4);

        key_event.state = KEY_NONE;


        ret = misc_register(&motor_dev);
    if(ret)
    {
        DBG("could not register gpio devices. \n");
        return ret;
    }
    printk("gpio motor  driver insmod successful!\n");


               
    return ret;
}

static void __exit motor_exit(void)
{
    misc_deregister(&motor_dev);
    //free_irq(IRQ_GPIO9, (void*)&key_event);
    free_irq(TIMER3_IRQ_3358,(void*)&key_event);
        gpio_free(GPIO_TO_PIN(1, 16));
    printk("gpio driver exit successful!\n");
}

module_init(motor_init);
module_exit(motor_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("carlos");
 楼主| qxj511 发表于 2016-7-1 17:59:32 | 显示全部楼层
呼呼呼,来人啊,帮帮忙啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-3-29 15:50 , Processed in 1.046875 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表