/* result: [0] Calibrating delay loop... 299.00 BogoMIPS (lpj=1495040,armclk=600000000) [0] clock source mult=0x29ab , shift=8 [0] one jiffies delay,s=0x190c1f4,e=0x1946cc5,ns=10014354( 10ms , 100HZ ) [0] delay us=1234,s=0x195437d,e=0x195b701,ns=1232205 [0] one jiffies delay,s=0x190c39a,e=0x1946e58,ns=10013562 [0] delay us=584,s=0x19544ec,e=0x1957bb6,ns=584434 delay us=11,s=0x171b8c0,e=0x171b9fb,ns=13125 ddr_pll_delay: arm clk(600,000,000hz),s=0x1199726,e=0xf6d124d,ns=10014981250 arm clk(60,000,000hz),s=0x119bcfa,e=0x2887f9c,ns=1001531380 arm clk(40,000,000hz),s=0x119b766,e=0x20e3b5b,ns=667711073 arm clk(6,000,000hz),s=0x1734eec,e=0x197fd0f,ns=100164588 */ int rk28_delay( int us ) { struct rockchip_clock *clock = &rockchip_clocks; struct clocksource *cs = &clock->clocksource; cycle_t s,e; unsigned long ticks; int clk = rockchip_clk_get_arm(); printk("clock source mult=0x%x , shift=%d\n" , cs->mult , cs->shift ); ticks = jiffies; while( jiffies < ticks+1 ); s = cs->read(); ticks = jiffies; while( jiffies < ticks+1 ); e = cs->read(); printk("one jiffies delay,s=0x%Lx,e=0x%Lx,ns=%Ld\n" , s , e , cyc2ns(cs , e-s ) ); s = cs->read(); udelay( us ); e = cs->read(); printk("delay us=%d,s=0x%Lx,e=0x%Lx,ns=%Ld\n" , us , s , e , cyc2ns(cs , e-s ) ); // for set ddr_pll_delay clk /= 100; s = cs->read(); ddr_pll_delay( clk ); e = cs->read(); printk("ddr_pll_delay arm clk(%dhz),s=0x%Lx,e=0x%Lx,ns=%Ld\n" , clk , s , e , cyc2ns(cs , e-s ) ); return 0x20; }
int main(int ac, char *av[]) { struct cfg_s c; struct timeval end; double ll; int i; char msg[40]; uint64_t cyc; struct sched_param schedparam; schedparam.sched_priority = 11; if (sched_setscheduler(0, SCHED_FIFO, &schedparam) == 0) printf("Set process to real-time priority %i\n", 11); else printf("Couldn't invoke real time scheduling priority %i" " (access denied?)\n", 11); bzero(&c, sizeof(c)); c.ac = ac; c.av = av; init(&c); gettimeofday(&c.time, NULL); cyc = mainloop(&c); gettimeofday(&end, NULL); end.tv_sec -= c.time.tv_sec; end.tv_usec -= c.time.tv_usec; if (end.tv_usec < 0) { end.tv_usec += 1000000; end.tv_sec--; } c.time = end; ll = end.tv_sec*1000000 + end.tv_usec; ll *= 1000; /* convert to nanoseconds */ ll /= c._enqueue; sprintf(msg, "1::%d", c.flows); D("%-8s n %d %d time %d.%06d %8.3f qlen %d %d flows %s drops %d", c.name, c._enqueue, c.loops, (int)c.time.tv_sec, (int)c.time.tv_usec, ll, c.th_min, c.th_max, c.fs_config ? c.fs_config : msg, c.drop); D("---Accurate Timing Information---"); D("Time for Cycle:\n\t Originally:%8.3f ns\n\tWith gticks:%8.3f ns\n", ll, (double) cyc2ns(cyc) / c._enqueue); D("Summary time:\n\t Originally: %d.%06d s\n\tWith gticks: %8.6f s\n", (int)c.time.tv_sec, (int)c.time.tv_usec, (double) cyc2ns(cyc)/1000000000.0); dump(&c); DX(1, "done ac %d av %p", ac, av); for (i=0; i < ac; i++) DX(1, "arg %d %s", i, av[i]); return 0; }
unsigned long long sched_clock(void) { unsigned long long cycles; /* jiffies based sched_clock if no clocksource is installed */ if (!clocksource_sh.rating) return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ); cycles = clocksource_sh.read(&clocksource_sh); return cyc2ns(&clocksource_sh, cycles); }
/* * Returns current time from boot in nsecs. It's OK for this to wrap * around for now, as it's just a relative time stamp. */ unsigned long long sched_clock(void) { static int first = 1; static cycle_t saved_ticks; static int saved_ticks_valid; static unsigned long long base; static unsigned long long last_result; unsigned long irq_flags; static cycle_t last_ticks; cycle_t ticks; static unsigned long long result; local_irq_save(irq_flags); last_ticks = saved_ticks; saved_ticks = ticks = sec_sched_timer_read(); if(!saved_ticks_valid) { saved_ticks_valid = 1; last_ticks = ticks; base -= cyc2ns(&clocksource_sec, ticks); } if(ticks < last_ticks) { if (first) first = 0; else { base += cyc2ns(&clocksource_sec, clocksource_sec.mask); base += cyc2ns(&clocksource_sec, 1); } } last_result = result = cyc2ns(&clocksource_sec, ticks) + base; local_irq_restore(irq_flags); return result; }
static int linux_tx_raw(int burst, struct tx_arg_t *arg, struct fun_ret_t *ret, struct linux_priv_core *core, struct sockaddr_ll *socket) { int i, j; uint64_t start, end, ticks=0; for (i=0; i<burst; i++) { sched_yield(); start = gticks_serial(); for (j=0; j<arg->pkt_in_burst; j++) { sendto(core->sockfd, arg->master_pkt, arg->pkt_size, 0, (struct sockaddr*)socket, sizeof(struct sockaddr_ll)); } end = gticks_serial(); ticks += end-start; } ret->count = arg->count; ret->ns = cyc2ns(ticks); ret->pkt_size = arg->pkt_size; return 0; }
/* * Rounds down to nearest nsec. */ unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k) { return cyc2ns(&clocksource_32k, ticks_32k); }
/* Remember: this is a thread, or it will lock until first packet */ int linux_rx (struct rx_arg_t *arg, int (*callback)(int, void*)) { struct fun_ret_t *ret = arg->ret; struct pollfd fds[1]; struct linux_priv_core *core = (struct linux_priv_core*) arg->state; struct sockaddr from; socklen_t fromlen = sizeof(struct sockaddr_in); int i, now_read = 0, B_read = 0, p_read = 0; char buffer[MTU]; memset(fds, 0, sizeof(fds)); fds[0].fd = core->sockfd; fds[0].events = (POLLIN); uint64_t start, end, wstart; /* unbounded wait for the first packet. */ for (;;) { i = poll(fds, 1, 1000); if (i > 0 && !(fds[0].revents & POLLERR)) break; //D("waiting for initial packets, poll returns %d %d\n", i, fds[0].revents); } // activate other end if we are fw if (callback != NULL) callback(1, arg->state); start = gticks_serial(); while(1) { //sched_yield(); /* Note that "buffer" should be at least the MTU size of the interface, eg 1500 bytes */ wstart = gticks_serial(); if (poll(fds, 1, 1 * 1000) <= 0) break; now_read = recvfrom(core->sockfd, buffer, sizeof(buffer), 0,(struct sockaddr *)&from,&fromlen); //now_read = recv(core->sockfd, buffer, sizeof(buffer), 0); //D("Recv this pack:"); //debug_tx((struct pkt*) buffer); if (now_read < 0) break; ++p_read; B_read += now_read; if (callback != NULL && now_read > 0 && p_read % arg->pkt_in_burst == 0) callback(arg->pkt_in_burst, arg->state); if (arg->count > 0 && p_read > arg->count) break; } end = gticks_serial(); if (callback != NULL) callback ((p_read % arg->pkt_in_burst)-1, arg->state); ret->count = p_read; ret->ns = cyc2ns(end-start) - cyc2ns(end-wstart); if (p_read != 0) ret->pkt_size = (B_read / p_read) ; else ret->pkt_size = 0; return 0; }
int linux_tx(struct tx_arg_t *arg) { int i, j, burst = arg->count/arg->pkt_in_burst; struct sockaddr_ll socket_address; struct linux_priv_core *core = (struct linux_priv_core*) arg->state; struct fun_ret_t *ret = arg->ret; /* Index of the network device */ socket_address.sll_ifindex = core->if_idx->ifr_ifindex; /* Address length*/ socket_address.sll_halen = ETH_ALEN; /* Destination MAC */ bcopy(arg->master_pkt->eh.ether_dhost, &socket_address.sll_addr, 6); //D("SEND this pack"); //debug_tx(arg->master_pkt); if (arg->rem == NULL || arg->rem->tv_nsec == 0) return linux_tx_raw(burst, arg, ret, core, &socket_address); /* Send packet */ uint64_t start, end, sleep_end, ticks = 0, sleep_ns; long fiftyperc, skew = 0; struct timespec delay; delay.tv_sec = 0; delay.tv_nsec = arg->rem->tv_nsec; // activate the receiver sendto(core->sockfd, arg->master_pkt, arg->pkt_size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)); for (i=0; i<burst-1; i++) { sched_yield(); start = gticks_serial(); nanosleep(&delay, NULL); sleep_end = gticks_serial(); for (j=0; j<arg->pkt_in_burst; j++) { sendto(core->sockfd, arg->master_pkt, arg->pkt_size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)); } end = gticks_serial(); ticks += end-start; sleep_ns = cyc2ns(sleep_end - start); skew = sleep_ns - arg->rem->tv_nsec; fiftyperc = abs(skew * 0.5); //D("Dormito per %"PRIu64" us ma dovevo per %li us", sleep_ns/1000, arg->rem->tv_nsec/1000); //D("Ho accumulato un ritardo di %li", skew/1000); if (skew > 0) delay.tv_nsec -= fiftyperc; else delay.tv_nsec += fiftyperc; //D("50%%: %li us, dormo per %li us", fiftyperc/1000, delay.tv_nsec/1000); } sched_yield(); start = gticks_serial(); nanosleep(&delay, NULL); // one is already sent at the beginning to activate the receiver for (j=1; j<arg->pkt_in_burst; j++) { sendto(core->sockfd, arg->master_pkt, arg->pkt_size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)); } // Send the remaining from the modulo for (j=0; j < arg->count % arg->pkt_in_burst; j++) { sendto(core->sockfd, arg->master_pkt, arg->pkt_size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)); } end = gticks_serial(); ticks += end-start; ret->count = arg->count; ret->ns = cyc2ns(ticks); ret->pkt_size = arg->pkt_size; return 0; }
/* * Rounds down to nearest nsec. */ unsigned long long sec_ticks_to_nsecs(unsigned long ticks) { return cyc2ns(&clocksource_sec, ticks); }