• Nios II 系统时钟timestamp的应用


    在用Nios II做外设时序驱动的时候,经常会用延时函数。有时会常使用某个FPGA芯片和时钟,比如笔者一直使用的芯片是cyclone系列 EP2C35F484C8N,PLL输入SOPC时钟是50M。因此,提前测试硬件运行延时情况并编写今后常用的延时函数有一定的意义。
    软件:Quartus II 9.0, Nios II 9.0
    硬件配置:
    1、  在SOPC中调用Interval Timer核


    图 1 调用Interval Timer核

    2、配置Interval Time

    图 2 Interval Timer参数配置

    各参数说明请参照Quartus II Handbook Version 9.0 Volume 5: Embedded Peripherals, Chapter 24: Interval Timer Core.请根据需要进行设置。
    3、更改核的名称
    该名称可以按照自己的习惯取名。

     图 3 更改核的名称
    4、生成SOPC系统后,要在Nios II中进行设置。右击工程名->System Library Properties-> system library->Timestamp timer

     图 4 Nios II设置
    5、完成Nios II设置后,编译。
     
    软件编程
    参考Nios II Software Developer’s Handbook
    例程:
    #include <stdio.h>                  //printf()
    #include <unistd.h>                 //usleep()
    #include "system.h"                 
    #include <sys/alt_timestamp.h>      //timestamp
    #include "alt_types.h"
    void Delay0(unsigned long m)
    {
        usleep(m);
    }
    void Delay1(unsigned long n)
    {
        for(;n>0;n--);   
    }
    void Delay2(unsigned long p)
    {
        while(--p);
    }
    int main(void)
    {
        alt_u32 t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,
                t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,
                t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,
                freq;     
        if(alt_timestamp_start()<0)              //启动timestampe的计数
        {
            printf("No timestamp device available ");
        }
        else
        {
            //usleep
            t0 = alt_timestamp();                 // 测量时间戳t0 
            Delay0(1); 
            t1 = alt_timestamp();                 // 测量时间戳t1
            Delay0(4); 
            t2 = alt_timestamp();                 // 测量时间戳t2 
            Delay0(7); 
            t3 = alt_timestamp();                 // 测量时间戳t3  
            Delay0(10); 
            t4 = alt_timestamp();                 // 测量时间戳t4
            Delay0(40); 
            t5 = alt_timestamp();                 // 测量时间戳t5 
            Delay0(70); 
            t6 = alt_timestamp();                 // 测量时间戳t6  
            Delay0(100); 
            t7 = alt_timestamp();                 // 测量时间戳t7
            Delay0(400); 
            t8 = alt_timestamp();                 // 测量时间戳t8  
            Delay0(700); 
            t9 = alt_timestamp();                 // 测量时间戳t9 
            Delay0(1000); 
            t10 = alt_timestamp();                 // 测量时间戳t10
            Delay0(4000); 
            t11 = alt_timestamp();                 // 测量时间戳t11 
            Delay0(7000); 
            t12 = alt_timestamp();                 // 测量时间戳t12  
            Delay0(10000); 
            t13 = alt_timestamp();                 // 测量时间戳t13
            Delay0(40000); 
            t14 = alt_timestamp();                 // 测量时间戳t14
            Delay0(70000); 
            t15 = alt_timestamp();                 // 测量时间戳t15
            Delay0(100000); 
            t16 = alt_timestamp();                 // 测量时间戳t16 
            
            //for
            t17 = alt_timestamp();                 // 测量时间戳t17 
            Delay1(1); 
            t18 = alt_timestamp();                 // 测量时间戳t18
            Delay1(4); 
            t19 = alt_timestamp();                 // 测量时间戳t19 
            Delay1(7); 
            t20 = alt_timestamp();                 // 测量时间戳t20  
            Delay1(10); 
            t21 = alt_timestamp();                 // 测量时间戳t21
            Delay1(40); 
            t22 = alt_timestamp();                 // 测量时间戳t22 
            Delay1(70); 
            t23 = alt_timestamp();                 // 测量时间戳t23  
            Delay1(100); 
            t24 = alt_timestamp();                 // 测量时间戳t24
            Delay1(400); 
            t25 = alt_timestamp();                 // 测量时间戳t25  
            Delay1(700); 
            t26 = alt_timestamp();                 // 测量时间戳t26 
            Delay1(1000); 
            t27 = alt_timestamp();                 // 测量时间戳t27
            Delay1(4000); 
            t28 = alt_timestamp();                 // 测量时间戳t28 
            Delay1(7000); 
            t29 = alt_timestamp();                 // 测量时间戳t29  
            Delay1(10000); 
            t30 = alt_timestamp();                 // 测量时间戳t30
            Delay1(40000); 
            t31 = alt_timestamp();                 // 测量时间戳t31
            Delay1(70000); 
            t32 = alt_timestamp();                 // 测量时间戳t32
            Delay1(100000); 
            t33 = alt_timestamp();                 // 测量时间戳t33 
            
            //while
            t34 = alt_timestamp();                 // 测量时间戳t34 
            Delay2(1); 
            t35 = alt_timestamp();                 // 测量时间戳t35
            Delay2(4); 
            t36 = alt_timestamp();                 // 测量时间戳t36 
            Delay2(7); 
            t37 = alt_timestamp();                 // 测量时间戳t37  
            Delay2(10); 
            t38 = alt_timestamp();                 // 测量时间戳t38
            Delay2(40); 
            t39 = alt_timestamp();                 // 测量时间戳t39 
            Delay2(70); 
            t40 = alt_timestamp();                 // 测量时间戳t40  
            Delay2(100); 
            t41 = alt_timestamp();                 // 测量时间戳t41
            Delay2(400); 
            t42 = alt_timestamp();                 // 测量时间戳t42  
            Delay2(700); 
            t43 = alt_timestamp();                 // 测量时间戳t43 
            Delay2(1000); 
            t44 = alt_timestamp();                 // 测量时间戳t44
            Delay2(4000); 
            t45 = alt_timestamp();                 // 测量时间戳t45 
            Delay2(7000); 
            t46 = alt_timestamp();                 // 测量时间戳t46  
            Delay2(10000); 
            t47 = alt_timestamp();                 // 测量时间戳t47
            Delay2(40000); 
            t48 = alt_timestamp();                 // 测量时间戳t48
            Delay2(70000); 
            t49 = alt_timestamp();                 // 测量时间戳t49
            Delay2(100000); 
            t50 = alt_timestamp();                 // 测量时间戳t50 
            
            freq=alt_timestamp_freq();
            
            printf("系统时钟频率是 %ld Hz ", freq);   //freq可以写成ALT_CPU_FREQ
            printf(" ");
            printf("usleep(1)= %ld us ",(t1-t0)/(ALT_CPU_FREQ/1000000));  
            printf("usleep(4)= %ld us ",(t2-t1)/(ALT_CPU_FREQ/1000000));
            printf("usleep(7)= %ld us ",(t3-t2)/(ALT_CPU_FREQ/1000000));
            printf("usleep(10)= %ld us ",(t4-t3)/(ALT_CPU_FREQ/1000000));
            printf("usleep(40)= %ld us ",(t5-t4)/(ALT_CPU_FREQ/1000000));
            printf("usleep(70)= %ld us ",(t6-t5)/(ALT_CPU_FREQ/1000000));  
            printf("usleep(100)= %ld us ",(t7-t6)/(ALT_CPU_FREQ/1000000));
            printf("usleep(400)= %ld us ",(t8-t7)/(ALT_CPU_FREQ/1000000));
            printf("usleep(700)= %ld us ",(t9-t8)/(ALT_CPU_FREQ/1000000));  
            printf("usleep(1000)= %ld us ",(t10-t9)/(ALT_CPU_FREQ/1000000));
            printf("usleep(4000)= %ld us ",(t11-t10)/(ALT_CPU_FREQ/1000000));
            printf("usleep(7000)= %ld us ",(t12-t11)/(ALT_CPU_FREQ/1000000));  
            printf("usleep(10000)= %ld us ",(t13-t12)/(ALT_CPU_FREQ/1000000));
            printf("usleep(40000)= %ld us ",(t14-t13)/(ALT_CPU_FREQ/1000000));
            printf("usleep(70000)= %ld us ",(t15-t14)/(ALT_CPU_FREQ/1000000));
            printf("usleep(100000)= %ld us ",(t16-t15)/(ALT_CPU_FREQ/1000000));
            printf(" ");
            printf("for(1)= %ld us ",(t18-t17)/(ALT_CPU_FREQ/1000000));  
            printf("for(4)= %ld us ",(t19-t18)/(ALT_CPU_FREQ/1000000));
            printf("for(7)= %ld us ",(t20-t19)/(ALT_CPU_FREQ/1000000));
            printf("for(10)= %ld us ",(t21-t20)/(ALT_CPU_FREQ/1000000));
            printf("for(40)= %ld us ",(t22-t21)/(ALT_CPU_FREQ/1000000));
            printf("for(70)= %ld us ",(t23-t22)/(ALT_CPU_FREQ/1000000));  
            printf("for(100)= %ld us ",(t24-t23)/(ALT_CPU_FREQ/1000000));
            printf("for(400)= %ld us ",(t25-t24)/(ALT_CPU_FREQ/1000000));
            printf("for(700)= %ld us ",(t26-t25)/(ALT_CPU_FREQ/1000000));  
            printf("for(1000)= %ld us ",(t27-t6)/(ALT_CPU_FREQ/1000000));
            printf("for(4000)= %ld us ",(t27-t27)/(ALT_CPU_FREQ/1000000));
            printf("for(7000)= %ld us ",(t29-t28)/(ALT_CPU_FREQ/1000000));  
            printf("for(10000)= %ld us ",(t30-t29)/(ALT_CPU_FREQ/1000000));
            printf("for(40000)= %ld us ",(t31-t30)/(ALT_CPU_FREQ/1000000));
            printf("for(70000)= %ld us ",(t32-t31)/(ALT_CPU_FREQ/1000000));
            printf("for(100000)= %ld us ",(t33-t32)/(ALT_CPU_FREQ/1000000));
            printf(" ");
            printf("while(1)= %ld us ",(t35-t34)/(ALT_CPU_FREQ/1000000));  
            printf("while(4)= %ld us ",(t36-t35)/(ALT_CPU_FREQ/1000000));
            printf("while(7)= %ld us ",(t37-t36)/(ALT_CPU_FREQ/1000000));
            printf("while(10)= %ld us ",(t38-t37)/(ALT_CPU_FREQ/1000000));
            printf("while(40)= %ld us ",(t39-t38)/(ALT_CPU_FREQ/1000000));
            printf("while(70)= %ld us ",(t40-t39)/(ALT_CPU_FREQ/1000000));  
            printf("while(100)= %ld us ",(t41-t40)/(ALT_CPU_FREQ/1000000));
            printf("while(400)= %ld us ",(t42-t41)/(ALT_CPU_FREQ/1000000));
            printf("while(700)= %ld us ",(t43-t42)/(ALT_CPU_FREQ/1000000));  
            printf("while(1000)= %ld us ",(t44-t43)/(ALT_CPU_FREQ/1000000));
            printf("while(4000)= %ld us ",(t45-t44)/(ALT_CPU_FREQ/1000000));
            printf("while(7000)= %ld us ",(t46-t45)/(ALT_CPU_FREQ/1000000));  
            printf("while(10000)= %ld us ",(t47-t46)/(ALT_CPU_FREQ/1000000));
            printf("while(40000)= %ld us ",(t48-t47)/(ALT_CPU_FREQ/1000000));
            printf("while(70000)= %ld us ",(t49-t48)/(ALT_CPU_FREQ/1000000));
            printf("while(100000)= %ld us ",(t50-t49)/(ALT_CPU_FREQ/1000000));
        }
        return 0; 
        
    }
     
    运行结果如下:

    系统时钟频率是 50000000 Hz

    usleep(1)= 42 us
    usleep(4)= 38 us
    usleep(7)= 40 us
    usleep(10)= 44 us
    usleep(40)= 72 us
    usleep(70)= 102 us
    usleep(100)= 130 us
    usleep(400)= 418 us
    usleep(700)= 706 us
    usleep(1000)= 994 us
    usleep(4000)= 3874 us
    usleep(7000)= 6754 us
    usleep(10000)= 9634 us
    usleep(40000)= 38435 us
    usleep(70000)= 67234 us
    usleep(100000)= 96035 us

    for(1)= 9 us
    for(4)= 11 us
    for(7)= 15 us
    for(10)= 18 us
    for(40)= 53 us
    for(70)= 87 us
    for(100)= 122 us
    for(400)= 465 us
    for(700)= 809 us
    for(1000)= 226971 us
    for(4000)= 0 us
    for(7000)= 8018 us
    for(10000)= 11452 us
    for(40000)= 45782 us
    for(70000)= 80115 us
    for(100000)= 114447 us

    while(1)= 7 us
    while(4)= 10 us
    while(7)= 11 us
    while(10)= 14 us
    while(40)= 35 us
    while(70)= 58 us
    while(100)= 79 us
    while(400)= 298 us
    while(700)= 516 us
    while(1000)= 734 us
    while(4000)= 2916 us
    while(7000)= 5099 us
    while(10000)= 7281 us
    while(40000)= 29104 us
    while(70000)= 50927 us
    while(100000)= 72751 us

    在ALT_CPU_FREQ处右击,选中Open Declaration,可以找到ALT_CPU_FREQ在system.h中的定义。其值与函数alt_timestamp_freq()返回的值相同,都是在SOPC中设置的。如图5所示。

    图5 系统时钟设置
    分析得知, 100us以下用while较准确, 100us以上用usleep。
     
    补充:
    1、 要在SOPC中加入Interval Timer,并在Nios II中”system library properties”中的”system library”中,为timestamp timer指定物理设备,即在SOPCBuilder中添加的timer。否则出现如下错误。

     
    2、 如果没有头文件alt_types.h,会出现如下警告。


    3、(2011.5.31)

    在调试好延时函数之后,要将红圈处System Library Properties-> system library->Timestamp timer设置成none。本人就是遇到问题,比如最简单的LED跑马灯,同样的ptf和Nios II程序,之前做的可以运行。设置timer之后,实验没有现象,也没有提示错误,过了很久才找到的问题产生的原因。
    4、(2011.6.15)对于时序比较复杂要求严格的控制,比如DS18B20,不适用于Nios II完全控制它的操作。先用硬件逻辑实现,再用Nios II读取温度数据的办法较好。
  • 相关阅读:
    产品运营干货丨如何设计SAAS系统?
    SpringBoot原理及应用布署(中信银行)
    让大家出系分
    MyBatis的执行原理详细介绍
    技术管理进阶——一线Leader怎么做?经理的速成宝典
    技术管理进阶——如何脱颖而出?
    技术管理进阶——扎心了!老板问我:你们技术部和外包团队有什么区别?
    技术管理进阶——为什么要多总结,如何做总结?
    程序员与产品之间应该如何配合,什么时候技术为重,什么时候产品为重?
    java快速寻找一个数组的最大值或最小值, min, max,三种方法
  • 原文地址:https://www.cnblogs.com/lueguo/p/3414842.html
Copyright © 2020-2023  润新知