Go Down

Topic: Help - Random function not working (Read 6794 times) previous topic - next topic

jbsnyder

Ubuntu 8.10, 32-bit, Arduino 0012, Duemilanove.

Same issues here. Weird...

I also tried 0011, and it seems to give me the same problem.

Has anyone found toolchain/arduino combination that gives reasonable behavior on linux?

halley

Can someone just trade .hex files with someone else, to see exactly what's wrong with the libc rand() on the offending platform?  There's a disassembler in the AVR toolset that someone mentioned, we should see what's broken with a diff.

timmaah

Linked is a "bad" version of the sketch on the RandomSeed ref page

http://82smugglers.com/misc/sketch_081230b.hex

http://arduino.cc/en/Reference/RandomSeed

It repeats 138,188,288

timmaah

#33
Dec 31, 2008, 04:18 am Last Edit: Dec 31, 2008, 04:20 am by timmaah Reason: 1
And here is the same code that runs correctly. Compiled on Ubunut 7.10 with arduino-0012

http://82smugglers.com/misc/sketch_081230a.hex

(I don't know enough to mess with the hex, but I'll take a look just for fun)

timmaah

#34
Dec 31, 2008, 04:32 am Last Edit: Dec 31, 2008, 04:33 am by timmaah Reason: 1
I am sure this means something to someone... but not my just yet.. .

NON RAND CODE
http://82smugglers.com/misc/sketch_b.txt

PROPER RAND CODE:
http://82smugglers.com/misc/sketch_a.txt

(oh yeah... used vAVRdisasm http://www.frozeneskimo.com/electronics/vavrdisasm-free-avr-disassembler/ )

Patzak

#35
Dec 31, 2008, 04:50 am Last Edit: Dec 31, 2008, 04:55 am by Patzak Reason: 1
@timmahh...Thank you for posting the code and the disassembler source.  The code is fairly easy to trace as the AVR only has 136 instructions but still is quite tedious.  Could you tell me the sources for both code segments, the difference is quite significant.

timmaah

Sources == Source Code?

If so... both should be the very same.. I noticed the large difference as well..

Code: [Select]

long randNumber;

void setup(){
 Serial.begin(9600);
 randomSeed(analogRead(0));
}

void loop(){
 randNumber = random(300);
 Serial.println(randNumber);

 delay(50);
}


halley

#37
Dec 31, 2008, 05:04 am Last Edit: Dec 31, 2008, 05:04 am by halley Reason: 1
timmaah, this is great, but I made a mistake.  We can get a listing file (with symbol info mixed in) from the .elf file, which is the build step just before .hex.  Can you build again on both platforms, and post your .lst file(s)?

Code: [Select]
avr-objdump -h -S sketch_081230a.elf > sketch_081230a.lst

I've done this for OSX, can you do one for the broken sketch A?

timmaah

B is the bad one...

http://82smugglers.com/misc/sketch_081230b.lst


A works...
http://82smugglers.com/misc/sketch_081230a.lst

mikalhart

Just to avoid confusion, it might be better to test a script that calls just rand(void) and random(void) -- both of which are misbehaving standard library functions -- and not random(int x), which is the Arduino function that only indirectly calls libc's rand().

Also, calling the seeding functions in the test program muddy the waters unnecessarily.

I am curious to find out why these two functions misbehave and whether there might not be other libc functions that are defective.

Mikal

westfw

Just for completeness, could you run "avr-gcc --version" ?
(is there a similar command that will print the versions of all the
libraries involved ?)

The macosx arduino 12 has gcc 4.3.0

timmaah

avr-gcc (GCC) 4.3.0   as well...


mikalhart, I'll make a more direct rand call after work today.. (no boss == short workday.. woohoo)



halley

It doesn't matter, mikalhart.

random() calls rand(); rand() calls an internal do_rand().

In A and B, all of the incidental calls like srand(), rand(), random() are identical bytecodes.  The do_rand() is significantly different.

As I mentioned earlier, the usual PRNG approach is more bit-fiddling than what I would call real math, and I expect the bit fiddling math just works out to be wrong in one library or the other.

The do_rand() in B uses more convenience routines to do the prologue and epilogue, but that probably isn't breaking the values.

The two routines are using significantly different operations to move the basic operands into place before starting the math.  This is typical when a compiler's optimizer gets employed, so maybe one libc was built with an optimizer enabled, while the other was not.

The do_rand() in A uses a routine called __udivmodsi4 twice.  In the same fashion, the do_rand() in B uses a routine called __divmodsi4.  Signed vs unsigned division is probably the culprit here.

mikalhart

#43
Dec 31, 2008, 04:37 pm Last Edit: Dec 31, 2008, 04:46 pm by mikalhart Reason: 1
Hi Halley,

Quote
It doesn't matter... random() calls rand();

I'm just trying to avoid confusing people between Arduino's random(int), which does indeed call rand(), and libc's less-known cousin random() which doesn't, but is broken in the same way as rand().  It calls do_random().  (See random.c.)

If we were going to try to trace through the routines, it would be much better if they started with identical seeds, hence the admonition to avoid calling srand or srandom.

That said, I think you are probably on to something with the do_rand() analysis.  Nice work!  Do we have the wherewithal to push this awful bug back to its source and get it fixed?

Thanks, Halley!

Mikal

halley

mikalhart, no worries, wasn't trying to be dismissive.

As for getting it fixed upstream, I guess someone has to contact the avr-gcc developers to point out the discrepancy.  Showing them the two listing files above, asking them to look at code at <do_rand> and THEN a link to this whole discussion, should be enough for them to track down the problem.

Go Up