QT2410的timer一共四組,我這邊先略過timer詳細的操作步驟,相關資料在網路上都可以找得到,而timer範例程式碼可參考我之前寫的qt2410 bootloader

打開arch/arm/mach-qt2410/time2410.c,可看到如下程式碼

qt2410_time_init就是qt2410 timer初始化的程式碼擺放位置,而gettimeoffset是kernel提供給各個architecture要自訂的API

瞭解架構後就來塞程式碼吧,首先是initial的部份,initial要做三件事
(1)初始化timer0(我用timer0當系統時鐘,最小tick count 1us)
(2)註冊timer中斷(增加kernel tick count)
(3)開啟timer中斷
詳細程式碼如下所示

void __init qt2410_time_init (void) 
{ 
unsigned long temp;
 
qt2410_timer_irq.handler = qt2410_timer_interrupt;
setup_irq(nTIMER0_INT, &qt2410_timer_irq);
 
 
temp=__raw_readl(rTCFG0);
temp|=249;
__raw_writel(temp,rTCFG0);
 
temp=__raw_readl(rTCFG1);
temp|=0x03;
__raw_writel(temp,rTCFG1);
 
__raw_writel(12,rTCNTB0);
 
temp=__raw_readl(rTCON);
temp|=(1<<1);
__raw_writel(temp,rTCON);
 
temp=__raw_readl(rTCON);
temp&=~(1<<1);
__raw_writel(temp,rTCON);
 
temp=__raw_readl(rTCON);
temp|=0x9;
__raw_writel(temp,rTCON);
 
INT_ENABLE(nTIMER0_INT);
}

而timer的中斷函式與註冊程式碼如下所示

static irqreturn_t qt2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{                                                                                                                                       
        //timer_cnt++; 
        write_seqlock(&xtime_lock);                                                                                                                                         
        timer_tick(regs);         
        write_sequnlock(&xtime_lock);                                                                                                                           
        return IRQ_HANDLED;
}
 
 static struct irqaction qt2410_timer_irq =
 {
        .name           = "QT2410 Timer Tick",
        .flags          = SA_INTERRUPT | SA_TIMER,
        .handler        = qt2410_timer_interrupt
};

至於gettimeoffset就參考4510的寫法,不需要大改

寫完之後,就可以試著用ICE去load vmlinux並執行,看看timer是否能正確處理timer interrupt
下圖是用ICE在timer interrupt設中斷的情況

最後修改日期: 3 6 月, 2022

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。