Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Laderegler Test Tueftler Seite

(Ausgelagert aus Artikel avr-gcc)
 
(Startwert (seed) besorgen)
 
(7 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 4: Zeile 4:
  
 
=Startwert (seed) besorgen=
 
=Startwert (seed) besorgen=
Am einfachsten geht dies, indem man eine Variable in die Sektion <tt>.noinit</tt> lokatiert und den Wert liest:
+
Am einfachsten geht dies, indem man eine Variable in die [[avr-gcc/Interna#Sections|Section]] <tt>.noinit</tt> lokatiert und den Wert liest:
 
<tt>
 
<tt>
 
  unsigned long seed __attribute__ ((section (".noinit")));
 
  unsigned long seed __attribute__ ((section (".noinit")));
 
</tt>
 
</tt>
  
Etwas bessere Resultate erhält man, wenn man den ganzen Inhalt des nicht verwendeten SRAMs zur Bildung der seed heranzieht. Das Symbol <tt>__heap_start</tt> wird übrigens im standard Linker-Script definiert, <tt>RAMEND</tt> ist ein Makro aus <tt>ioxxxx.h</tt>:
+
Etwas bessere Resultate erhält man, wenn man den ganzen Inhalt des nicht verwendeten SRAMs zur Bildung der seed heranzieht. Das Symbol <tt>__heap_start</tt> wird übrigens im standard Linker-Script definiert, <tt>RAMEND</tt> ist ein Makro aus <tt>avr/ioxxxx.h</tt>:
  
 
Das Beispiel interpretiert den SRAM-Inhalt als <tt>unsigned short</tt> Werte und berechnet die seed, indem die einzelnen Werte mit exor &quot;überlagert&quot; werden.
 
Das Beispiel interpretiert den SRAM-Inhalt als <tt>unsigned short</tt> Werte und berechnet die seed, indem die einzelnen Werte mit exor &quot;überlagert&quot; werden.
  
 
<pre>
 
<pre>
#include <avr/io.h>
+
#include <avr/io.h>
 
   
 
   
unsigned short get_seed()
+
unsigned short get_seed()
{
+
{
    unsigned short seed = 0;
+
  unsigned short seed = 0;
    unsigned short *p = (unsigned short*) (RAMEND+1);
+
  unsigned short *p = (unsigned short*) (RAMEND+1);
    extern unsigned short __heap_start;
+
  extern unsigned short __heap_start;
 
      
 
      
    while (p >= &__heap_start + 1)
+
  while (p >= &__heap_start + 1)
      seed ^= * (--p);
+
      seed ^= * (--p);
 
      
 
      
    return seed;
+
  return seed;
}
+
}
 
</pre>
 
</pre>
  
Zeile 34: Zeile 34:
 
  #include <stdlib.h>
 
  #include <stdlib.h>
  
Prototypen und Defines:
+
Prototypen und Defines aus <tt>stdlib.h</tt>:
 
<pre>
 
<pre>
#define RAND_MAX 0x7FFF
+
#define RAND_MAX 0x7FFF
 +
#define RANDOM_MAX 0x7FFFFFFF
 
   
 
   
int rand (void);
+
int rand (void);
void srand (unsigned int seed);
+
void srand (unsigned int seed);
 
   
 
   
long random (void);
+
long random (void);
void srandom (unsigned long seed);
+
void srandom (unsigned long seed);
 
</pre>
 
</pre>
 +
<tt>RAND_MAX</tt> und <tt>RANDOM_MAX</tt> haben rein informativen Charakter. Ein Umdefinieren dieser Werte kann natürlich die Arbeitsweise der Bibliotheksalgorithmen nicht verändert und bleibt daher nutzlos!
  
 +
= Web-Links =
 +
[http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html http://www.nongnu.org/avr-libc/user-manual] - Dokumentation zu <tt>stdlib.h</tt>
 
=Siehe auch=
 
=Siehe auch=
[[avr-gcc]]
+
* [[avr-gcc]]
  
[[Kategorie:AVR]]
+
[[Kategorie:Microcontroller]]
 
[[Kategorie:Quellcode C]]
 
[[Kategorie:Quellcode C]]
 +
[[Kategorie:Software]]

Aktuelle Version vom 14. November 2006, 15:50 Uhr

"Echte" Zufallszahlen zu generieren ist leider nicht möglich, hierzu muss man externe Hardware wie einen Rauschgenerator verwenden. Funktionen wie rand und random basieren auf algebraischen Verfahren, die eine gute Verteilung der gelieferten Werte haben. Werden diese Funktionen mit dem selben Startwert (seed) initialisiert, liefern sie auch immer die gleiche Folge. In diesem Sinne sind die Werte nicht zufällig sondern nur scheinbar zufällig und "wüst umherhüpfend".

Um einen zufälligen Startwert zu erhalten, kann man den uninitialisierten Inhalt des SRAM verwenden, das nach dem power-up keinen definierten Zustand hat.

Startwert (seed) besorgen

Am einfachsten geht dies, indem man eine Variable in die Section .noinit lokatiert und den Wert liest:

unsigned long seed __attribute__ ((section (".noinit")));

Etwas bessere Resultate erhält man, wenn man den ganzen Inhalt des nicht verwendeten SRAMs zur Bildung der seed heranzieht. Das Symbol __heap_start wird übrigens im standard Linker-Script definiert, RAMEND ist ein Makro aus avr/ioxxxx.h:

Das Beispiel interpretiert den SRAM-Inhalt als unsigned short Werte und berechnet die seed, indem die einzelnen Werte mit exor "überlagert" werden.

#include <avr/io.h>
 
unsigned short get_seed()
{
   unsigned short seed = 0;
   unsigned short *p = (unsigned short*) (RAMEND+1);
   extern unsigned short __heap_start;
    
   while (p >= &__heap_start + 1)
      seed ^= * (--p);
    
   return seed;
}

Pseudozufall in der avr-libc

In der avr-libc finden sich Funktionen, um Pseudo-Zufallszahlen zu erhalten bzw. um Startwerte für die Algorithmen zu setzen:

#include <stdlib.h>

Prototypen und Defines aus stdlib.h:

#define RAND_MAX 0x7FFF
#define RANDOM_MAX 0x7FFFFFFF
 
int rand (void);
void srand (unsigned int seed);
 
long random (void);
void srandom (unsigned long seed);

RAND_MAX und RANDOM_MAX haben rein informativen Charakter. Ein Umdefinieren dieser Werte kann natürlich die Arbeitsweise der Bibliotheksalgorithmen nicht verändert und bleibt daher nutzlos!

Web-Links

http://www.nongnu.org/avr-libc/user-manual - Dokumentation zu stdlib.h

Siehe auch


LiFePO4 Speicher Test