Commit 3497d157 authored by Alessandro Rubini's avatar Alessandro Rubini

lib: add usleep.c (and call its own init from main)

This adds a real usleep implementation. The init function calculates
the "loops per jiffy" variable, by watching the timer ticks before
interrupts are enabled by spll_init().  This init takes 40ms.

Then, the udelay runs the same loop used in calculating lpj, and
is thus correct (it will be slower because we have interrupts running
at run time, but this is not a problem).
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent b445f5ca
...@@ -13,10 +13,3 @@ ...@@ -13,10 +13,3 @@
#endif #endif
static inline uint16_t ntohs(uint16_t x) {return x;} static inline uint16_t ntohs(uint16_t x) {return x;}
static inline int usleep(useconds_t useconds)
{
while(useconds--)
asm volatile("nop");
return 0;
}
...@@ -39,6 +39,12 @@ void timer_init(uint32_t enable); ...@@ -39,6 +39,12 @@ void timer_init(uint32_t enable);
uint32_t timer_get_tics(); uint32_t timer_get_tics();
void timer_delay(uint32_t how_long); void timer_delay(uint32_t how_long);
/* usleep.c */
extern void usleep_init(void);
extern int usleep(useconds_t usec);
extern volatile struct SYSCON_WB *syscon; extern volatile struct SYSCON_WB *syscon;
/**************************** /****************************
......
obj-y += lib/util.o lib/atoi.o obj-y += lib/util.o lib/atoi.o
obj-y += lib/usleep.o
obj-y += lib/net.o obj-y += lib/net.o
obj-$(CONFIG_ETHERBONE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o obj-$(CONFIG_ETHERBONE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o
...@@ -12,13 +12,6 @@ ...@@ -12,13 +12,6 @@
#include "wrc_ptp.h" #include "wrc_ptp.h"
#include <syscon.h> #include <syscon.h>
int usleep(useconds_t useconds)
{
while(useconds--) asm volatile("nop");
return 0;
}
uint64_t ptpd_netif_get_msec_tics(void) uint64_t ptpd_netif_get_msec_tics(void)
{ {
return timer_get_tics(); return timer_get_tics();
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <wrc.h>
#include <syscon.h>
#include <shell.h>
static int usleep_lpj; /* loops per jiffy */
static inline void __delay(int count)
{
while (count-- > 0)
asm("");
}
static int verify_lpj(int lpj)
{
unsigned long j;
/* wait for the beginning of a tick */
j = timer_get_tics() + 1;
while (timer_get_tics() != j)
;
__delay(lpj);
/* did it expire? */
j = timer_get_tics() - j;
if (0)
pp_printf("check %i: %li\n", lpj, j);
return j;
}
void usleep_init(void)
{
int lpj = 1024, test_lpj;
int step = 1024;
/* Increase until we get over it */
while (verify_lpj(lpj) == 0) {
lpj += step;
step *= 2;
}
/* Ok, now we are over; half again and restart */
lpj /= 2; step /= 4;
/* So, *this* jpj is lower, and with two steps we are higher */
while (step) {
test_lpj = lpj + step;
if (verify_lpj(test_lpj) == 0)
lpj = test_lpj;
step /= 2;
}
usleep_lpj = lpj;
pp_printf("Loops per jiffy: %i\n", lpj);
}
/* lpj is around 20800 on the spec: the above calculation overflows at 200ms */
int usleep(useconds_t usec)
{
/* Sleep 10ms each time, so we support 20x faster cards */
const int step = 10 * 1000;
const int usec_per_jiffy = 1000 * 1000 / TICS_PER_SECOND;
const int count_per_step = usleep_lpj * step / usec_per_jiffy;
while (usec > step) {
__delay(count_per_step);
usec -= step;
}
__delay(usec * usleep_lpj / usec_per_jiffy);
return 0;
}
...@@ -224,6 +224,7 @@ int main(void) ...@@ -224,6 +224,7 @@ int main(void)
_endram = ENDRAM_MAGIC; _endram = ENDRAM_MAGIC;
wrc_initialize(); wrc_initialize();
usleep_init();
shell_init(); shell_init();
wrc_ptp_set_mode(WRC_MODE_SLAVE); wrc_ptp_set_mode(WRC_MODE_SLAVE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment