既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
sleep/nanosleep
sleep() 和nanosleep() 是VxWorks提供的延时函数接口,sleep以秒为单位,nanosleep提供更精确的延时,传参是时钟的结构体,参数可以精确到ns,但实际上只能做到大于或等于这个时间。因为sleep或nanosleep函数延时的时间基准仍是tick,调用此函数的任务处于任务延时状态,这些点与taskDelay() 一致。不同的地方是,taskDelay() 是用于任务调度,taskDelay(0)有他自身的含义,sleep(0) 是没有意义的。前面提过,taskDelay(n) 延时时间(n-1) tick ~ n tick,而sleep/nanosleep保证实际延时时间大于或等于设定的时间参数。这一点我们可以通过编写一个测试程序试验证明。代码如下:
void testTimer(int sec,int nsec) // 测试函数,输入参数为秒和纳秒
{
struct timespec tm; // 声明一个时钟结构体,包括秒和纳秒成员
tm.tv_sec = sec; // 根据传参赋值
tm.tv_nsec = nsec;
nanosleep(&tm,NULL); // 执行延时程序
}
在tornado的windshell环境下执行该函数和输出结果如下:
-> sp testTimer,0,1000*1000*16; 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
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.
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新