Patchwork Clean up delay loop calibration

login
register
about
Submitter Carl-Daniel Hailfinger
Date 2010-03-06 03:28:35
Message ID <4B91CBE3.4040306@gmx.net>
Download mbox | patch
Permalink /patch/1016/
State Accepted
Commit r986
Headers show

Comments

Carl-Daniel Hailfinger - 2010-03-06 03:28:35
Note: This patch is the first step towards a better delay loop
calibration which will work regardless of how smart the C compiler is.

The delay loop is probably one of the oldest pieces of code in flashrom
and it shows.
Clean up code duplication and measure timing of 10/100/1000/10000 us delays.
Add copyright notices for my past and current work on this file.

If possible, please run the following command a few times and mail the
output to flashrom@flashrom.org
flashrom -V|grep delay

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Carl-Daniel Hailfinger - 2010-03-24 03:13:16
Ping?
This cleanup is part 1/2 to make flashrom work with clang and unbreak
the delay calculation.
If the new style code is OK, I'll submit part 2/2 which makes heavy use
of the new style code to get timing accuracy of +-10% even in case of
CPU speed variations. Considering that the current code relies on the
dumbness of the optimizer in the C compiler and still manages to make
all delays twice as long as intended, I hope we can get the fixed code
in before 0.9.2.

On 06.03.2010 04:28, Carl-Daniel Hailfinger wrote:
> Note: This patch is the first step towards a better delay loop
> calibration which will work regardless of how smart the C compiler is.
>
> Clean up code duplication and measure timing of 10/100/1000/10000 us delays.
> Add copyright notices for my past and current work on this file.
>
> If possible, please run the following command a few times and mail the
> output to flashrom@flashrom.org
> flashrom -V|grep delay
>   

Regards,
Carl-Daniel
Maciej Pijanka - 2010-03-27 13:35:55
On Wed, 24 Mar 2010, Carl-Daniel Hailfinger wrote:

> Ping?
> This cleanup is part 1/2 to make flashrom work with clang and unbreak
> the delay calculation.
> If the new style code is OK, I'll submit part 2/2 which makes heavy use
> of the new style code to get timing accuracy of +-10% even in case of
> CPU speed variations. Considering that the current code relies on the
> dumbness of the optimizer in the C compiler and still manages to make
> all delays twice as long as intended, I hope we can get the fixed code
> in before 0.9.2.

Imo looks fine, 
on one machine and nic3com i get
Calibrating delay loop... 95M loops per second, 10 myus = 23 us, 100 myus = 202 us, 1000 myus = 2042 us, 10000 myus = 20020 us, OK.
same machine but mainboard interface (internal)
Calibrating delay loop... 94M loops per second, 10 myus = 23 us, 100 myus = 199 us, 1000 myus = 1972 us, 10000 myus = 19784 us, OK.

still bit far from 10uS = 10myus 

anyway i think it won't break anything

Acked-by: Maciej Pijanka <maciej.pijanka@gmail.com>

> 
> On 06.03.2010 04:28, Carl-Daniel Hailfinger wrote:
> > Note: This patch is the first step towards a better delay loop
> > calibration which will work regardless of how smart the C compiler is.
> >
> > Clean up code duplication and measure timing of 10/100/1000/10000 us delays.
> > Add copyright notices for my past and current work on this file.
> >
> > If possible, please run the following command a few times and mail the
> > output to flashrom@flashrom.org
> > flashrom -V|grep delay
> >   
> 
> Regards,
> Carl-Daniel
>
Carl-Daniel Hailfinger - 2010-03-27 16:17:08
On 27.03.2010 14:35, Maciej Pijanka wrote:
> On Wed, 24 Mar 2010, Carl-Daniel Hailfinger wrote:
>   
>> This cleanup is part 1/2 to make flashrom work with clang and unbreak
>> the delay calculation.
>> If the new style code is OK, I'll submit part 2/2 which makes heavy use
>> of the new style code to get timing accuracy of +-10% even in case of
>> CPU speed variations. Considering that the current code relies on the
>> dumbness of the optimizer in the C compiler and still manages to make
>> all delays twice as long as intended, I hope we can get the fixed code
>> in before 0.9.2.
>>     
>
> Imo looks fine, 
> on one machine and nic3com i get
> Calibrating delay loop... 95M loops per second, 10 myus = 23 us, 100 myus = 202 us, 1000 myus = 2042 us, 10000 myus = 20020 us, OK.
> same machine but mainboard interface (internal)
> Calibrating delay loop... 94M loops per second, 10 myus = 23 us, 100 myus = 199 us, 1000 myus = 1972 us, 10000 myus = 19784 us, OK.
>
> still bit far from 10uS = 10myus
>   

Indeed. That's a code bug I'll deal with in the next patch.

> anyway i think it won't break anything
>
> Acked-by: Maciej Pijanka <maciej.pijanka@gmail.com>
>   

Thanks, committed in r986.

Regards,
Carl-Daniel

Patch

Index: flashrom-delayloop/udelay.c
===================================================================
--- flashrom-delayloop/udelay.c	(Revision 921)
+++ flashrom-delayloop/udelay.c	(Arbeitskopie)
@@ -2,6 +2,7 @@ 
  * This file is part of the flashrom project.
  *
  * Copyright (C) 2000 Silicon Integrated System Corporation
+ * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +20,8 @@ 
  */
 
 #include <sys/time.h>
+#include <stdlib.h>
+#include <limits.h>
 #include "flash.h"
 
 // count to a billion. Time it. If it's < 1 sec, count to 10B, etc.
@@ -30,21 +33,30 @@ 
 	for (i = 0; i < usecs * micro; i++) ;
 }
 
+unsigned long measure_delay(int usecs)
+{
+	unsigned long timeusec;
+	struct timeval start, end;
+	
+	gettimeofday(&start, 0);
+	myusec_delay(usecs);
+	gettimeofday(&end, 0);
+	timeusec = 1000000 * (end.tv_sec - start.tv_sec) +
+		   (end.tv_usec - start.tv_usec);
+
+	return timeusec;
+}
+
 void myusec_calibrate_delay(void)
 {
 	int count = 1000;
 	unsigned long timeusec;
-	struct timeval start, end;
 	int ok = 0;
 
 	printf("Calibrating delay loop... ");
 
 	while (!ok) {
-		gettimeofday(&start, 0);
-		myusec_delay(count);
-		gettimeofday(&end, 0);
-		timeusec = 1000000 * (end.tv_sec - start.tv_sec) +
-		    (end.tv_usec - start.tv_usec);
+		timeusec = measure_delay(count);
 		count *= 2;
 		if (timeusec < 1000000 / 4)
 			continue;
@@ -53,14 +65,18 @@ 
 
 	// compute one microsecond. That will be count / time
 	micro = count / timeusec;
+	msg_pdbg("%ldM loops per second, ", micro);
 
-	gettimeofday(&start, 0);
-	myusec_delay(100);
-	gettimeofday(&end, 0);
-	timeusec = 1000000 * (end.tv_sec - start.tv_sec) +
-	    (end.tv_usec - start.tv_usec);
-	printf_debug("%ldM loops per second, 100 myus = %ld us. ",
-		     (unsigned long)micro, timeusec);
+	/* We're interested in the actual precision. */
+	timeusec = measure_delay(10);
+	msg_pdbg("10 myus = %ld us, ", timeusec);
+	timeusec = measure_delay(100);
+	msg_pdbg("100 myus = %ld us, ", timeusec);
+	timeusec = measure_delay(1000);
+	msg_pdbg("1000 myus = %ld us, ", timeusec);
+	timeusec = measure_delay(10000);
+	msg_pdbg("10000 myus = %ld us, ", timeusec);
+
 	printf("OK.\n");
 }