• [转]关于编写Nios II的延时函数的一点心得


    平台

    硬件:nios/f 100MHz

    软件:image

    内容

    0 一点说明

    本文仅讨论所述平台的一点心得,若其他等级的nios或优化,请自行研究。

    1 usleep()有多准

    参考[笔记].怎样使用Nios II中的timestamp_timer?.[Nios II][SOPC Builder],我们做以下实验:

    代码1 本文所用测试代码模板

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <stdio.h>                    // printf()
    #include <unistd.h>                   // usleep()
    #include "system.h"                   // 系统
    #include "my_types.h"                 // 数据类型
    #include "sys/alt_timestamp.h"        // timestamp
    int main()
    {
      u32 t0, t1, t2;
      vu32 i;
     
      alt_timestamp_start();                // 开启时间戳服务
     
      t0 = alt_timestamp();                 // 测量时间戳t0
      usleep(1000);
      t1 = alt_timestamp();                 // 测量时间戳1
      for(i=0; i<1000; i++);
      t2 = alt_timestamp();                 // 测量时间戳1
     
      printf("时间戳(t1-t0) = %ld ", (t1-t0));
      printf("时间戳(t2-t1) = %ld ", (t2-t1));
      printf(" ");
      printf("系统时钟频率是 %ld Hz ", alt_timestamp_freq());
     
      return 0;
    }

    其中第14行和第16行的内容是下面讨论的重点

    1
    usleep(1000);
    1
    for(i=0; i<100; i++);

    众所周知,usleep()是Nios II HAL自带的us级的延时函数,那么它究竟有多准。

    (1)修改第14行为:

    1
    usleep(1*1000*1000);

    编译运行的结果如图1.1 所示,usleep(1*1000*1000)共占用99,568,957个tick。那么1s有多少tick呢,正如显示的时钟频率一样,1s可分为100,000,000个tick。也就是说usleep(1*1000*1000)实际延时为99,568,957/100M=0.99568957 s。这个时间已经相当准了,和1s差距不大。

    图1.1 usleep(1*1000*1000)的结果

    图1.1 usleep(1*1000*1000)的结果

    (2)修改第14行为:

    1
    usleep(1*1000);

    编译运行的结果如图1.2所示。这一次是100,843/100M=1.008ms,也不错。

    图1.2 usleep(1*1000)的结果

    图1.2 usleep(1*1000)的结果

    (3)修改第14行为:

    1
    usleep(100);

    编译运行的结果如图1.3所示。这一次是11,743/100M=117.43us,误差开始显现了。

    图1.3 usleep(100) 的结果

    图1.3 usleep(100) 的结果

    (4)修改第14行为:

    1
    usleep(10);

    编译运行的结果如图1.4所示。这一次是1,511/100M=15.11us,误差不是一点点。

    图1.4 usleep(10)的结果

    图1.4 usleep(10)的结果

    (5)修改第14行为:

    1
    usleep(1);

    编译运行的结果如图1.5所示。这一次是620/100M=6.2us,已经相当离谱了。

    图1.4 usleep(1)的结果

    图1.4 usleep(1)的结果

    小结一下:usleep()在ms级别及以上的延时的确很准,但是us级别就有点捉襟见肘了。

    2 想要延时1us怎么办?

    (1)修改第16行为:

    1
    for(i=0; i<100; i++);

    编译运行的结果如图2.1所示,亦即延时1,197/100M=11.97us。

    图2.1 for(100)的结果

    图2.1 for(100)的结果

    (2)修改第16行为:

    1
    for(i=0; i<10; i++);

    编译运行的结果如图2.2所示,亦即延时207/100M=2.07us。

    图2.2 for(10)的结果

    图2.2 for(10)的结果

    (3)修改第16行为:

    1
    for(i=0; i<1; i++);

    编译运行的结果如图2.2所示,亦即延时106/100M=1.06us。

    图2.3 for(1)的结果

    图2.3 for(1)的结果

    小结:for(1)可以很第实现延时1us的任务。

    需要注意的地方

    观察第9行,此处i被申明为vu32(volatile unsigned long)类型,倘若改为u32(unsigned long)类型的话。那么无论i值为多少,都会被gcc优化掉的。

    4 小结

    timestamp可以有效地协助我们编写小时间段的延时代码。

  • 相关阅读:
    投票系统完善
    投票系统设计与实现
    一天天进步
    洛谷P4168 [Violet]蒲公英 题解 数列分块
    LOJ6285. 数列分块入门 9 题解
    洛谷P5340 大中锋的游乐场 题解 分层图最短路
    P1073 [NOIP2009 提高组] 最优贸易 题解 分层图最短路
    洛谷P7297 [USACO21JAN] Telephone G 题解 分层图最短路
    洛谷P1119 灾后重建 题解 Floyd算法
    安装redis 后本地系统空间越来越小
  • 原文地址:https://www.cnblogs.com/tubujia/p/9335003.html
Copyright © 2020-2023  润新知