tWdbTask _wdbTask 230e920 3 READY 412cd8 230e7c8 0 0
s2u24 _testTimer 23092b8 100 DELAY 412cd8 23091b4 0 1
value = 0 = 0x0
-> sp testTimer,0,1; i
NAME ENTRY TID PRI STATUS PC SP ERRNO DELAY
tExcTask _excTask 2318d10 0 PEND 412cd8 2318c14 0 0
tLogTask _logTask 23131e0 0 PEND 412cd8 23130e4 0 0
tWdbTask _wdbTask 230e920 3 READY 412cd8 230e7c8 0 0
s2u25 _testTimer 23092b8 100 DELAY 412cd8 23091b4 0 1
value = 0 = 0x0
可见延时1ns和16ms的结果都是一样的,都相当于taskDelay(1)。
高精度时钟sysTimeStamp
sysTimeStamp()也称作时间戳,是通过系统时钟实现的,刚开始也觉得费解,系统时钟的定时周期就是tick,怎么实现高精度时钟呢?通过走读BSP底层代码发现,sysTimeStamp其实是通过读取该定时器的当前计数值来获取高精度的定时。通过sysTimestampFreq)函数可以得到系统时间戳的频率,它往往反映的是CPU定时器的基准频率。当然如此高的分辨率只能是一个理想值,对于不同的系统不一定都能实现。毕竟该时间戳的实现方式就有一个致命的弱点:通过查询方式。系统时钟定时中断是以tick为单位的,进一步提高分辨率读取定时器计数值(CPU的一个特殊功能寄存器),只能是查询方式实现。如下代码示例。
void msDelay( int ms )
{
int t, t1, t2;
t1 = sysTimestamp(); // 记录上一轮时间戳
do
{
t = 0; //计数清零
while(t <sysTimestampFreq()/1000) // 时间戳小于1ms
{
t2 = sysTimestamp(); // 读取当前时间戳
if( t2>t1) t += (t2-t1); // 根据前后时间戳比较算出经历时间
else t+=t2; // 发生定时中断清零,应该为t+=(t2+计数最大值-t1),这里简化计算
t1 = t2; // 当前时间戳保存到下一轮计算
}
}while(ms–) // 循环ms次
}
这种方式定时比较占用系统资源,但是能方便实现并只适用于短时间的定时。为确保定时准确,应该在锁定中断情况下调用sysTimestamp,否则应该考虑使用sysTimestampLock函数。
辅助时钟
辅助时钟是利用目标板上CPU的另一个定时器(除了系统时钟之外)中断实现的,它可以灵活配置实现高分辨率的定时,而且容易实现ms级甚至us级定时。VxWorks也提供一系列与系统时钟相同的操作接口,用户可以方便挂接自己的中断处理函数,时钟分辨率的高低取决于硬件定时器的精度和用户中断函数的长短。要将辅助时钟作为精确的延时机制(比如毫秒级延时),我们可以通过这种方式实现。初始化程序先调用SysAuxClkRateSet()函数设置辅助时钟中断周期为1ms(一般在config.h文件中对中断频率作了限定,在AUX_CLK_RATE_MIN和AUX_CLK_RATE_MAX之间,如果需要可以对此宏定义修改),通过SysAuxClkConnect() 将用户处理函数连接到辅助时钟中断上,用户处理函数可以为SemGive(semTimer)释放一个同步信号量。编写一个msDelay(int ms)作为其他任务调用接口,函数代码如下:
void msDelay(int ms)
{
int i;
sysAuxClkEnable(); //启动辅助定时器
for(i=0;i<ms;i++) //循环ms次
semTake(semTimer); //等待定时中断释放信号量
sysAuxClkDisable(); //关闭辅助定时器
}
这种方式能实现十分精确的定时,调用延时的任务处于任务阻塞状态。但是使用上任存在缺陷,不能实现多个任务同时调用,并且需要CPU的一个时钟资源,如果没有多余的时钟,这一方法就不能实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aaFwDVNA-1636160296577)(https://www.vxworks.net/images/app/timer-spy.jpg)]
另外需要注意一点:Tornado的调试工具Browser ->Spy Chart的实现原理是利用辅助定时器产生中断,并记录当前被中断的任务,抽样数据反映各任务CPU占用率的情况。因此如果调试程序中使用了辅助定时器,使用Spy Chart时,定时处理函数会被重新挂接,原有定时挂接的程序将得不到进行。反过来,如果在Spy Chart运行之后挂接辅助定时处理函数,Spy Chart的运行将出现问题。试验发现,运行Spy Chart后重现挂接辅助定时处理函数,Spy Chart即使选中自动刷新,各任务状态也不会更新,如图2所示。
VxWorks提供的定时接口(不一定专门用于定时,可以间接实现)远不只这些,具体使用哪种方式,应根据其精度要求,资源状态和优先级要求而定。
后面介绍一下重要函数的使用方法
taskDelay( )
NAME
*taskDelay*( ) - delay a task from executing
SYNOPSIS
STATUS taskDelay
(
int ticks /* number of ticks to delay task */
)
DESCRIPTION
This routine causes the calling task to relinquish the CPU for the duration specified (in ticks). This is commonly referred to as manual rescheduling, but it is also useful when waiting for some external condition that does not have an interrupt associated with it.
If the calling task receives a signal that is not being blocked or ignored, *taskDelay*( ) returns ERROR and sets errno to EINTR after the signal handler is run.
RETURNS
OK, or ERROR if called from interrupt level or if the calling task receives a signal that is not blocked or ignored.
ERRNO
S_intLib_NOT_ISR_CALLABLE, EINTR
SEE ALSO
VxWorks中的sysClkRateGet()返回系统时钟详解
操作系统总是基于某个时钟节拍来跑的,这个节拍的得到往往是通过硬件时钟中断得到,一般来说这个中断的优先级就比NMI低一点点,比其他的都高。
这个中断是供给操作系统用的,操作系统用他来进行调度等各种处理。而在VxWorks中的一个重要参数就是SYS_CLK_RATE这个参数,也就是系统时钟率。它的含义是:系统时钟滴嗒在一秒钟之内发生多少次。
比如说,你定义为 60,那么系统时钟在1s中将发生60次中断,两次之间的时间差就是1/60s。发生中断后,操作系统可以进行任务切换。也就是说,如果你有一个任务被挂起,则至少要过1/60s后被激活(其它中断除外)。
又假如你设置为1000,那么系统时钟1秒发生1000次中断,两个时间差就是1ms。而函数sysClkRateGet就是用来获取系统时钟率的,如果你没有调用sysClkRateSet() 函数对系统时钟率进行重新设置的 话,其返回值应该是你在config.h中定义的SYS_CLK_RATE宏的值。而函数taskDelay()是以tick数目为单位的,比如 taskDelay(1) 是指将调用该函数的任务延迟1个tick。那么时间是多少呢,根据你的SYS_CLK_RATE的值,其实际时间不同,但具体 时间是1/SYS_CLK_RATE。假如SYS_CLK_RATE是1000,那么就是1ms。如果是60那么就大约是16.67ms。
通常来讲,VxWorks手册建议不要将时钟率设得太高,否则它就由硬实时变得趋向于软实时了。因为过高的时钟率使得内核调度频繁进入,可能导致一些低优先 级的硬件中断不能得到及时响应。当然,也不要太担心,在x86系统中完全可以设置为1000,这样比较好使,1个tick就是1ms,跟Windows一 样了。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
续会持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-JZCydDyE-1712918870995)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!