cpu cycle counter gettimeofday 两种us级延时

us级延时可调用系统函数gettimeofday来实现,也可以用时钟计数器来实现
arm的要先使能用户态访问权限,v6 v7 v8都不一样 读取时钟计数器需先内核态使能,x86可以直接读
利用cpu时钟计数器可以ns级延时

以下代码

#include <sys/time.h>
#include <stddef.h>
#include <stdio.h>
#define CPUFREQ 7e8 // 700M

typedef void (*Delay)(unsigned int);
Delay delay;

//arm11 reset cycle counter
void rstccnt()
{
        unsigned int tmp;
        asm volatile (  "mrc p15, 0, %0, c15, c12, 0 \n"
                        "orr %0,%0,%1 \n"
                        "mcr p15, 0, %0, c15, c12, 0 \n"
                        :"+r" (tmp) : "r"(0x4));
}

unsigned int readccnt()
{
        unsigned int tmp;
        asm volatile ("mrc p15, 0, %0, c15, c12, 1 \n":"=r" (tmp));
        return tmp;
}

void ccdelay(unsigned int cnt) //cycle counter delay
{
        //cnt = ((CPUFREQ>>6) * cnt) >> 3 ;// avoid overflow    
        unsigned long long ct = cnt;
        cnt = (CPUFREQ*ct)/1e6;
        unsigned int tmp;

         rstccnt();
         tmp = readccnt();
         while(tmp < cnt)
              tmp = readccnt();
}

void tmdelay(unsigned int cnt)
{
        struct timeval cur;
        gettimeofday(&cur, NULL);
        unsigned long long now = cur.tv_sec * 1e6 + cur.tv_usec;
        unsigned long long end = now + cnt;
        while(now < end){
                gettimeofday(&cur, NULL);
                now = cur.tv_sec * 1e6 + cur.tv_usec;
        }
}
int main()
{
        unsigned int t[50];
        delay = ccdelay;
        (*delay)(100);
        t[0] = readccnt()*1e6/CPUFREQ;
        delay = tmdelay;
        for(int i = 1; i < 20; i++){
                rstccnt();
                (*delay)(20*i);
                t[i] = readccnt()*1e6/CPUFREQ;
        }
        printf("tccnt 100  %u \n",t[0]);
        for(int i = 1; i < 20; i++)
                printf(" %u-%u \n",20*i,t[i]);
}

输出

tccnt 100  100 
 20-231 
 40-42 
 60-61 
 80-82 
 100-102 
 120-124 
 140-142 
 160-162 
 180-181 
 200-201 
 220-221 
 240-241 
 260-261 
 280-321 
 300-302 
 320-322 
 340-342 
 360-361 
 380-382

相差不大, gettimeofday只在初次延时较大。
bcm2835测试,其它需改写前面的汇编代码。

附 其它几个读取时钟计数器的汇编代码
arm64

 asm volatile("mrs %0, cntvct_el0" :"=r"(ct));

arm32 v7

asm volatile("mrc p15,0,%0, c9, c13, 0":"=r"(ct));

x86 64

 asm volatile("rdtsc ; shl $32, %%rdx ; or %%rdx, %0": "=a"(ct));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yvee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值