Forum: FPGA, VHDL & Co. Device Tree unter Linux auslesen


von segfault (. (segfault)


Lesenswert?

Es geht um einen Altera FPGA mit NIOS II Prozessor, auf dem Linux 3.7 
läuft. Der Kernel verwendet einen Device Tree zur Geräteerkennung, was 
auch korrekt funktioniert. Nun würde ich gerne Teile des Device Trees 
auslesen, um sie für eigene Treiber zu nutzen. Z.B. würde ich gerne die 
property "reg" aus folgendem Knoten lesen:

1
memory@0 {
2
  device_type = "memory";
3
  reg = < 0x11000000 0x00080000
4
    0x11085000 0x00000400
5
    0x00000000 0x08000000>;
6
};

Im /proc-Dateisystem sieht die property folgendermassen aus:

1
root:/proc/device-tree/memory@0> hexdump -C reg 
2
00000000  17 03 00 21 26 f0 3f 20  17 00 40 81 26 f2 03 28  |...!&.? ..@.&..(|
3
00000010  17 01 c0 80 17 00 c0 89                           |........|
4
00000018

Wat is'n das fürn sinnloser Brei? Wo sind meine reg-Werte 0x11000000 
usw.? Ich habe auch versucht, die Werte direkt aus meinem Treiber 
(Kernelmodul) zu lesen:

1
dt_node = of_find_node_by_path("/memory@0");
2
3
struct property *pp;
4
u32 reg[6];
5
for_each_property_of_node(dt_node, pp) {
6
  printk("property name: %s, length: %d\n", pp->name, pp->length);
7
  if (pp->length == 24) {
8
    if (!of_property_read_u32_array(dt_node, pp->name, reg, 6))
9
  printk("reg: %x %x %x %x\n", reg[0], reg[1], reg[2], reg[3]);
10
  }
11
}

Der Code hat mich mit folgendem Output beglückt:

1
[ 1881.948000] property name: ���=, length: 7
2
[ 1881.948000] property name: &I>0�������1��, length: 24
3
[ 1881.948000] reg: 17030021 26f03f20 17004081 26f20328
4
[ 1881.948000] property name: name, length: 7

Leider wieder der gleiche Datenmüll wie in der /proc-Datei. Was mache 
ich falsch?

von rev (Gast)


Lesenswert?

Benutzt du eine initrd Ramdisk oder ein intramfs? Bei letzterem hatte 
ich schon das prblem, das /proc/device-tree überschreiben worden ist, 
wenn das RAM knapp geworden is...

von segfault (. (segfault)


Lesenswert?

Ich verwende initramfs, habe aber genug RAM -- 128 MB, davon belegt 
Linux nur 16 MB, da sollte also nichts überschrieben werden (?).

von rev (Gast)


Lesenswert?

Ich weiss nicht mehr woran es lag, allerdings war /proc/device-tree 
Mist, solange ich ein initramfs benutzt habe...

Andere Möglichkeit:
Kleines C-Programm um den device-tree als binary aus dem speicher zu 
holen und dann mit der libfdt auslesen. Klappt super.

von segfault (. (segfault)


Lesenswert?

rev schrieb:
> Kleines C-Programm um den device-tree als binary aus dem speicher zu
> holen und dann mit der libfdt auslesen. Klappt super.

Hast du Beispielcode dafür? Wo im Speicher finde ich den device tree?

von rev (Gast)


Lesenswert?

Also die libfdt ist ja ziemlich selbsterklärend. Man muss nur den Buffer 
mit dem Device-Tree-Binary übergeben, und kann dann ziemlich alles damit 
anstellen.

Wo der Device-Tree liegt hängt natürlich von deinem Board ab. Irgendwo 
im Flash, also evtl in einem der /dev/mtdX

Der Device-Tree wird ja vom Bootloader beim Start an den Kernel 
übergeben, also irgendwo im Speicehr wird er schon sein.

Die unelegante(aber sehr effektive) Methode wäre /dev/mem zu beutzen um 
den Speicher zu lesen...

von segfault (. (segfault)


Lesenswert?

Ich hab die Wurzel des Problems gefunden: Der Device-Tree-Speicher wird 
vom Kernel freigegeben, sobald er nicht mehr benötigt wird, d.h. nachdem 
der Tree vom Kernel ausgewertet wurde. Wenn ich mein Modul, das den Baum 
liest, direkt in den Kernel kompiliere, sehe ich die richtigen Werte 
statt binären Datenmüll. Hat jemand eine Idee, wie man es unterbinden 
kann, dass der Kernel den Devtree-Speicher freigibt?

von Duke Scarring (Gast)


Lesenswert?

segfault (core dumped) schrieb:
> Hat jemand eine Idee, wie man es unterbinden
> kann, dass der Kernel den Devtree-Speicher freigibt?
Vielleicht fragst Du da an geeigneter Stelle nach z.B. auf der 
Kernel-Mailing-List. [1]

Duke

[1] http://www.lkml.org

von segfault (. (segfault)


Lesenswert?

Für die Nachwelt: Das Freigeben des Device-Tree-Speichers durch den 
Kernel kann mit einer einfachen Code-Modifikation vermieden werden. Vor 
dem Aufruf von unflatten_device_tree() sind folgende Zeilen einzufügen:
1
void *fdt_copy;
2
fdt_copy = alloc_bootmem(size);
3
memcpy(fdt_copy, initial_boot_params, size);
4
initial_boot_params = fdt_copy;

Dies erstellt eine Kopie des Device-Trees in einem Speicherbereich, der 
nicht freigegeben wird. Wo genau unflatten_device_tree() aufgerufen 
wird, ist architekturabhängig.

von Peter II (Gast)


Lesenswert?

segfault (core dumped) schrieb:
> Für die Nachwelt: Das Freigeben des Device-Tree-Speichers durch den
> Kernel kann mit einer einfachen Code-Modifikation vermieden werden. Vor
> dem Aufruf von unflatten_device_tree() sind folgende Zeilen einzufügen:
> void *fdt_copy;
> fdt_copy = alloc_bootmem(size);
> memcpy(fdt_copy, initial_boot_params, size);
> initial_boot_params = fdt_copy;
> Dies erstellt eine Kopie des Device-Trees in einem Speicherbereich, der
> nicht freigegeben wird. Wo genau unflatten_device_tree() aufgerufen
> wird, ist architekturabhängig.

irgendwie sieht das merkürdig aus.

da kannst du auch gleich
1
initial_boot_params = alloc_bootmem(1);

oder
1
initial_boot_params = null;

schreiben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.