您尚未登录。

#1 2021-04-23 10:04:01 分享评论

无根浮萍
会员
注册时间: 2021-01-14
已发帖子: 60
积分: 29.5

请问大家,我写了一个 tina f1c200s timer1 中断驱动, 怎么改都只进入一次中断, 请问这是什么原因呢?

timer.c:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/clk/sunxi.h>
#include <linux/delay.h>
#ifdef CONFIG_ARCH_SUN3I
#include <asm/sched_clock.h>
#include <linux/clocksource.h>
#endif

#define TIMER_IRQ_EN_REG        0x00
#define TIMER_IRQ_EN(val)       (1 << val)
#define TIMER_IRQ_ST_REG        0x04
#define TIMER_IRQ_ST(val)       (1 << val)
#define TIMER_CTL_REG(val)      (0x10 * val + 0x10)
#define TIMER_CTL_ENABLE        (1 << 0)
#define TIMER_CTL_AUTORELOAD    (1 << 1)
#define TIMER_CTL_MODE_MASK     (1 << 7)
#define TIMER_CTL_PERIODIC      (0 << 7)
#define TIMER_CTL_ONESHOT       (1 << 7)
#define TIMER_INTVAL_REG(val)   (0x10 * val + 0x14)
#define TIMER_CNTVAL_REG(val)   (0x10 * val + 0x18)

#define TIMER_IRQ 14  //timer1 irq

static int timer_nr = 1;
//static void __iomem *timer_base = 0x01c20c00;
static void __iomem *timer_base = 0xF1C20C00;
//#define HZ 100


static irqreturn_t timer_handler(int irq, void *dev_id)
{
        u32 val = 0;
        u32 rate = 24000000;
        u32 prescale = 16;

        writel(rate / (prescale * HZ),
               timer_base + TIMER_INTVAL_REG(timer_nr));

        writel(TIMER_IRQ_ST(timer_nr), timer_base + TIMER_IRQ_ST_REG);

        val = readl(timer_base + TIMER_CTL_REG(timer_nr));
//      writel(val | TIMER_CTL_ENABLE | TIMER_CTL_PERIODIC, timer_base + TIMER_CTL_REG(timer_nr));
        writel(val | TIMER_CTL_ENABLE | TIMER_CTL_PERIODIC | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(timer_nr));

//      printk(">");

        return IRQ_HANDLED;
}

int init_timer_module(void)
{
        u32 rate = 24000000;
        u32 prescale = 16;
        int ret, irq;
        u32 val;

        printk("HZ = %d \n", HZ);
        printk("rate / (prescale * HZ) = %d \n", rate / (prescale * HZ));
        writel(rate / (prescale * HZ),
               timer_base + TIMER_INTVAL_REG(timer_nr));

        /* set clock source to HOSC, 16 pre-division */
        val = readl(timer_base + TIMER_CTL_REG(timer_nr));
        val &= ~(0x07 << 4);
        val &= ~(0x03 << 2);
        val |= (4 << 4) | (1 << 2);
        writel(val, timer_base + TIMER_CTL_REG(timer_nr));

        val = readl(timer_base + TIMER_CTL_REG(timer_nr));
        printk("222 val = 0x%X\n ", val);


        /* set mode to auto reload */
        val = readl(timer_base + TIMER_CTL_REG(timer_nr));
        writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(timer_nr));

        val = readl(timer_base + TIMER_CTL_REG(timer_nr));
        printk("333 val = 0x%X\n ", val);
//        ret = setup_irq(irq, &sunxi_timer_irq);
//        if (ret)
//                pr_warn("failed to setup irq %d\n", irq);



//      if (request_irq(14, (irq_handler_t )timer_handler, IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL ,
        if (request_irq(14, (irq_handler_t )timer_handler, 0,
                                "sunxi_timer1", NULL))
        {
                printk("irq request failure\n");
                return -1;
        }

        /* Enable timer interrupt */
        val = readl(timer_base + TIMER_IRQ_EN_REG);
        writel(val | TIMER_IRQ_EN(timer_nr), timer_base + TIMER_IRQ_EN_REG);
        printk("555 val = 0x%X\n", val);

        return 0;
}

void release_timer_module(void)
{
        free_irq(14, NULL);
        return;
}

module_init(init_timer_module);
module_exit(release_timer_module);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("whycan");

Makefile

obj-m = timer.o

编译指令:

ARCH=arm CROSS_COMPILE=${PWD}/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-arm9-musl/toolchain/bin/arm-openwrt-linux-muslgnueabi- make -C ${PWD}/lichee/linux-3.10/ M=${PWD}/modules/timer

只触发了一次中断:

root@TinaLinux:/# insmod /tmp/timer.ko
module is already loaded - timer
root@TinaLinux:/#
root@TinaLinux:/# lsmod
8723bs               1500733  0
gc0308                  9903  0
ov2640                 10760  0
snd_mixer_oss          11988  1 snd_pcm_oss
snd_pcm_oss            30646  0
snd_seq_device          4506  0
timer                   1084  0
vfe_io                 26420  3 vfe_v4l2
vfe_v4l2              204719  0
videobuf2_core         21778  1 vfe_v4l2
videobuf2_dma_contig    7789  1 vfe_v4l2
videobuf2_memops        1260  1 videobuf2_dma_contig
root@TinaLinux:/#
root@TinaLinux:/#
root@TinaLinux:/# cat /proc/interrupts
           CPU0
 13:        724  sun3i_irq  sunxi_timer
 14:          1         -  sunxi_timer1
 38:          1  sun3i_irq  PIN_GRP
 39:          0  sun3i_irq  PIN_GRP
 40:          0  sun3i_irq  PIN_GRP
101:       5413  sun3i_irq  1c02000.dma-controller
103:          0  sun3i_irq  cedar_dev
104:        155  sun3i_irq  uart1
105:         22  sun3i_irq  twi0
106:      17980  sun3i_irq  spi0
107:         43  sun3i_irq  sunxi-mmc
108:       4424  sun3i_irq  lcd
109:          0  sun3i_irq  dispaly
113:          0  sun3i_irq  csi_irq
114:         99  sun3i_irq  sunxi_usb_udc
115:          0  sun3i_irq  sunxikbd
Err:          0

离线

#2 2021-04-23 10:27:09 分享评论

无根浮萍
会员
注册时间: 2021-01-14
已发帖子: 60
积分: 29.5

Re: 请问大家,我写了一个 tina f1c200s timer1 中断驱动, 怎么改都只进入一次中断, 请问这是什么原因呢?

我想了一下, 有两个原因, 定时器中断函数清除状态寄存器那里

1. 没有加锁
2. timer0 没有先读出寄存器数据再写

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn