📄 timer.c
字号:
/*
* ApOS (Another Project software for s3c2410)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Copyright caiyuqing
*
*/
#include "../include/kernel/irq.h"
#include "../include/s3c2410/timer.h"
#include "../include/s3c2410/s3c2410.h"
#include "../include/s3c2410/cpu.h"
#include "../include/kernel/task.h"
#include "../include/kernel/signal.h"
#include "../include/s3c2410/io.h"
/*
Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
Sample:
prescaler value = 119
divider value = 1/16
PCLK= 50700000
Timer input clock Frequency =50700000/ (119+1)/(1/16)=26406
*/
extern irq_ptr irq_rotunie[32];
void do_timer0(struct cpu_registers *regs);//Timer0中断服务例程
void do_timer1(struct cpu_registers *regs);//Timer1中断服务例程
void do_timer2(struct cpu_registers *regs);//Timer2中断服务例程
void do_timer3(struct cpu_registers *regs);//Timer3中断服务例程
void do_timer4(struct cpu_registers *regs);//Timer4中断服务例程
struct timer_ctrl_object timer_ctrl_object;
extern struct task_struct* current;
extern int volatile jiffies;
unsigned int current_singal;
unsigned int *led=0x56000054;
/*
初始化 timer_ctrl_object 对象
*/
void timer_ctrl_obj_init(struct timer_ctrl_object *tco)
{
tco->tcfg0 =&rTCFG0;
tco->tcfg1 =&rTCFG1;
tco->tcon =&rTCON;
tco->tcntb0 =&rTCNTB0;
tco->tcmpb0 =&rTCMPB0;
tco->tcnto0 =&rTCNTO0;
tco->tcntb1 =&rTCNTB1;
tco->tcmpb1 =&rTCMPB1;
tco->tcnto1 =&rTCNTO1;
tco->tcntb2 =&rTCNTB2;
tco->tcmpb2 =&rTCMPB2;
tco->tcnto2 =&rTCNTO2;
tco->tcntb3 =&rTCNTB3;
tco->tcmpb3 =&rTCMPB3;
tco->tcnto3 =&rTCNTO3;
tco->tcntb4 =&rTCNTB4;
tco->tcnto4 =&rTCNTO4;
tco->timer_cnt0 =0;
tco->timer_cnt1 =0;
tco->timer_cnt2 =0;
tco->timer_cnt3 =0;
}
/*
设置 rTCFG0 寄存器中的 prescaler
*/
int timer_set_prescaler(unsigned char timerX,unsigned int pres_val)
{
unsigned int tcfg0 =*timer_ctrl_object.tcfg0;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
/*
TIMER_0,TIMER_1的 prescaler 占用 rTCFG0 的前0~7位
*/
case TIMER_0:
case TIMER_1:
tcfg0&=0xFF00;
tcfg0|=pres_val<<PRESCALER0_OFFSET_TCFG0;
break;
/*
TIMER_2,TIMER_3,TIMER_4的 prescaler 占用 rTCFG0 的第8~16位
*/
case TIMER_2:
case TIMER_3:
case TIMER_4:
tcfg0&=0x00FF;
tcfg0|=(pres_val<<PRESCALER1_OFFSET_TCFG0);
break;
}
*timer_ctrl_object.tcfg0 =tcfg0;
return 1;
}
}
/*
设置 rTCFG1 寄存器中的 MUX,MUX的取值由time.h中的宏 MUX_X1_X2 定义,
X1_X2表示X1/X2,例如MUX_1_2,表示MUX为 1/2
*/
int timer_set_mux(unsigned char timerX,unsigned int mux_val)
{
unsigned int tcfg1 =*timer_ctrl_object.tcfg1;
unsigned int tmp_mux_val=0x0000000F;
if(timerX>4)
return -1;
else
{
tcfg1&=~(tmp_mux_val<<timerX*MUX_BITS_TCFG1);
tcfg1|=mux_val<<timerX*4;
*timer_ctrl_object.tcfg1=tcfg1;
return 1;
}
}
/*
DMA模式/中断模式选择,dma_sel_val的值由time.h中的宏TIMERX_DMA_MODE
和INTERRUPT_MODE定义
*/
void timer_dma_sel(unsigned int dma_sel_val)
{
unsigned int tcfg1 =*timer_ctrl_object.tcfg1;
unsigned int tmp_dma_sel_val=0x0000000F;
tcfg1&=~(tmp_dma_sel_val<<DMA_MODE_OFFSET_TCFG1);
tcfg1|=dma_sel_val<<DMA_MODE_OFFSET_TCFG1;
*timer_ctrl_object.tcfg1=tcfg1;
}
/*
设置rTCNTBX寄存器(计数寄存器)的值
*/
int timer_set_cnt_buffer(unsigned char timerX,unsigned int cnt_val)
{
if(timerX>4)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
*timer_ctrl_object.tcntb0=cnt_val;
break;
case TIMER_1:
*timer_ctrl_object.tcntb1=cnt_val;
break;
case TIMER_2:
*timer_ctrl_object.tcntb2=cnt_val;
break;
case TIMER_3:
*timer_ctrl_object.tcntb3=cnt_val;
break;
case TIMER_4:
*timer_ctrl_object.tcntb4=cnt_val;
break;
}
return 1;
}
}
/*
设置rTCMPBX寄存器(比较寄存器)的值
*/
int timer_set_cmp_buffer(unsigned char timerX,unsigned int cmp_val)
{
if(timerX>3)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
*timer_ctrl_object.tcmpb0=cmp_val;
break;
case TIMER_1:
*timer_ctrl_object.tcmpb1=cmp_val;
break;
case TIMER_2:
*timer_ctrl_object.tcmpb2=cmp_val;
break;
case TIMER_3:
*timer_ctrl_object.tcmpb3=cmp_val;
break;
}
return 1;
}
}
int timer_set_cnto_buffer(unsigned char timerX,unsigned int cnto_val)
{
if(timerX>4)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
*timer_ctrl_object.tcnto0=cnto_val;
break;
case TIMER_1:
*timer_ctrl_object.tcnto1=cnto_val;
break;
case TIMER_2:
*timer_ctrl_object.tcnto2=cnto_val;
break;
case TIMER_3:
*timer_ctrl_object.tcnto3=cnto_val;
break;
case TIMER_4:
*timer_ctrl_object.tcnto4=cnto_val;
break;
}
return 1;
}
}
/*
开始刷新CTCNTBX和CTCMPBX寄存器,当开启TIMERX时,该TIMER必须停止
对CTCNTBX和CTCMPBX的刷新,否则TIMER不会进行计数(CTCNTBX不会递减)
*/
int timer_update_cntb_and_cmpb(unsigned char timerX)
{
unsigned int tcon =*timer_ctrl_object.tcon;
unsigned int tmp_update=0x00000001;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
//CTCNTB0,CTCMPB0
case TIMER_0:
tcon&=~(tmp_update<<TIMER0_UPDATE_BIT_TCON);
tcon|=(tmp_update<<TIMER0_UPDATE_BIT_TCON);
break;
//CTCNTB1,CTCMPB1
case TIMER_1:
tcon&=~(tmp_update<<TIMER1_UPDATE_BIT_TCON);
tcon|=(tmp_update<<TIMER1_UPDATE_BIT_TCON);
break;
//CTCNTB2,CTCMPB2
case TIMER_2:
tcon&=~(tmp_update<<TIMER2_UPDATE_BIT_TCON);
tcon|=(tmp_update<<TIMER2_UPDATE_BIT_TCON);
break;
//CTCNTB3,CTCMPB3
case TIMER_3:
tcon&=~(tmp_update<<TIMER3_UPDATE_BIT_TCON);
tcon|=(tmp_update<<TIMER3_UPDATE_BIT_TCON);
break;
//CTCNTB4,CTCMPB4
case TIMER_4:
tcon&=~(tmp_update<<TIMER4_UPDATE_BIT_TCON);
tcon|=(tmp_update<<TIMER4_UPDATE_BIT_TCON);
break;
}
*timer_ctrl_object.tcon =tcon;
return 1;
}
}
/*
停止刷新CTCNTBX和CTCMPBX寄存器,当开启TIMERX时,该TIMER对应的
update位必须为0(停止刷新),否则TIMER不会进行计数(CTCNTBX不会递减)
*/
int timer_unupdate_cntb_and_cmpb(unsigned char timerX)
{
unsigned int tcon =*timer_ctrl_object.tcon;
unsigned int tmp_update=0x00000001;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
//CTCNTB0,CTCMPB0
case TIMER_0:
tcon&=~(tmp_update<<TIMER0_UPDATE_BIT_TCON);
break;
//CTCNTB1,CTCMPB1
case TIMER_1:
tcon&=~(tmp_update<<TIMER1_UPDATE_BIT_TCON);
break;
//CTCNTB2,CTCMPB2
case TIMER_2:
tcon&=~(tmp_update<<TIMER2_UPDATE_BIT_TCON);
break;
//CTCNTB3,CTCMPB3
case TIMER_3:
tcon&=~(tmp_update<<TIMER3_UPDATE_BIT_TCON);
break;
//CTCNTB4,CTCMPB4
case TIMER_4:
tcon&=~(tmp_update<<TIMER4_UPDATE_BIT_TCON);
break;
}
*timer_ctrl_object.tcon =tcon;
return 1;
}
}
/*
选择CTCNTBX加载模式,load_mode由 time.h中的宏AUTO_RELOAD 1
和 ONE_SHORT 定义
*/
int timer_load_mode(unsigned char timerX,unsigned load_mode)
{
unsigned int tcon =*timer_ctrl_object.tcon;
unsigned int tmp_reload_mode=0x00000001;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
tcon&=~(tmp_reload_mode<<TIMER0_LOADMODE_BIT_TCON);
tcon|=load_mode<<TIMER0_LOADMODE_BIT_TCON;
break;
case TIMER_1:
tcon&=~(tmp_reload_mode<<TIMER1_LOADMODE_BIT_TCON);
tcon|=load_mode<<TIMER1_LOADMODE_BIT_TCON;
break;
case TIMER_2:
tcon&=~(tmp_reload_mode<<TIMER2_LOADMODE_BIT_TCON);
tcon|=load_mode<<TIMER2_LOADMODE_BIT_TCON;
break;
case TIMER_3:
tcon&=~(tmp_reload_mode<<TIMER3_LOADMODE_BIT_TCON);
tcon|=load_mode<<TIMER3_LOADMODE_BIT_TCON;
break;
case TIMER_4:
tcon&=~(tmp_reload_mode<<TIMER4_LOADMODE_BIT_TCON);
tcon|=load_mode<<TIMER4_LOADMODE_BIT_TCON;
break;
}
*timer_ctrl_object.tcon =tcon;
return 1;
}
}
int timer_start(unsigned char timerX)
{
//停止TIMER的CTCNTB和CTCMPB进行update
timer_unupdate_cntb_and_cmpb(timerX);
unsigned int tcon =*timer_ctrl_object.tcon;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
//启动TIMER0
tcon|=(1<<TIMER0_START_BIT_TCON);
break;
case TIMER_1:
//启动TIMER1
tcon|=(1<<TIMER1_START_BIT_TCON);
break;
case TIMER_2:
//启动TIMER2
tcon|=(1<<TIMER2_START_BIT_TCON);
break;
case TIMER_3:
//启动TIMER3
tcon|=(1<<TIMER3_START_BIT_TCON);
break;
case TIMER_4:
//启动TIMER4
tcon|=(1<<TIMER4_START_BIT_TCON);
break;
}
*timer_ctrl_object.tcon =tcon;
return 1;
}
}
void timer_config(unsigned char timerX,
unsigned int cntb,unsigned int cmpb)
{
timer_set_prescaler(timerX,119);
timer_set_mux(timerX,MUX_1_16);
timer_set_cnt_buffer(timerX,cntb);
timer_set_cmp_buffer(timerX,cmpb);
timer_update_cntb_and_cmpb(timerX);
timer_load_mode(timerX,AUTO_RELOAD);
}
/*
* 有了 timer_enable(),我们就可以方便的调整任何一个timer的频率并开启它
*/
void timer_enable(unsigned char timerX,unsigned int freq)
{
switch(timerX)
{
case TIMER_0:
irq_mask(INT_TIMER0,IRQ_MASK);
timer_config(TIMER_0,26406/freq,0);
timer_start(TIMER_0);
irq_rotunie[INT_TIMER0]=&do_timer0;
irq_mask(INT_TIMER0,IRQ_UNMASK);
break;
case TIMER_1:
irq_mask(INT_TIMER1,IRQ_MASK);
timer_config(TIMER_1,26406/freq,0);
timer_start(TIMER_1);
irq_rotunie[INT_TIMER1]=&do_timer1;
irq_mask(INT_TIMER1,IRQ_UNMASK);
break;
case TIMER_2:
irq_mask(INT_TIMER2,IRQ_MASK);
timer_config(TIMER_2,26406/freq,0);
timer_start(TIMER_2);
irq_rotunie[INT_TIMER2]=&do_timer2;
irq_mask(INT_TIMER2,IRQ_UNMASK);
break;
case TIMER_3:
irq_mask(INT_TIMER3,IRQ_MASK);
timer_config(TIMER_3,26406/freq,0);
timer_start(TIMER_3);
irq_rotunie[INT_TIMER3]=&do_timer3;
irq_mask(INT_TIMER3,IRQ_UNMASK);
break;
case TIMER_4:
irq_mask(INT_TIMER4,IRQ_MASK);
timer_config(TIMER_4,26406/freq,0);
timer_start(TIMER_4);
irq_rotunie[INT_TIMER4]=&do_timer4;
irq_mask(INT_TIMER4,IRQ_UNMASK);
break;
}
}
/*
* timer_disable()用于停止指定的timer并关闭与该timer相关的中断
*/
int timer_disable(unsigned char timerX)
{
unsigned int tcon =*timer_ctrl_object.tcon;
if(timerX>4)
return -1;
else
{
switch(timerX)
{
case TIMER_0:
//停止TIMER0
tcon&=~(1<<TIMER0_START_BIT_TCON);
irq_mask(INT_TIMER0,IRQ_MASK);
break;
case TIMER_1:
//停止TIMER1
tcon&=~(1<<TIMER1_START_BIT_TCON);
irq_mask(INT_TIMER1,IRQ_MASK);
break;
case TIMER_2:
//停止TIMER2
tcon&=~(1<<TIMER2_START_BIT_TCON);
irq_mask(INT_TIMER2,IRQ_MASK);
break;
case TIMER_3:
//停止TIMER3
tcon&=~(1<<TIMER3_START_BIT_TCON);
irq_mask(INT_TIMER3,IRQ_MASK);
break;
case TIMER_4:
//停止TIMER4
tcon&=~(1<<TIMER4_START_BIT_TCON);
irq_mask(INT_TIMER4,IRQ_MASK);
break;
}
*timer_ctrl_object.tcon =tcon;
return 1;
}
}
//设置系统的时钟滴答
void set_sched_freq(unsigned int freq)
{
timer_enable(TIMER_0,freq);
}
extern struct task_struct* task[128];
//Timer0 中断服务例程
void do_timer0(struct cpu_registers *regs)
{
int sp;
irq_mask(INT_TIMER0,IRQ_MASK);
timer_ctrl_object.timer_cnt0++;
//若当前任务运行在内核态,则stime增一
if(current->cpu_registers.cpsr&SystemMode)
current->stime++;
else//若当前任务运行在用户态,则utime增一
current->utime++;
//当前进程时间片递减
current->counter--;
/*对当前任务的信号位图进行识别处理*/
for(current_singal=0;current_singal<NSIG;current_singal++)
{
if((current->signal)&(1<<current_singal))
{
current->signal&=~(1<<current_singal);
do_signal_irq(current_singal,regs);
break;
}
}
jiffies++; //时钟滴嗒增1
if(jiffies%10==0)
{
*led=0;
}
else
{
*led=1<<4;
}
switch_to_next(regs,schedule()); // 进行任务调度
clean_src_pnd(INT_TIMER0);
clean_int_pnd(INT_TIMER0);
irq_mask(INT_TIMER0,IRQ_UNMASK);
}
//Timer1 中断服务例程
void do_timer1(struct cpu_registers *regs)
{
irq_mask(INT_TIMER1,IRQ_MASK);
timer_ctrl_object.timer_cnt1++;
//在这里添加timer1的中断功能代码
//
printk("timer1 \n");
clean_src_pnd(INT_TIMER1);
clean_int_pnd(INT_TIMER1);
irq_mask(INT_TIMER1,IRQ_UNMASK);
}
//Timer2 中断服务例程
void do_timer2(struct cpu_registers *regs)
{
irq_mask(INT_TIMER2,IRQ_MASK);
timer_ctrl_object.timer_cnt2++;
//在这里添加timer2的中断功能代码
//
printk("timer2 \n");
clean_src_pnd(INT_TIMER2);
clean_int_pnd(INT_TIMER2);
irq_mask(INT_TIMER2,IRQ_UNMASK);
}
//Timer3 中断服务例程
void do_timer3(struct cpu_registers *regs)
{
irq_mask(INT_TIMER3,IRQ_MASK);
timer_ctrl_object.timer_cnt3++;
//在这里添加timer3的中断功能代码
//
printk("timer3 \n");
clean_src_pnd(INT_TIMER3);
clean_int_pnd(INT_TIMER3);
irq_mask(INT_TIMER3,IRQ_UNMASK);
}
//Timer4 中断服务例程
void do_timer4(struct cpu_registers *regs)
{
irq_mask(INT_TIMER4,IRQ_MASK);
timer_ctrl_object.timer_cnt4++;
//在这里添加timer3的中断功能代码
//
printk("timer4 \n");
clean_src_pnd(INT_TIMER4);
clean_int_pnd(INT_TIMER4);
irq_mask(INT_TIMER4,IRQ_UNMASK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -