Exynos4412裸机开发系列教程--TICK机制
来源:互联网 发布:05~06赛季科比数据 编辑:程序博客网 时间:2024/06/05 15:33
Tick信号对于任何一款操作系统而言,就类似于人的心脏脉搏,关键性不言而寓,其本质上就是操作系统的激励源,各种调度算法,时间片等概念,包括具体的任务,可以理解为一个巨大的状态机,在激励源的激励下,按部就班执行,一切都是可预测的,只不过复杂度比较高而已。
同样,对于裸机而言,虽没有多任务执行的能力,但是实现了tick机制,可以编写出比较复杂的裸机软件,而且结构清新,可读性强,扩展简单。当然,如果我们真的需要在裸机下实现多种任务的执行,比如在后台下载http网页的时候,同时显示下载进度,并可以接收用户的任何点击操作,比如停止按钮等。我们可以通过协程就可以实现多任务了,协程的本质就是由程序员来控制各种任务的轮换,而不是由操作系统本身按照一定的算法进行调度。当然也可以用传统的MCU编程方法,前后台系统来实现。方法很多,但都异曲同工,条条大路通罗马。
Tick其实很简单,就是一周期性执行的一段代码,不管cpu当前在执行什么任务,时间到了,这段代码必须运行。在这个周期性的代码里,我们可以将一个全局变量加一,用于记录流逝的时间,在具体的应用软件里,我们可以依据此变量实现精确延时。
了解到这里,我想大家已经明白该怎么做了,就是申请一个周期性触发中断的定时器,然后在中断处理函数里,添加相应的代码而已。
Exynos4412裸机开发系列教程中使用了一个100HZ的定时器,也就最大精度为10ms,小于10ms的延时都是不太准确的,当然我们可以提高到1000HZ,这样精度就可以到1ms了。
好了,来看具体的实现。首先,我们需要初始化定时器,设置相应的寄存器,并注册中断处理函数:
void exynos4412_tick_initial(void){u64_t pclk;if(!clk_get_rate("pclk", &pclk))return;if(!request_irq("TIMER4", timer_interrupt, 0))return;/* Using pwm timer 4, prescaler for timer 4 is 16 */writel(EXYNOS4412_TCFG0, (readl(EXYNOS4412_TCFG0) & ~(0xff<<8)) | (0x0f<<8));/* Select mux input for pwm timer4 is 1/2 */writel(EXYNOS4412_TCFG1, (readl(EXYNOS4412_TCFG1) & ~(0xf<<16)) | (0x01<<16));/* Load value for 10 ms timeout */writel(EXYNOS4412_TCNTB4, (u32_t)(pclk / (2 * 16 * 100)));/* Auto load, manaual update of timer 4 and stop timer4 */writel(EXYNOS4412_TCON, (readl(EXYNOS4412_TCON) & ~(0x7<<20)) | (0x06<<20));/* Enable timer4 interrupt and clear interrupt status bit */writel(EXYNOS4412_TINT_CSTAT, (readl(EXYNOS4412_TINT_CSTAT) & ~(0x1<<4)) | (0x01<<4) | (0x01<<9));/* Start timer4 */writel(EXYNOS4412_TCON, (readl(EXYNOS4412_TCON) & ~(0x7<<20)) | (0x05<<20));/* initial system tick */tick_hz = 100;jiffies = 0;}
中断处理函数里,只让一个全局变量jiffies简单的加一,并清中断标志:
static void timer_interrupt(void * data){/* tick count */jiffies++;/* Clear interrupt status bit */writel(EXYNOS4412_TINT_CSTAT, (readl(EXYNOS4412_TINT_CSTAT) & ~(0x1f<<5)) | (0x01<<9));}当然这里还有些辅助函数及变量,这里一遍贴出
volatile u32_t jiffies = 0;static u32_t tick_hz = 0;u32_t get_system_hz(void){return tick_hz;}u64_t clock_gettime(void){if(get_system_hz() > 0)return (u64_t)jiffies * 1000000 / get_system_hz();return 0;}有了以上的tick机制,我们就可以实现一些比较使用的功能了,比如延时函数,具体实现如下。
static volatile u32_t loops_per_jiffy = 0;void __attribute__ ((noinline)) __delay(volatile u32_t loop){for(; loop > 0; loop--);}void udelay(u32_t us){u32_t hz = get_system_hz();if(hz)__delay(us * loops_per_jiffy / (1000000 / hz));else__delay(us);}void mdelay(u32_t ms){u32_t hz = get_system_hz();if(hz)__delay(ms * loops_per_jiffy / (1000 / hz));else__delay(ms * 1000);}static void calibrate_delay(void){u32_t ticks, loopbit;s32_t lps_precision = 8;u32_t hz = get_system_hz();if(hz > 0){loops_per_jiffy = (1<<12);while((loops_per_jiffy <<= 1) != 0){/* wait for "start of" clock tick */ticks = jiffies;while (ticks == jiffies);/* go ... */ticks = jiffies;__delay(loops_per_jiffy);ticks = jiffies - ticks;if(ticks)break;}loops_per_jiffy >>= 1;loopbit = loops_per_jiffy;while(lps_precision-- && (loopbit >>= 1)){loops_per_jiffy |= loopbit;ticks = jiffies;while(ticks == jiffies);ticks = jiffies;__delay(loops_per_jiffy);/* longer than 1 tick */if(jiffies != ticks)loops_per_jiffy &= ~loopbit;}}else{loops_per_jiffy = 0;}}void exynos4412_tick_delay_initial(void){calibrate_delay();}这里有个关键的函数calibrate_delay,这个是用于计算loops_per_jiffy,计算方法为逐次逼近,这个是linux内核里计算bogomips的方法,即每秒种运行多少条指令,是一个相对量,同平台,同环境比较才有意义。
计算出此变量后,我们就可以实现精确延时了,比如mdelay及udelay函数,大家可以自行做实验,看是否准确。
恩,需要源码的朋友,可以直接在本博客寻找链接,或者直接加QQ8192542
0 0
- Exynos4412裸机开发系列教程--TICK机制
- Exynos4412裸机开发系列教程--LED流水灯
- Exynos4412裸机开发系列教程--蜂鸣器
- Exynos4412裸机开发系列教程--启动流程
- Exynos4412裸机开发系列教程--时钟管理
- Exynos4412裸机开发系列教程--中断管理
- Exynos4412裸机开发系列教程--源码下载
- S5P4418裸机开发系列教程--源码下载
- Exynos4412裸机开发综合练习
- Exynos4412裸机开发综合练习
- Exynos4412 裸机开发—— 流水灯
- Exynos4412裸机开发——PWM定时器
- Exynos4412裸机开发——中断处理
- Exynos4412裸机开发 —— 看门狗定时器
- Exynos4412裸机开发 —— UART
- Exynos4412 裸机开发 —— IIC总线
- Exynos4412 裸机开发 —— IIC总线
- Exynos4412裸机开发 —— UART
- Codeforces Round #262 (Div. 2) B
- 摄像头立体成像资料记录--SLAM和MonoSLAM
- Chanel iPhone 5 Case bvbolk:n
- UIWebView与js(JavaScript)交互
- XCode快捷键使用
- Exynos4412裸机开发系列教程--TICK机制
- 排列数据的输出(二) 循环处理
- ios获得UIImage的主色调方法
- EaselJS简明教程2-动画
- js 清空某个div中的input标签值
- android之JSON 进行网络数据交换
- Android 给类及方法自动添加注释 高亮显示选中词
- Cocos2d-x 3.1 一步步做屏幕适配
- Description Resource Path Location Type undefined reference to