Hallo Leute,
ich möchte einen Linux Kernel selber bauen. Bevor ihr mir jetzt Google
um die Ohren haut -- jaaa, ich weiss, es gibt 1000 Seiten zu dem Thema
:-) aber, ich habe eine sehr spezifische Frage dazu.
Ich arbeite am PC schon unter Linux. Dort habe ich mir diesen Compiler
installiert:
https://launchpad.net/gcc-arm-embedded
der funktioniert auch und man kann damit Programme compilieren. Soweit
so gut. Damit möchte ich nun den Linux Kernel compilieren! Das
Zielsystem ist ein ARM7TDMI, da ich sowas gleich auf dem Tisch liegen
habe und testen kann (nachher wird es dann ein 'echtes' System mit MMU
etc.). Ich habe
make ARCH=arm versatile_defconfig
ausgeführt, und anschliessend
make ARCH=arm menuconfig
gemacht. Dort habe ich einfach so ziemlich alles deaktiviert, um
mögliche Fehlerquellen auszuschalten - es soll vorerst mal so wenig wie
möglich mit rein compiliert werden. So, das hat auch funktioniert!
Nachdem menuconfig durch war, habe ich
make ARCH=arm all
ausgeführt. Das hat ungefähr 20 Minuten gerattert, und jetzt habe ich ne
Meldung
...
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
arm-none-eabi-ld: no machine record defined
make: *** [vmlinux] Error 1
Was bedeutet dies? muss ich in menuconfig noch mehr Sachen einstellen,
oder bedeutet dies etwa, dass dieser Linker gar nicht für meine
Plattform funktioniert? ich steh grade auf dem Schlauch, aber ich bin
sicher hier gibt es ein paar Leute die sowas schon mal gemacht haben und
mir weiterhelfen können.
Gruss
Ja, aber uClinux ist jetzt im normalen Kernel dabei. Siehe Wikipedia.
Dass ich keine MMU habe weiss ich wohl, danke trotzdem.
Und RAM habe ich 32MB, sollte auch reichen ;-)
Mit diesem Compiler kannst du Linux nicht kompilieren. Du musst den
Compiler so compilieren, das er die C-Bibliothek und die Header von
deinem Cross-Linux verwendet. Bei "cross linux from scratch" ist das im
Detail beschrieben.
Hallo,
also ich bin nun schon wesentlich weiter!
Ich habe unter menuconfig die ARM7TDMI CPU aktiviert, sowie den Support
für Ethernet aktiviert. Ich kann den Kernel nun compilieren!
und zwar mit
make ARCH=arm VERSATILE_DEFCONFIG=y all
und unter arm/boot habe ich dann zwei interessante Dateien:
Image (3.3MB)
zImage (1.7MB)
in einem anderen Tutorial habe ich gelesen, dass man diese nur erhält,
wenn alles erfolgreich compiliert worden ist. Also, die Dateien habe ich
schon mal. So wie ich das jetzt verstehe, müsste man diese nun auf das
Target ins SDRAM laden (vorher dekomprimieren bei zImage) und dann kann
man das Dingens ausführen, richtig?
Mir stellt sich noch die Frage, wie ich dem Teil verklickere, dass ich
einen LPC2468 habe, der mit einem PHY ans Ethernet angeschlossen ist.
Von sich aus kann der Kernel das ja nicht einfach so wissen.... :-/
Gruss
Das ist kein Compiler Fehler.
Alfons schrieb:> arm-none-eabi-ld: no machine record defined
Das sagt fast schon alles aus ;-)
Schau mal unter
System Type -> Versatile platform type
da muss eine Option aktiviert sein.
Welche genau solltest du selber wissen (Hardwareabhängig).
ARM7TDMI beschreibt nur die CPU.
Wo jetzt die serielle Schnittstelle usw. zu finden ist, das beschreibt
der mach-record in
arch/arm/mach-*
Hallo Ulli,
ja wie gesagt, der Kernel compiliert jetzt schon mal! :-)
ich hab die zImage und die Image Datei. Das ist schonmal gut, oder? mit
denen kann man mal was machen, ja?
Ich frage mich jetzt noch, wie man das dem Kernel verklickern kann, dass
ich da noch einen PHY dran habe (initialisierung der IO Pins?) und dass
ich gerne eine Shell auf der seriellen Schnittstelle starten möchte (so
für erste Testzwecke, das sollte doch möglich sein via UART, oder?).
Alfons schrieb:> und unter arm/boot habe ich dann zwei interessante Dateien:>> Image (3.3MB)> zImage (1.7MB)>> in einem anderen Tutorial habe ich gelesen, dass man diese nur erhält,> wenn alles erfolgreich compiliert worden ist. Also, die Dateien habe ich> schon mal. So wie ich das jetzt verstehe, müsste man diese nun auf das> Target ins SDRAM laden (vorher dekomprimieren bei zImage) und dann kann> man das Dingens ausführen, richtig?
Es gibt noch ein uImage, das für den Bootloader uBoot gedacht ist.
Alfons schrieb:>> Mir stellt sich noch die Frage, wie ich dem Teil verklickere, dass ich> einen LPC2468 habe, der mit einem PHY ans Ethernet angeschlossen ist.> Von sich aus kann der Kernel das ja nicht einfach so wissen.... :-/>
PHY und MAC sind wichtig.
soweit ich weis gibt es für den LPC2468 auch einen mach Record.
Gibt es eine Herstellerbezeichnung von dem Board.
ggf. Teste mal diese Config
lpc32xx_defconfig
Ein uImage taucht bei mir nicht auf. Das kann ich aber sicher im
menuconfig irgendwo einstellen, oder?
Woher kann ich den mach-Record für den 2468 her kriegen? ich erinnere
mich, auch mal sowas gesehen zu haben, aber unter kernel.org gibts das
nicht, und ich weiss nicht mehr wo ich das teil gefunden habe.
Von dem Board gibt es leider keine Herstellerbezeichnung, da ich es
selber gebaut habe ;-) Aber es gibt z.B. das Embedded Artists LPC2468
OEM Board, oder dasjenige von Olimex, von denen ich weiss dass da
uClinux drauf läuft. Also muss es auch den mach record geben ;-)
"Teste diese config" heisst
make ARCH=arm lpc32xx_defconfig
ja?
Ich bin noch am suchen.
Ich hatte auch mal eine amch Record für den lpc24xx gefunden und wollte
diesen mal mit meinen Source vergleichen, habe aber leider die Seite
gleschlossen.
Ich habe dafür ein paar andere git-Trees gefunden.
http://git.lpclinux.com/
Ist das zufällig die Platine von Embedded Projects ??
Wenn mann sich die Datei
arch/arm/mach-lpc22xx/lpc2468_devices.c
ansehe, sehe ich
DMA, TIMER, USB, GPIO.
Der Kernel ist etwas alt
2.6.24.2
Und der lpc24xx ist mit dem lpc24xx verwandt.
Du brauchst ausserdem noch eine libc und einige Tools.
Ein uImage musst du explizit erzeugen, das ist nicht in der
Konfiguration:
1
make uImage
Ach ja:
... schrieb:> Mit diesem Compiler kannst du Linux nicht kompilieren. Du musst den> Compiler so compilieren, das er die C-Bibliothek und die Header von> deinem Cross-Linux verwendet.
Was ein Schmarrn, der Kernel verwendet keine libc und keine Header die
er nicht selber mitbringt.
Hallo Hans Ulli,
danke für den Link, genau diesen Code habe ich gemeint!
Davon kann man ja schon mal ein wenig abkupfern, auch wenns für einen
veralteten Kernel ist. Ich verwende ja den neuesten Kernel (3.6 oder
sowas in der Art).
Die libc bringt mein Compiler mit, denke ich... sonst würde der Kernel
ja auch so schon nicht compilieren, oder? Welche Tools meinst du, die
ich noch benötige?
Andreas,
dane für den Hinweis. Ich werde das heute Abend gleich testen. Im Moment
sitze ich am Windows-Rechner ;-)
Alfons schrieb:> Hallo Hans Ulli,>> danke für den Link, genau diesen Code habe ich gemeint!> Davon kann man ja schon mal ein wenig abkupfern, auch wenns für einen> veralteten Kernel ist. Ich verwende ja den neuesten Kernel (3.6 oder> sowas in der Art).>
Der Code ist aber nicht in mainline ...
Hier noch eine Mial von dem Entwickler der ein Howto geschrieben hat
http://mailman.uclinux.org/pipermail/uclinux-dev/2007-May/042858.html
Zu den gefundennen git Trees gibt es noch eine Homepage
http://www.lpclinux.com
Ich würde erstmal die Kernelversion in der Mail testen7starten. Erst
danach ein update auf eine aktuelle Version starten.
Es ändern sich viele Schnittstellen innerhalb des Kernels.
> Die libc bringt mein Compiler mit, denke ich... sonst würde der Kernel> ja auch so schon nicht compilieren, oder? Welche Tools meinst du, die> ich noch benötige?>
Nein die libc ist nicht im Kernel drin. Die wird auch nicht gebraucht um
den Kernel zu bauen. Das darf es auch nicht, weil sonst hättest du das
Henne und Ei Problem.
Mit Tools meine ich eine Shell usw.
Habe gerade nochmal in buildroot, da gibt es eine Option für ARM7TDMI.
Da wird ein komplettes RootFS gebaut. Diese kannst du dann ggf. als cpio
Archiv dem Kernel "unterschieben" (Wird dann zusammen mit dem Kernel
eine Datei) und dann per TFTP übertragen.
>> Andreas,>> dane für den Hinweis. Ich werde das heute Abend gleich testen. Im Moment> sitze ich am Windows-Rechner ;-)
Hallo Ulli,
meinst du direkt mit dem aktuellen Kernel zu starten ist keine gute
Idee? Da gibt es prinzipiell ja auch eine Option für ARM7TDMI...
Zu den Tools - ich dachte das ist irgendwie Bestandteil des Kernels.
Dann halt doch nicht :-) Die Frage ist - was brauche ich denn noch alles
dazu? Filesystem, Netzwerk & Co bringt der Kernel ja mit, aber eine
Shell wiederum nicht?
Alfons schrieb:> Hallo Ulli,>> meinst du direkt mit dem aktuellen Kernel zu starten ist keine gute> Idee? Da gibt es prinzipiell ja auch eine Option für ARM7TDMI...>
Ein aktueller Kernel ist keine gute Idee.
Das die Option für einen ARM7TDMI vorhanden ist, hat nichts damit zu
tun.
Der Kernel ist, sagen wir mal, zu 99% in C geschrieben.
Der Rest ist in Assembler und eben die Machine Init Routinen.
Letztere sind je nach CPU und Speicheraufteilung unterschiedlich.
Daher immer diese Kernelversion nutzen, die auf dem Board ist. Das da
auch die Patches für das Board drin sein sollten ist selbstverständlich.
Erst wenn dieser läuft kann man damit beginnen einen (relativ) aktuellen
Kernel zu verwenden.
Dazu solltest du auch ein Versionkontrollsystem nutzen.
git ist im Linux Kernel die Wahl
>> Zu den Tools - ich dachte das ist irgendwie Bestandteil des Kernels.> Dann halt doch nicht :-) Die Frage ist - was brauche ich denn noch alles> dazu? Filesystem, Netzwerk & Co bringt der Kernel ja mit, aber eine> Shell wiederum nicht?
schau mal, wie ich gesagt habe, nach buildroot.
Die bauen ein RootFS wie du es haben willst ...
Am bekanntesten ist die Kombination uClibc und busybox. Da kommst du als
statischen Build so auf 1-2 MByte für das RootFS.
Und wie gesagt, wenn du dieses RootFS als cpio Archiv bauen lässt kannst
du es in den Kernel-Configs angebeben und der Kernel "baut" das mit ein.
Da brauchst du dir keine gedanken zu machen wo dein RootFS im Speicher
von deinem Board ist um es wieder dem Kernel zu übergeben.
Hallo Ulli
vielen herzlichen Dank für deine Hilfe.
Ich meinte bisher immer, dass ich ARM sehr gut kenne, und auch in C und
ASM sehr fit bin, aber ich merke, die Materie ist sehr komplex. Da kann
man sich nicht einfach so einarbeiten, ich gebs auf... Das kriege ich
nicht gebacken, noch mit busybox etc., dazu bin ich was Linux anbelangt
einfach zu wenig fit. Ich kaufe das fertig ein, das ist am
einfachsten.... schade eigentlich.
Einen veralteten Kernel will ich nicht benutzen, eigentlich hätte ich
die aktuelle Version ja auch so weit gehabt, dass das Dingens
kompiliert.
Naja, danke trotzdem :-)
Alfons schrieb:> Hallo Ulli>> vielen herzlichen Dank für deine Hilfe.>> Ich meinte bisher immer, dass ich ARM sehr gut kenne, und auch in C und> ASM sehr fit bin, aber ich merke, die Materie ist sehr komplex. Da kann> man sich nicht einfach so einarbeiten, ich gebs auf... Das kriege ich> nicht gebacken, noch mit busybox etc., dazu bin ich was Linux anbelangt> einfach zu wenig fit. Ich kaufe das fertig ein, das ist am> einfachsten.... schade eigentlich.> Einen veralteten Kernel will ich nicht benutzen, eigentlich hätte ich> die aktuelle Version ja auch so weit gehabt, dass das Dingens> kompiliert.>
Ja das die Sache nicht einfach ist weiss ich selber aus eigener
Erfahrung.
Der Kernel ist einfach compilert. Ich habe ja selber vor ca. 4-5 Jahren
mit dem Kernel Kram angefangen. (Und ich mach das nur privat ...)
Das Problem sind immer die Board spezifischen Sachen. Wobei schon mal
bei dem RootFS das buildroot System dir fast alles abnimmt.
Wie gesagt wenn du Glück hast und es sind keine spezifischen Devices
drin. Welche mit einer blöden NDA "lizenziert" werden müssen (also nur
Treiber die Mainline sind), dann ist der Update auf eine aktuelle
Kernelversion relativ einfach.
So was ich gesehen habe ist die Platform LCP24XX interessant. 32MiB RAM
so um 128 MiB Flash. NoMMU ist schon was neues für mich, da ich nur mit
Sytemen mit MMU zu tun hatte.
Gibt es da irgendwie Module/Boards mit WLAN und/oder Zigbee o.a.
So nur als Interesse halber, zur Zeit habe ich mit meiner Iomega
Iconnect zu tun, das DING will nicht mit einem aktuellen Kernel booten,
wenn ich die Option Device Tree(*) aktiviere. Da häng es irgendwo in der
Bootloader/Kernel Schnittstelle ...
(*) Device Tree
ist eine "neue" Art eine Machinen Definition wo die Schnittstellen usw.
beschrieben werden.
Da hat der Gottvater Linus Torvalds drüber aufgeregt, das es für jeden
ARM SoC eigene Startcodes benötigt.
> Naja, danke trotzdem :-)
Hallo Ulli,
also, ich sehe das so:
Meine CPU ist ja vom Kernel grundsätzlich mal unterstützt (ARM7, bzw.
ARM v4). Von daher ist das ja schon mal gut, denn für ARM7 gibt es
fertige Compiler, die ganzen hässlichen Assemblersachen sind schon
erledigt, etc., soweit so gut. Was ich nun machen würde:
zuallererst einmal einen Treiber schreiben für die ser. Schnittstelle.
Ich habe mir von einem Freund extra ein Buch geborgt "Linux Device
Drivers", wo u.a. auch "Character devices" erklärt werden. Meine
Hardware, wo der Kernel drauf laufen soll, habe ich im Griff, also ich
weiss sehr genau, wie diese serielle Schnittstelle von der SW her
angesprochen werden soll etc.
Dann würde ich unter arch/arm/ einen neuen Ordner "mach-lpc2468"
anlegen, und dort meine eigenen Board-spezifischen Sachen ablegen. In
irgend einem Makefile muss man das dann noch eintragen, habe ich
gesehen, und wenn man das alles gemacht hat, dann kann man beim make
menuconfig diese HW als Target auswählen, richtig?
Wenn ich das dann alles habe, dann würde ich den Kernel einfach mal
compilieren, ein nicht komprimiertes Image erzeugen und das mit meinem
Debugger aus das Target runter laden. Den Bootloader lasse ich erst mal
aussen vor, der ist eine andere Baustelle ;-)
Beim Kernel kann man ja noch Parameter zum Start mit übergeben, und dort
würde ich dann sowas sagen wie
console=ttyS0
oder ähnlich, und wenn der Kernel wirklich läuft, sollten dann ja auf
der ser. Schnittstelle ein paar Meldungen zu sehen sein, oder? ;-)
Und wenn das mal geht, dann Schrittweise drauf aufbauen.
Die Sache ist halt die, das habe ich glaube ich verschwiegen bzw. nicht
so deutlich gesagt: Ich soll das auf der Arbeit auch machen, dort für
einen etwas grösseren ARM (ARM9), und da mich das persönlich sehr
interessiert und auch damit ich ein paar erste Erfahrungen sammeln kann,
möchte ich das halt schon mal ein wenig ausprobieren. Hier zu Hause habe
ich ein ARM7 Board, wo SDRAM mit drauf ist, von daher ginge das ja,
Speicher steht genug zur Verfügung und Schnittstellen wie seriell und
Ethernet auch ;-)
Meinst du, das wäre ein gangbarer weg? Wie gesagt, meine CPU wird ja
grundsätzlich unterstützt, ich muss "nur noch" rausfinden, was ich sonst
noch alles an HW-Spezialitäten konfigurieren muss. Und mit dem LPC22xx
Sourcecode von Google habe ich ja schon mal einen Startpunkt, wo ich ein
paar Sachen abgucken kann, dann sollte es doch machbar sein, oder?
Ganz einfach so aufgeben kann ich das Projekt dann doch nicht, es
interessiert mich selber zu sehr :-) zudem muss es früher oder später
sowieso gemacht werden, von daher.......
Schönen Gruss
Alfons schrieb:> Hallo Ulli,>> also, ich sehe das so:>> Meine CPU ist ja vom Kernel grundsätzlich mal unterstützt (ARM7, bzw.> ARM v4). Von daher ist das ja schon mal gut, denn für ARM7 gibt es> fertige Compiler, die ganzen hässlichen Assemblersachen sind schon> erledigt, etc., soweit so gut. Was ich nun machen würde:> zuallererst einmal einen Treiber schreiben für die ser. Schnittstelle.> Ich habe mir von einem Freund extra ein Buch geborgt "Linux Device> Drivers", wo u.a. auch "Character devices" erklärt werden. Meine> Hardware, wo der Kernel drauf laufen soll, habe ich im Griff, also ich> weiss sehr genau, wie diese serielle Schnittstelle von der SW her> angesprochen werden soll etc.> Dann würde ich unter arch/arm/ einen neuen Ordner "mach-lpc2468"> anlegen, und dort meine eigenen Board-spezifischen Sachen ablegen. In> irgend einem Makefile muss man das dann noch eintragen, habe ich> gesehen, und wenn man das alles gemacht hat, dann kann man beim make> menuconfig diese HW als Target auswählen, richtig?
Das Buch "Linux Device Driver" gibt es auch online kostenlos
suche mal nach *LDD3e.pdf*, das ist praktisch mein Begleiter auf dem
Notebook.
Die meisten Treiber brauchst du nicht schreiben, die sind teilweise
schon vorhanden. Bei der seriellen Schnittstelle brauchst du nur die
Addresse des 16550A/8250 kompatiblen Baustein im SoC und noch ein paar
Parameter anzugeben.
GPIO ist als "Lib" im Kernel, also auch nur Bereiche usw. angeben.
Bei der Netzwerkkarte dürfte es auch so sein.
ABER :
Seit Device Tree ist es nach meiner Meinung noch einfacher:
Wenn die Hardware im Kernel bekannt ist (keine neuen Treiber) brauchst
nur nur dieses File. Es ist eine Art von XML. Und seit v3.9-rc1 kannst
du diese compilierte Datei an deinen Kernel hängen ohne eine neunen
Bootloader zu haben.
> Wenn ich das dann alles habe, dann würde ich den Kernel einfach mal> compilieren, ein nicht komprimiertes Image erzeugen und das mit meinem> Debugger aus das Target runter laden. Den Bootloader lasse ich erst mal> aussen vor, der ist eine andere Baustelle ;-)>> Beim Kernel kann man ja noch Parameter zum Start mit übergeben, und dort> würde ich dann sowas sagen wie>> console=ttyS0>> oder ähnlich, und wenn der Kernel wirklich läuft, sollten dann ja auf> der ser. Schnittstelle ein paar Meldungen zu sehen sein, oder? ;-)>
Im Prinzipo ja.
Debugger aka gdb ist schwer, habe ich auch gar nicht genutzt. printk ist
hier mein Freund ...
Auch würde ich wie gesagt erstmal sehen ob ein "alter" Kernel läuft um
sicher zu stellen, das du keine HW Fehler hast.
Wenn der LPC24XX mit LPC32XX von der HW (nur die Bausteine selber, nicht
die Addressen) würde ich mal das arch/arm/boot/dts/lpc32xx.dtsi File
ansehen. ggf. auch eine Config Optionen einfügen damit die "speziellen"
Schnittstellen von NXP eingebunden werden.
Hier mal die aktuelle Startmeldung vom iconnect-Kernel mit Device Tree,
den Fehler habe ich gefunden. Und wie immer LESEN des HELP Textes lohnt
sich immer ;-)
hast du sehr viel gewonnen. Der Kernel will auf das RootFS zugreifen, da
ich ihm nicht gezeigt habe.
> oder ähnlich, und wenn der Kernel wirklich läuft, sollten dann ja auf> der ser. Schnittstelle ein paar Meldungen zu sehen sein, oder? ;-)>> Und wenn das mal geht, dann Schrittweise drauf aufbauen.>> Die Sache ist halt die, das habe ich glaube ich verschwiegen bzw. nicht> so deutlich gesagt: Ich soll das auf der Arbeit auch machen, dort für> einen etwas grösseren ARM (ARM9), und da mich das persönlich sehr> interessiert und auch damit ich ein paar erste Erfahrungen sammeln kann,> möchte ich das halt schon mal ein wenig ausprobieren. Hier zu Hause habe> ich ein ARM7 Board, wo SDRAM mit drauf ist, von daher ginge das ja,> Speicher steht genug zur Verfügung und Schnittstellen wie seriell und> Ethernet auch ;-)>
Da ist der Weg ähnlich, nur die MMU versaut dir ein wenig dein Gehirn.
Ich habe bei einer Platform ein wenig gebraucht um da durchzusteigen,
besonders weil der Code auch so alt war v2.6.15 und die da teilweise
seltsame Code Constructs hatten.
> Meinst du, das wäre ein gangbarer weg? Wie gesagt, meine CPU wird ja> grundsätzlich unterstützt, ich muss "nur noch" rausfinden, was ich sonst> noch alles an HW-Spezialitäten konfigurieren muss. Und mit dem LPC22xx> Sourcecode von Google habe ich ja schon mal einen Startpunkt, wo ich ein> paar Sachen abgucken kann, dann sollte es doch machbar sein, oder?>
Ja.
Nimm aber wie ich gesagt habe git, als Source-Code Verwaltung. Die ist
da viel einfacher als SVN und CVS, besonders wenn du ans Mergen von
zweigen kommst. Branches kannst du dir so viele anlegen wie du willst,
da gibt es keine Begrenzung im System.
Und wenn der Code sauber ist kannst du ihn ja Mainline schicken.
Anleitungen gibt es dazu von Greg Kroah-Hartmann (youtube) und noch
einem anderen dessen Name mir jetzt nicht einfällt.
> Ganz einfach so aufgeben kann ich das Projekt dann doch nicht, es> interessiert mich selber zu sehr :-) zudem muss es früher oder später> sowieso gemacht werden, von daher.......>> Schönen Gruss
Hallo Ulli,
ja ich habe mir auch überlegt, dass z.B. der 16550-UART-Treiber bereits
existieren sollte. Allrdings ist dann noch die Frage, wie das Handling
der Interrupts vonstatten geht?
Denn die ARM7-Controller haben ja einen sehr herstellerspezifischen
Interruptcontroller, da kannder Kernel ja unmöglich alle Spezialitäten
"wissen".
Deb Code bei mainline einzureichen, daran hatte ich auch schon gedacht.
Wenn dann erst mal alles läuft.... :-)
Alfons schrieb:> Hallo Ulli,>> ja ich habe mir auch überlegt, dass z.B. der 16550-UART-Treiber bereits> existieren sollte. Allrdings ist dann noch die Frage, wie das Handling> der Interrupts vonstatten geht?> Denn die ARM7-Controller haben ja einen sehr herstellerspezifischen> Interruptcontroller, da kannder Kernel ja unmöglich alle Spezialitäten> "wissen".>> Deb Code bei mainline einzureichen, daran hatte ich auch schon gedacht.> Wenn dann erst mal alles läuft.... :-)
Ich habe mal eben den SVN Code ausgechecket und mal grep drüber laufen
lassen.
Das gibt mir ein
find -type f -print0 | xargs -0 grep -l LPC2
aus
1
./arch/arm/boot/compressed/head.S
2
./arch/arm/Kconfig
3
./arch/arm/Kconfig-nommu
4
./arch/arm/kernel/entry-armv.S
5
./arch/arm/kernel/head-common.S
6
./arch/arm/kernel/head-nommu.S
7
./arch/arm/mach-lpc22xx/head.S
8
./arch/arm/mach-lpc22xx/irq.c
9
./arch/arm/mach-lpc22xx/Kconfig
10
./arch/arm/mach-lpc22xx/Kconfig-boards
11
./arch/arm/mach-lpc22xx/Kconfig-lpc2468
12
./arch/arm/mach-lpc22xx/lpc2468_devices.c
13
./arch/arm/mach-lpc22xx/lpc2468_ea_board.c
14
./arch/arm/mach-lpc22xx/lpc_2478stk.c
15
./arch/arm/mach-lpc22xx/lpc_e2468.c
16
./arch/arm/mach-lpc22xx/Makefile
17
./arch/arm/mach-lpc22xx/old/arch.c
18
./arch/arm/mach-lpc22xx/old/head.S
19
./arch/arm/mach-lpc22xx/old/irq.c
20
./arch/arm/mach-lpc22xx/old/Kconfig
21
./arch/arm/mach-lpc22xx/old/lpc2468_devices.c
22
./arch/arm/mach-lpc22xx/old/Makefile
23
./arch/arm/mach-lpc22xx/old/time.c
24
./arch/arm/mach-lpc22xx/time.c
25
./arch/arm/Makefile
26
./arch/arm/mm/Kconfig
27
./arch/arm/mm/Makefile
28
./arch/arm/mm/proc-arm7tdmi.S
29
./arch/arm/mm/proc-lpc22xx.S
30
./arch/arm/tools/mach-types
31
./drivers/i2c/busses/i2c-lpc22xx.c
32
./drivers/i2c/busses/Kconfig
33
./drivers/i2c/busses/Makefile
34
./drivers/mtd/devices/Kconfig
35
./drivers/mtd/devices/Makefile
36
./drivers/mtd/devices/mtd-lpc22xx-flash.c
37
./drivers/mtd/maps/Kconfig
38
./drivers/mtd/maps/lpc2468-ea-flash.c
39
./drivers/mtd/maps/Makefile
40
./drivers/net/arm/Kconfig
41
./drivers/net/arm/lpc22xx_eth.c
42
./drivers/net/arm/lpc22xx_eth.h
43
./drivers/net/arm/Makefile
44
./drivers/net/pcmcia/pcnet_cs.c
45
./drivers/rtc/Kconfig
46
./drivers/rtc/Makefile
47
./drivers/rtc/rtc-lpc22xx.c
48
./drivers/rtc/rtc-lpc22xx.h
49
./drivers/serial/8250.c
50
./drivers/video/Kconfig
51
./drivers/video/Kconfig.old
52
./drivers/video/lpc2468_registers.h
53
./drivers/video/Makefile
54
./include/asm-arm/arch-lpc22xx/Copyoflpc22xx.h
55
./include/asm-arm/arch-lpc22xx/dma.h
56
./include/asm-arm/arch-lpc22xx/entry-macro.S
57
./include/asm-arm/arch-lpc22xx/gpio.h
58
./include/asm-arm/arch-lpc22xx/hardware.h
59
./include/asm-arm/arch-lpc22xx/irq.h
60
./include/asm-arm/arch-lpc22xx/irqs.h
61
./include/asm-arm/arch-lpc22xx/keyboard.h
62
./include/asm-arm/arch-lpc22xx/log
63
./include/asm-arm/arch-lpc22xx/lpc22xx.h
64
./include/asm-arm/arch-lpc22xx/nvram.h
65
./include/asm-arm/arch-lpc22xx/serial.h
66
./include/asm-arm/arch-lpc22xx/time.h
67
./include/asm-arm/arch-lpc22xx/uncompress.h
68
./include/asm-arm/arch-lpc22xx/vmalloc.h_old
69
./include/linux/i2c-id.h
aus. Ich habe nur die wichtigen Dateien genommen.
Und das sind nur die "offensichtlichen" Änderngen um Code mit Kconfig.
Die anderen bekommst du nur mit diif ggf. diffstat heraus.
In dem Fall habe ich immer mit zwei Verzeichnissen gerarbeitet.
"Original Code" vom BSP
und der "Master" git mit der entsprechenden Version inkl. Subversion)
hier also v2.6.24.2
Sowie "dein" Controller in
arch/arm/mach-lpc22xx/irq.c
wo ja der "mach" spezifische Teil sein soll. arch/arm/mach-lpc22xx
Die Jungs haber schon vorher weit alles abstrahiert was geht ...
Wenn du wie gesagt vor hast mainline zu gehen, hier meine zwei
Empfehlungen die du dir ansehen solltes :
Wie schreibt man eine Patch und sendet ihn
http://www.youtube.com/watch?v=LLBrBBImJt4
Arbeiten mit Git in der Gruppe (nenn ich mal so)
http://www.youtube.com/watch?v=j45cs5_nY2k
Beim letzteren wird gezeigt was der Unterschied zwischen einem Rebase
und einem Merge ist. Und wo die Fehlerquellen sind WICHTIG, wenn in
der Gruppe gearbeitet wird.
N'Abend Ulli,
ich habe soeben dieses Dokument gefunden:
http://www.linux-arm.org/pub/LinuxKernel/WebHome/aleph-porting.pdf
dort wird verhältnismässig vieles erklärt. Fragt sich, wie akkurat das
mit dem aktuellen Kernel noch ist.... wie gesagt möchte ich einen
einigermassen aktuellen Kernel benutzen, nicht mehr 2.6, der ist ja
wirklich alt. Zumal gemäss Wikipedia und vielen anderen Quellen die
MMU-lose Variante bereits im aktuellen Kernel enthalten ist.
Okay, ich werde mich mal an das obengenannte Dokument halten. Ich habe
vorhin schon mal einen einfachen Bootloader für mein Board gebastelt,
der die ganze HW initialisiert, den SDRAM-Controller startet usw., sowie
einen seriellen Port initialisiert und ein paar Meldungen ausgibt. Mein
Ziel ist es dann, die Feiertage über Ostern sinnvoll zu nutzen ;-))) und
einen wirklich minimalistischen 3.6er-Kernel (oder ähnlich) zu bauen,
der nur mal die serielle Schnitte enthält, und mal ein paar Meldungen
ausspuckt.
Wenn ich so schaue in den obengenannten Dokumenten, dann enthält der
Kernel bereits ein paar allernotwendigste Routinen zur Textausgabe, auch
den Interruptcontroller kann man mit irq.c recht gut abstrahieren
(struct irq_chip usw.).
Weisst du grade, welchen Treiber ich bei menuconfig einbinden muss,
damit er den 16550er UART findet? bzw. dessen Basisadresse müsste man ja
auch noch irgendwo einstellen können, das finde ich grade nicht.
Aber herzlichen Dank schonmal für deine Hilfe.
Wenns dir recht ist melde ich mich später nochmal per PN, über Mail ist
es sicherlich bequemer, einige Fragen zu klären ;-)
Gruss
Ich habe mal (echt) nur kurz das PDF überflogen ...
DAS DING IST URALT und stinkt schon.
Ich gehe mal davon aus da wenigstens 30% der beschriebenen Sachen nicht
mehr stimmen und andere Teile gelöscht worden sind.
Besonders was es sich mit dem
include/asm-arm/arch-lpc22xx/ (alter Code) auf sich halt stimmt nicht
mehr.
Und den anderem Kram kann ich auch nicht genau sagen ...
Warum ... legt dir mal ein git Repo irgendwo an github und Co lassen
grüssen.
Wie sieht es mit dem Speicher aus ??
Was ist an Addresse 0xa0008000 ??
Die CPU ist eine "2468" CPU nur für den Baustein ??
Lerne git, ohne fange mal mit an ...
Im Branch
lpc24xx/v3.8/mach-lpc24xx
habe ich schon mal angefangen zu spielen
Dieser ist wie der Name schon sagt v3.8 basiert.
Das meiste habe C&P vom Google Repo genommen und nach und nach
angepasst.
Zur Zeit hängt der Compiler jetzt bei irq.c
So wie es an der Fehlermeldung sehe, liegt das an dem fehlenden sysdev.h
das ich im laufe der Zeit herausgenommen habe. Da muss eine Anpassung
nach einem platform device oder so gemacht werden. Beispiel dürfte in
mach-lpc32XX oder so zu finden sein.
Checkout des Branches mit z.B.
Viel Spass
Ach ja.
Die Mail Addresse stimmt, aber ich habe z.Zt. wenig Lust da zu
Antworten. Habe andere Sachenzu tun und wollte erst in ca. 4-6 Monaten
wieder voll einsteigen ...
Ulli
chroot bed && sleep
Hey Ulli,
herzlichen Dank für deine Hilfe!
ich habe inzwischen angefangen, das selbe zu tun :-)
Ich habe von Google Repository ein bisschen abgeschrieben. bei irq.c
habe ich den teil mit dem sysdev auskommentiert, nun compiliert der
Kernel schon mal ;-) allerdings kommt ganz am Schluss wieder die
hässliche Meldung:
"no machine record defined"
aber ich sehe inzwischen den Wald vor lauter Bäumen nicht mehr -_- ich
muss mich auch erst mal hinlegen und das ein wenig verdauen ;-)
Wenn du mal kurz Zeit hast kannst du dir ja meine Kconfig-Dateien
anschauen, ich hab da inzwischen ziemlich rumgedoktert, um den Fehler zu
beheben, leider bislang erfolglos.
Da bei arm.linux.co.uk schon mal jemand den mach-Typ LPC24xx registriert
hat, dieser jedoch nicht mainlined ist, habe ich einfach mal diesen
mach-Record übernommen:
lpc24xx MACH_LPC24XX LPC24XX 2967
Ob es vielleicht daran liegt?
Gruss
Hallo Ulli,
so habe den Fehler gefunden. Man muss in einer C-Datei noch ein Makro
einfügen:
DT_MACHINE_START(LPC24XX_DT, "LPC24XX SoC (Flattened Device Tree)")
.atag_offset = 0x100,
.map_io = NULL,
.init_irq = lpc22xx_init_irq,
.timer = NULL, /*??? &lpc32xx_timer*/
.init_machine = lpc2468_machine_init,
.dt_compat = lpc24xx_dt_compat,
.restart = NULL, /*?? lpc23xx_restart*/
MACHINE_END
ich habe das einfach mal vom LPC32xx kopiert und die Namen einfach
angepasst, in der Hoffnung, dass das Teil so schon mal halbwegs
funktioniert.
Nun: endlich kann ich den Kernel für meine Architektur compilieren! Ich
habe mal die Option "excute in Place" angewählt und spiele das xipImage
als binäre Datei in das externe Flash meines Controllers. Dann habe ich
einen simplen Bootloader gebastelt, der einfach den Uart sowie
Memorycontroller initialisiert und an die Basisadresse des ext. Flash
springt, wo dann das xipImage liegt. Wenn ich da mit dem Debugger drüber
steppe, dann passiert auch tatsächlich etwas, was einigermassen sinnvoll
erscheint! irgendwelche Daten werden da herum kopiert, vom Flash ins
SDRAM, gewisse SDRAM Bereiche werden mit 0x00 gefüllt und der
Stackpointer wird initialisiert und zeigt dann irgendwo ins SDRAM.
Irgendwo wird noch (so vermute ich) die Machine ID geladen, welche ich
mit "Hardwire the machine ID" auf 0x00007700 gesetzt habe; er errechnet
aber dann beim Target einen Wert von 0x41007700, vergleicht dies, stellt
fest, dass es nicht übereinstimmt, und geht in einen Endlosloop. Daher
habe ich dann einfach mal die Machine ID mit dem Debugger gefaket,
sodass der Vergleich erfolgreich ist; danach passieren weitere Dinge,
auf dem Terminal (ttyS0) erfolgt aber kein Zugriff, ausserdem kommt er
irgendwann wieder in einen Endlosloop (wo er vielleicht auf einen
Timerinterrupt wartet?).
Wie könnte man jetzt weiter vorgehen?
mein Setup ist wie folgt:
SDRAM 0xa0000000
Size 0x04000000
Ext. Flash 0x80000000
Size 0x00400000
"Remap Vectors to RAM" habe ich aktiviert und die Basisadresse des int.
RAM 0x40000000 angegeben, damit er da nicht irgendwie ins Flash zu
schreiben versucht.
So, naja jedenfalls passiert schon mal IRGENDWAS, das ist schon toll ;-)
wenn ich bis am WE noch eine Ausgabe auf der seriellen hin kriege, bin
ich glücklich.
Erst mal aber
sudo mv /dev/bed
Gruss
Hallo Ulli,
ich mal wieder. Hab noch ein wenig debugged.
Ich habe mal von Hand im Kconfig eingefügt
config EARLY_PRINTK
bool
default y
damit ich mit early_printk() Sachen ausgeben kann.
Nun, ich stelle fest anhand des Terminals:
der Kernel bootet jetzt, und zwar bis hier:
setup.c, funktion setup_arch(), beim Aufruf von paging_init() gibts ein
Problem. Bei pagint_init() geht er in die nommu.c, wo er versucht die
Vektoren umzukopieren. Das funktioniert, anschliessend geht er zum
bootmem_int(), und hier schlägts dann fehl:
init.c, bootmem_init(), aufruf von arm_bootmem_init().
Dann geht er irgendwann in die mark_bootmem(). Codeauszug, mit meinen
printk()'s:
BUG on 262144 (pos=a000c55c, bdata=0x (null), min_pfn=a0000, low_pfn=a1000.)
12
bootmem stuff done.
Interessant:
wenn ich die printk() Zeile entferne, dann resetiert sich der Prozessor
dauernd wieder.
Hast du eine Idee, wo ich suchen müsste?
Interessant ist, dass er da mit bootmem etwas versucht zu machen, wo
meine Interruptvektoren liegen.
Also ich habe bei mir folgendes:
den Kernel als XIP konfiguriert und auf Adresse 0x80000000 gelinkt, weil
da ein FLASH liegt. SDRAM liegt bei 0xA0000000. So, und die
Vektortabelle des ARM7 ist eigentlich im Flash, aber NXP bietet die
möglichkeit des "memory remappings", d.h. die Vektortabelle wird auf
Adresse 0x40000000 verschoben, dort liegt ein RAM. Und genau dies habe
ich im menuconfig auch aktiviert (Remap Vectors to RAM) und die Adresse
0x40000000 angegeben.
Wo könnte ich weitersuchen?
Bis bald hoffentlich,
Gruss
Übergibst du dem Kernel dem Speicherbereich für das RAM per ATAG ?
Wenn du den DeviceTree benutzt musst du ihn auch dem Kernel per
Parameter übergeben.
Howto für ATAG
http://www.simtec.co.uk/products/SWLINUX/files/booting_article.htmlhttp://armputer.pbworks.com/f/porting_to_arm.pdf
Für Device Tree
http://elinux.org/Device_Trees
So wie es aussieht ist die einzige brauchbare Doku für das Register,
wo dieser DT-Blob dem Kernel übergeben wird, entweder der Kernel source
oder der u-Boot source.
Für akuelle Kernel ab 3.8-rc1 gibt es wir sagt einem "Trick" um diesem
Block an dem Kernel anzuhängen. Es ist aber nur der Weg für zImage
beschrieben. (Helptext ist ist Kconfig).
Alfons schrieb:> Also ich habe bei mir folgendes:> den Kernel als XIP konfiguriert und auf Adresse 0x80000000 gelinkt, weil> da ein FLASH liegt. SDRAM liegt bei 0xA0000000. So, und die> Vektortabelle des ARM7 ist eigentlich im Flash, aber NXP bietet die> möglichkeit des "memory remappings", d.h. die Vektortabelle wird auf> Adresse 0x40000000 verschoben, dort liegt ein RAM. Und genau dies habe> ich im menuconfig auch aktiviert (Remap Vectors to RAM) und die Adresse> 0x40000000 angegeben.>> Wo könnte ich weitersuchen?>> Bis bald hoffentlich,>> Gruss
Was für eine Sch**ss* ...
Das Kopieren der Vectortabelle erfolgt in arch/arm/kernel/trace.c
und ist im mainline nur ein Stub.
Wie die das jetzt im LPC32XX (wenn dort auch so was vorhanden ist)
umgangen haben weiss ich nocht nicht.
EDIT:
Der LPC32XX hat eine MMU ...
Hallo Ulli,
hmm kann dir grade nicht so ganz folgen was du meinst.
Was, Sche... ?? mein Code, oder was?
Ich habe den "Fehler" mittlerweile gefunden. Der Code versucht, auf den
RAM zuzugreifen, den ich aber in der Memory map nicht drin hatte. Ich
rufe jetzt testweise mal vorher noch arm_add_memory() auf, in der
setup.c Funktion setup_arch(). Dort mache ich das Memory bekannt, und
dann geht auch die inisialisierung des Bootmem. Ich tippe mal darauf,
dass man normalerweise mit den ATAGs das Memory vorher bekannt gibt und
dann ist dieser Kram mit add_memory() nicht nötig.....
Nun denn, der Code läuft nun mittlerweile bis zur page_alloc.c, Funktion
memmap_init_zone(). Dort gibt es folgenden Code:
Dort liegt natürlich kein RAM und der Prozessor wird erwartungsgemäss
angehalten.
Ich frage mich, woher die Werte kommen.... Ob es wirklich nur daran
liegt, dass ich noch keine ATAGs habe? Wie gesagt - ich boote den Kernel
ohne ATAGs, weil ich nicht rausgefunden habe, wie dies genau
funktionieren soll. Daher habe ich das einfach mal weggelassen, und ich
boote ihn einfach, indem ich an die richtige Adresse springe und vorher
ins Register r2 noch die Machine ID lade (0x41007700 für ARM7TDMI).
Gruss
Die ATAG ist einfach eine LISTE.
Parameter für ATAG Boot:
r0 = 0
r1 = machine number
r2 = &(ATAG list)
Normalerweise wird die ATAG Liste nach validen Tags geprüft (soweit
ich mich noch erinnern kann)
Es macht aber nicht wenn du in r2 eien Addresse angibst die den Inhalt
0x00000000L (Ende der Liste) hat.
Was ich mit Sch**ss* meinete ist einfach :
Der Code zum Kopieren der INT-Vector Tabelle ist in den Original Source
in arch/arm/kernel/trace.c im Mainline-Kernel ist dieser code nicht.
Auch steht dort keine Info welches Register gesetzt werden muss um
diesem Bereich der CPU bekannt zu machen, diese denkt ja noch immer die
Tabelle ist im ROM
Es kann auch sein das noch mehr Kram Außerhalb des mach-lpc22xx
Verzeichnisses vorhanden ist.
Hi Ulli,
genau, die early_tra_init() kopiert mittels memcpy() die Vektoren.
Ich habe jetzt meinen einfachen "quick & dirty bootloader" angepasst,
dass er mal ein paar ATAGs schreibt. Ich setzt ATAG_MEM, ATAG_CORE und
ATAG_NONE. so gebe ich die memory map bekannt. Und es funktioniert
tatsächlich! nun konnte ich meinen debug code raus löschen und der
kernel kommt nun etwas weiter. Dank deiner Hilfe!! :D
Jetzt habe ich wirklich nur noch das Problem mit der page_alloc.c,
Funktion memmap_init_zone(). Dort gibts einen Crash, weil er auf eine
falsche Adresse zugreifen will. Die interessanterweise ausserhalb meiner
Memory Map liegt....
Folgendes kommt in meinem Terminal jetzt:
1
memmap_init(0x64000, 0x0, 0x0, 0x40000);
2
memmap init zone entered:size = 0x64000,nid=0x0,zone=0x0,start_pfn=0x40000
Hallo Ulli,
danke das schaue ich mir heute Abend an.
In der Zwischenzeit habe ich mit initramfs befasst und mir mal dies zu
gemüte geführt:
http://www.aclevername.com/articles/linux-xilinx-tutorial/minimalist-initramfs.html
Damit kann ich eine cpio- Datei erzeugen und beim menuconfig des Kernels
angeben. Ich würde jetzt busybox runterladen und dann compilieren und da
einfach in den ordner rein kopieren, ist das ne möglichkeit?
schönen Gruss, bis bald, melde mich heut Abend nochmal!
Ja das müßte gehen.
Hier noch andere Quellen.
http://en.gentoo-wiki.com/wiki/Initramfshttp://jootamam.net/howto-initramfs-image.htm
Letztere hat noch ein minimales init.
Wichtig ist auch hier die FAQ von busybox
http://www.busybox.net/FAQ.html
Unter dem Punkt "Job Control" gibt es da was wichtiges :
Wenn dein Terminal auf /dev/console liegt ist die Job Control
ausgeschaltet. Also Terminal auf /dev/ttyS0 legen. Logischerweise gilt
dies für dein RootFS auf deinem Ziel System.
Die busybox braucht logischweiser auch noch einen libc. Hier ist die
uClibc die Wahl, da du hier einstellen kannst ob du eine MMU hast.
Insgesammt dürfte eine statische busybox 1-2 MiB groß sein.
UND JETZT KOMMT DER HAKEN
z.Zt. ist der Support für DeviceTree und InitramFS mehr als schlecht,
besser gesagt NULL. Auf meiner iconncect bekomme ich keinen Kernel mit
InitramFS und DeviceTree ans laufen ...
Hallo Ulli,
so ich habe den Fehler gefunden, der das Problem
> memmap_init(0x64000, 0x0, 0x0, 0x40000);
verursacht. In der arm_bootmem_free() (init.c) wird folgendes gemacht:
zone_size[0] = max_low - min;
Und wenn ich mir da ein paar Variablen ausgeben lasse erhalte ich
folgendes:
zone_size[0]=0x64000; max_low = 0xa4000, min = 0x40000
Was natürlich korrekt gerechnet ist, aber trotzdem falsch. Denn der
Speicherbereich ist ja nicht zusammenhängend! Ich hab gesehen, dass es
sowas gibt wie CONFIG_MEM_DISCONTIG oder ähnlich, ich denke es könnte
sich damit beheben lassen?
Gruss
Alfons schrieb:> Was natürlich korrekt gerechnet ist, aber trotzdem falsch. Denn der> Speicherbereich ist ja nicht zusammenhängend! Ich hab gesehen, dass es> sowas gibt wie CONFIG_MEM_DISCONTIG oder ähnlich, ich denke es könnte> sich damit beheben lassen?>> Gruss
Welchen Speicher meinst du jetzt ?
Ich ohne USB und Netzwerk starten.
Nicht das da ein Treiber verkehrt ist. Und die beiden Treiber benutzen
den On-Chip-RAM
Hallo Ulli,
so, gute Nachricht: ENDLICH habe ich es geschafft, dass was tolles
passiert. Mir läuft die start_kernel() erfolgreich durch, setup_arch(),
timer_init() und so weiter werden alle aufgerufen, und die
start_kernel() läuft erfolgreich durch! YES! Was allerdings jetzt noch
nicht funktioniert ist
a) printk(),
b) Timer und IRQ, um die habe ich mich noch nicht gekümmert.
Ich darf einfach bei der ATAG-Liste keinen nicht-zusammenhängenden
Speicher engeben, dann funktioniert es! ist ja aber auch nicht weiter
schlimm, denn der interne RAM ist sowieso nur 64k gross, das stört nicht
wenn der nicht benutzt wird.
Ich habe gesehen, dass nachdem start_kernel durchgelaufen ist, das I und
das F bit im CPSR noch gesetzt sind? Da muss ich wohl einen
vollständigen Interruptcontroller noch programmieren und dem Kernel beim
Start bekannt geben, damit die Timerinterrupts funktionieren? Denn bei
der timer_init() habe ich mal einen Timer initialisiert, sodass er jede
Sekunde einen Interupt generiert, der IRQ tritt aber nicht ein weil ja
die Interrupts im CPSR noch deaktiviert sind......
Gruss
Alfons schrieb:> Hallo Ulli,>> so, gute Nachricht: ENDLICH habe ich es geschafft, dass was tolles> passiert. Mir läuft die start_kernel() erfolgreich durch, setup_arch(),> timer_init() und so weiter werden alle aufgerufen, und die> start_kernel() läuft erfolgreich durch! YES! Was allerdings jetzt noch> nicht funktioniert ist>> a) printk(),> b) Timer und IRQ, um die habe ich mich noch nicht gekümmert.>> Ich darf einfach bei der ATAG-Liste keinen nicht-zusammenhängenden> Speicher engeben, dann funktioniert es! ist ja aber auch nicht weiter> schlimm, denn der interne RAM ist sowieso nur 64k gross, das stört nicht> wenn der nicht benutzt wird.>
Die 64k "interes SRAM" wird vom USB und Ethernet benutzt. Dieser wird
auch im File
arch/arm/mach-lpc22xx/lpc2468_devices.c
"reserviert". Soweit ich es im Ethernet Treiber gelesen habe sind dort
die Deskriptoren für rx/tx Buffer abgelegt.
Moin Ulli,
so ich hab mal wieder ein paar Neuigkeiten!
ich habe gestern Abend noch ein wenig mit dem Device Tree rum geübt. Nun
habe ich meinen Bootloader so modifiziert, dass er anstatt der
ATAG-Liste den Device Tree ins Memory lädt und die Basisadresse ins
Register r2 lädt, bevor zum Kernel gesprungen wird.
Tja, auf der seriellen Schnittstelle sehe ich am PC Terminal dann:
"Loading device Tree" :-) Das Ding wird nun also erfolgreich eingelesen,
auch die Initialisierung eines Timers (Timer 0 des LPC2468) klappt und
der Tick-Interrupt wird aufgerufen. "jiffies" zählt hoch usw., also
eigentlich schonmal ganz gut oder?
Nur leider stürzt der Kernel nach einer gewissen Anzahl ticks aus mir
unerklärlichen Gründen ab; ich merke das daran, dass die ganzen
Boot-Messages nochmal erscheinen. Das muss ich noch Debuggen. Noch eine
Frage zum Interruptcontroller:
Der LPC2468 hat einen VIC. Ist das wirklich der selbe VIC, wie unter
arch/arm/common/vic.c ? Ich habe den mal in den Device Tree genommen,
und die richtige Basisadresse eingegeben und damit oben beschriebenes
Verhalten erzielt. Muss ich in meinem Board-spezifischen Code noch
weitere Initialisierungen für den VIC vornehmen, oder macht das der
Kernel selbst, wenn er weiss, dass das ein VIC ist?
Weiter: ich habe im Device Tree noch den UART0 angegeben mit seiner
Basisadresse; unter "compatible" habe ich vermerkt: "ns16550a". Im make
manuconfig habe ich dann unter "Device Drivers", "Character Devices"
angegeben, dass die 8250 Treiber eingebunden werden sollen. Das klappt
auch, aber die initialisierung des UARTs wird nicht aufgerufen? Im
Prinzip sollte doch dann die Konsole auf dem Terminal erscheinen, oder?
Es kommen aber immer nur die Meldungen raus, die ich mit meinem
early_printk() erzeuge. Vielleicht hast du noch einen Tipp für mich.
Gruss
Alfons schrieb:> Moin Ulli,>> so ich hab mal wieder ein paar Neuigkeiten!> ich habe gestern Abend noch ein wenig mit dem Device Tree rum geübt. Nun> habe ich meinen Bootloader so modifiziert, dass er anstatt der> ATAG-Liste den Device Tree ins Memory lädt und die Basisadresse ins> Register r2 lädt, bevor zum Kernel gesprungen wird.>> Tja, auf der seriellen Schnittstelle sehe ich am PC Terminal dann:> "Loading device Tree" :-) Das Ding wird nun also erfolgreich eingelesen,> auch die Initialisierung eines Timers (Timer 0 des LPC2468) klappt und> der Tick-Interrupt wird aufgerufen. "jiffies" zählt hoch usw., also> eigentlich schonmal ganz gut oder?>
Schon mal gut,dann läuft der Timer IRQ
> Nur leider stürzt der Kernel nach einer gewissen Anzahl ticks aus mir> unerklärlichen Gründen ab; ich merke das daran, dass die ganzen> Boot-Messages nochmal erscheinen. Das muss ich noch Debuggen. Noch eine> Frage zum Interruptcontroller:> Der LPC2468 hat einen VIC. Ist das wirklich der selbe VIC, wie unter> arch/arm/common/vic.c ? Ich habe den mal in den Device Tree genommen,> und die richtige Basisadresse eingegeben und damit oben beschriebenes> Verhalten erzielt. Muss ich in meinem Board-spezifischen Code noch> weitere Initialisierungen für den VIC vornehmen, oder macht das der> Kernel selbst, wenn er weiss, dass das ein VIC ist?>
Wenn du im Datenblatt vom LPC24XX nachschaust (Datei UM10237.pdf) Seite
113/114 wirst du sehen, das der Controller im IRQ oder FIQ "geschaltet"
werden kann. FIQ benutzt die Vector Interrupt Tabelle, daher der VIC. In
den original Source von der google Seite wird der Controller im IRQ
Modus betrieben. Siehe Zeile 114
1
/* set all to IRQ mode, not FIQ */
2
VICIntSelect=0x00000000;
Ich gahe mal davon aus, das das locking innerhalb des Kernels nur von
einem "Laufenden" Interrupt ausgeht (so war dies auf dem PC). Es mach
auch die Sache etwas einfacher.
> Weiter: ich habe im Device Tree noch den UART0 angegeben mit seiner> Basisadresse; unter "compatible" habe ich vermerkt: "ns16550a". Im make> manuconfig habe ich dann unter "Device Drivers", "Character Devices"> angegeben, dass die 8250 Treiber eingebunden werden sollen. Das klappt> auch, aber die initialisierung des UARTs wird nicht aufgerufen? Im> Prinzip sollte doch dann die Konsole auf dem Terminal erscheinen, oder?> Es kommen aber immer nur die Meldungen raus, die ich mit meinem> early_printk() erzeuge. Vielleicht hast du noch einen Tipp für mich.>
So wie es aussieht ist es ein 16550 kompatibler Chip also mit 16Byte
send/recieve FIFO.
Nur hier gibt es noch einen Unterschieb. Original Code
Hallo Ulli,
bezüglich des Timer IRQ - den habe ich auch als IRQ und nicht als FIQ
geschaltet. Man kann mit dem VIC des LPC24xx sowohl IRQs als auch FIQs
verwalten. Somit habe ich
VICIntSelect = 0;
in meinem Code übernommen. Auch die Anpassung für den UART habe ich so
übernommen. Die Frage ist: versucht der Kernel überhaupt, meinen Treiber
zu laden? Ich habe mal bei der init-Funktion folgendes eingebaut:
ealry_printk("uart initialised");
Dann sollte auf dem Terminal eine Meldung kommen, wenn der UART Treiber
geladen wird. Das passiert aber nicht. Muss ich im Menuconfig ggf. noch
eine Option einschalten, um das Laden des Treibers zu bewirken? Ich habe
Charachter Devices --> Console on Serial Port
aktiviert, sowie
8250 Driver
habe ich auch aktiviert. Bringt aber bis jetzt noch nichts :-) Ob wohl
mein Device Tree richtig gelesen wird? Keine Ahnung, kann ich das
irgendwie prüfen?
Gruss
Alfons schrieb:> in meinem Code übernommen. Auch die Anpassung für den UART habe ich so> übernommen. Die Frage ist: versucht der Kernel überhaupt, meinen Treiber> zu laden? Ich habe mal bei der init-Funktion folgendes eingebaut:>> ealry_printk("uart initialised");>> Dann sollte auf dem Terminal eine Meldung kommen, wenn der UART Treiber> geladen wird. Das passiert aber nicht. Muss ich im Menuconfig ggf. noch> eine Option einschalten, um das Laden des Treibers zu bewirken? Ich habe>
Hast du überhaupt in deinem
boardinit ()
den Device Tree "geparsed" ??
siehe
Documentation/devicetree/usage-model.txt
Ein gutes Beispiel finde ich kann man in der Datei
arch/arm/mach-kirkwood/board-dt.c
in der Funktion
kirkwood_dt_init ()
sehen
Ich habe jetzt nicht im aktuellen 3.8 Kernel nachgesehen, aber da
dürften die Board init's für die Iomega Iconnect und Raidsonic IB62x0
NAS fehlen. Diese Platformen habe ich ...
Hallo Ulli,
nee, die of_platform_populate() hatte ich bis jetzt nicht drin :O
aber irgendwie geht jetzt wieder gar nichts mehr, ich weiss nicht obs
gestern zufall war dass der timer interrupt funktioniert hat oder was
los war - jetzt stürzt der rechner wieder ab, auch die machine_init()
wird nicht aufgerufen.
Was mein Bootloader im Prinzip macht, ist, die DTB-Datei ins Memory zu
laden. Wenn ich das Teil an eine andere Adresse als die Basisadresse des
SDRAM lade oder gar mit ins Flash nehme, dann funktioniert gar nichts,
so erkennt der Kernel wenigstens die magic number.....
ich weiss grade nicht wo weiter suchen. Ich meld mich dann nochmal....
Hallo Ulli,
ich habe den Verdacht dass mit meinem Device Tree File was nicht in
Ordnung ist. Ich habe zwar versucht, so gut wie es mir aufgrund meines
Verständnisses möglich war, mich an die Spezifikation in
Documentation/devicetree/botting-without-of.txt zu halten. Das kan dabei
heraus:
1
/include/ "skeleton.dtsi"
2
3
/ {
4
compatible = "nxp,lpc2468";
5
model = "LPC2468 testboard";
6
interrupt-parent = <&vic>;
7
8
cpus {
9
cpu@0 {
10
compatible = "arm,arm7tdmi";
11
};
12
};
13
14
memory {
15
device_type = "memory";
16
reg = <0xa0000000 0x4000000>;
17
};
18
19
ahb {
20
#address-cells = <1>;
21
#size-cells = <1>;
22
compatible = "simple-bus";
23
ranges;
24
25
mac: ethernet@FFE00000 {
26
compatible = "nxp,lpc-eth";
27
reg = <0xFFE00000 0x1000>;
28
interrupts = <0x1d 0>;
29
};
30
31
vic: interrupt-controller@FFFFF000 {
32
compatible = "arm,vic";
33
interrupt-controller;
34
reg = <0xFFFFF000 0x1000>;
35
#interrupt-cells = <2>;
36
};
37
38
apb {
39
#address-cells = <1>;
40
#size-cells = <1>;
41
compatible = "simple-bus";
42
ranges;
43
44
uart0: serial@E000C000 {
45
compatible = "ns16550a";
46
reg = <xE000C000 0x100>;
47
interrupts = <10 0>;
48
clock-frequency = <72000000>;
49
status = "okay";
50
};
51
};
52
};
53
};
kann das stimmen? Beim Interruptcontroller bin ich mir halt nicht ganz
so sucher. Eventuell muss ich dazu selber was erfinden... :-O
Alfons schrieb:> Hallo Ulli,>> ich habe den Verdacht dass mit meinem Device Tree File was nicht in> Ordnung ist. Ich habe zwar versucht, so gut wie es mir aufgrund meines> Verständnisses möglich war, mich an die Spezifikation in> Documentation/devicetree/botting-without-of.txt zu halten. Das kan dabei> heraus:>
Ich kenne Device Tree auch nicht, aber man hat ja Sourcen ...
Also man nehme eine vergleichbare ARCH mit DT -> LCP33XX
arch/arm/boot/dts/lpc32xx.dtsi (ein inlucde FILE, kein BOARD File)
>
1
> /include/ "skeleton.dtsi"
2
>
3
> / {
4
> compatible = "nxp,lpc2468";
5
> model = "LPC2468 testboard";
6
> interrupt-parent = <&vic>;
7
>
8
> cpus {
9
> cpu@0 {
10
> compatible = "arm,arm7tdmi";
11
> };
12
> };
13
>
14
> memory {
15
> device_type = "memory";
16
> reg = <0xa0000000 0x4000000>;
17
> };
18
>
Könnte passen, ich muß mal woanders lesen was memory:reg bedeutet.
>
Sieht aus wie Addressen für DRAM
> mac: ethernet@FFE00000 {> compatible = "nxp,lpc-eth";> reg = <0xFFE00000 0x1000>;> interrupts = <0x1d 0>;> };
Passt, ggf. Addresse und IRQ prüfen.
>> vic: interrupt-controller@FFFFF000 {> compatible = "arm,vic";> interrupt-controller;> reg = <0xFFFFF000 0x1000>;> #interrupt-cells = <2>;> };
Dort steht was von MIC ?? Controller, kein VIC
>> apb {> #address-cells = <1>;> #size-cells = <1>;> compatible = "simple-bus";> ranges;
Auch hier fehlt ggf der Adderess range
>> uart0: serial@E000C000 {> compatible = "ns16550a";> reg = <xE000C000 0x100>;> interrupts = <10 0>;> clock-frequency = <72000000>;> status = "okay";> };
Hier wurde der LPC3220 Controller benutzt -> PORT_LPC3220
in drivers/tty/serial/8250/8250.c
kann man lesen
1
[PORT_LPC3220]={
2
.name="LPC3220",
3
.fifo_size=64,
4
.tx_loadsz=32,
5
.fcr=UART_FCR_DMA_SELECT|UART_FCR_ENABLE_FIFO|
6
UART_FCR_R_TRIG_00|UART_FCR_T_TRIG_00,
7
.flags=UART_CAP_FIFO,
IRQ Controller muss ich wie gesagt nochmal genauer lesen
Hi Ulli,
danke. Was die ganzen kryptischen Konstrukte im Device Tree angeht, habe
ich das angehängte PDF gefunden, vielleicht ist das für dich auch
interessant. Es geht dort zwar um PowerPC, aber der Device Tree ist ja
grundsätzlich der selbe.
Noch eine Frage - in der init_machine() habe ich ja
of_platform_populate().
Wann wird denn init_machine() aufgerufen? Bei mir ist er irgendwie gar
nie soweit gekommen, dass er die Funktion aufgerufen hätte.
Ich frage mich, ob es daran liegt, dass ich noch irgendwas beim Booten
falsch mache. Gemäss /Documentation/devicetree/booting-without-of.txt
sollte es ja reichen, wenn man den Device Tree ins Memory kopiert und
dann die Basisadresse in r2 übergibt.... So mache ich das auch. Und er
wird auch erkannt, aber ich hab das Gefühl irgend ein kleines Detail
fehlt noch, dass er init_machine() nicht aufruft.... :-/ Die Frage ist
auch, wohin der Device Tree geladen werden muss. Ich nehme mal an, der
darf nicht einfach irgendwo im Memory stehen, sonst wird er ja ggf.
überschrieben? Darf er im Flash liegen?
Dann noch was - wenn ich den Kernel "in-Place" aus dem Flash laufen
lasse - muss ich den Memory-Bereich, wo das Flash liegt, im Device Tree
auch angeben? theoretisch macht das ja keinen Sinn, da der Kernel
sowieso nicht ins Flash schreiben darf, sonst würde er sich ja selbst
überschreiben :-)
Gruss
Alfons schrieb:> Hi Ulli,>> danke. Was die ganzen kryptischen Konstrukte im Device Tree angeht, habe> ich das angehängte PDF gefunden, vielleicht ist das für dich auch> interessant. Es geht dort zwar um PowerPC, aber der Device Tree ist ja> grundsätzlich der selbe.
ich glaube er wird demnächst auch auf MIPS laufen, ich haben sowas auf
der OpenWRT Mailingliste gelesen.
>> Noch eine Frage - in der init_machine() habe ich ja> of_platform_populate().> Wann wird denn init_machine() aufgerufen? Bei mir ist er irgendwie gar> nie soweit gekommen, dass er die Funktion aufgerufen hätte.>
in
arch/arm/kernel/seutp.c habe ich was gefunden.
Was mir in dem Code gerade auffällt, falls es dir nicht schon bekannt
ist :
Alle Bezeichner (Funktionen und Variablen) mit Unterschrich (Underscore)
sind "versteckt". Je länger der Unterschrich ist umso verstecker sind
diese und umso mehr Ärger bekommt man, wenn diese benutzt werden.
> Ich frage mich, ob es daran liegt, dass ich noch irgendwas beim Booten> falsch mache. Gemäss /Documentation/devicetree/booting-without-of.txt> sollte es ja reichen, wenn man den Device Tree ins Memory kopiert und> dann die Basisadresse in r2 übergibt.... So mache ich das auch. Und er> wird auch erkannt, aber ich hab das Gefühl irgend ein kleines Detail> fehlt noch, dass er init_machine() nicht aufruft.... :-/ Die Frage ist> auch, wohin der Device Tree geladen werden muss. Ich nehme mal an, der> darf nicht einfach irgendwo im Memory stehen, sonst wird er ja ggf.> überschrieben? Darf er im Flash liegen?
Die Doku ist meitens für den "normalen" Fall geschrieben, wenn das
zImage im Speicher liegt. Da reloziert und entpackt sich ja
bekanntermaßen.
>> Dann noch was - wenn ich den Kernel "in-Place" aus dem Flash laufen> lasse - muss ich den Memory-Bereich, wo das Flash liegt, im Device Tree> auch angeben? theoretisch macht das ja keinen Sinn, da der Kernel> sowieso nicht ins Flash schreiben darf, sonst würde er sich ja selbst> überschreiben :-)>
Vergleiche das mal den den anderen Arches, dort wird seit einiger Zeit
"In-Place" gemacht und das zu Zeiten ohne Device Tree. Dort wurden alle
Speicherbereiche mit angegeben.
Ich muss mir nochmal durchlesen wie die ATAGS und/oder DeviceTree an
dem entpackten Kernel übergeben werden.
Der Kopf war schenller als ich gedacht habe.
in
arch/arm/boot/bootp startet der Kernel.
ich muss das mal prüfen mit einem XIP Kernel-Build
Hi Ulli,
hmm ja die Setup.c "verpackt" einfach den Aufruf von init_machine() in
customize_machine() :-) Zudem ist da noch
arch_initcall(customize_machine);
woraus ich allerdings leider auch nicht sehe, wann das Dingens
aufgerufen wird.
Bezüglich des ganzen Memory Gedöns - ich werde also heute Abend mal
versuchen, nicht mit XIP zu arbeiten, sondern mit dem zImage. Der soll
sich selber seinen Speicher zurecht suchen, den er braucht ;-) Dann
lasse ich den DT mal im Flash, das muss ja irgendwie gehen...
Arghh.
Der "richtige" Start ist in
arch/arm/kernel/head.S
muss ja auch Assembler sein, da ja noch kein Stack, MMU usw,
initialisiert ist.
Der Compressor und das zImage sind ja "ungültig", und darauf kann man
sich nicht verlassen.
Auch sieht man hier wieder das Register "r2" aber nur r2. Die ATAGS
werden im DT falls nach DT "portiert", das habe ich im Bootcode gelesen.
Und auch jetzt verstanden warum das gemacht wurde:
Die brauchten den stabilen code in head.S und setup.c kaum anzufassen
um den DT zu implementieren, eine Fehlerquelle weniger.
In
arch/arm/kernel/setup.c
dürfte mein Kandidat zum starten dies hier sein
void __init setup_arch(char **cmdline_p)
Meine Vermutung das läuft irgendwie über eine Art Tabelle
struct machine_desc *machine_desc __initdata;
Das werde ich mir vielleicht heute nochmal genauer ansehen.
Hallo Ulli,
so, ich hab das Ding jetzt so weit, dass er bis zur customize_machine()
startet. Der Timer wird initialisiert und "tickt" dann nachher auch ;-)
kann man sehen auf dem Terminal. Und nach einigen (5 oder so)
Timer-Ticks kommt dann die machine_init(). Sieht also schon mal gut aus.
Heute werde ich da noch die of_platform_populate() rein schreiben bei
der machine_ini(), und dann sollte auch der UART usw. korrekt
funktionieren nachher oder? of_platform_populate() "nimmt" sich, so wie
ich das sehen kann, den Device Tree vor und schaut da drin, welche
Devices es so gibt und initialisiert die mal. Richtig?
Ein Problem habe ich allerdings noch immer. WO muss ich den Device Tree
ablegen? Ich habe mal versucht, die dtb-Datei als binäre Daten im Flash
abzulegen. Das funktionierte nicht, offenbar muss sie im RAM sein. Lede
ich die Datei aber im RAM unterhalb von 0xa0000000 ab, so funktioniert
gar nichts; dann bleibt er schon bei bootmem_init() hängen, weil er
meint, von 0x40000000 bis 0xa4000000 sei durchgehender Speicher, aber
ich habe den ja nicht contiguous, sondern mit "Löchern" drin :-( also
muss ich den Device Tree ins SDRAM speichern, und dort besteht irgendwie
immer die Gefahr, dass der Kernel ihn selbst überschreibt... Hast du
eine Idee?
Gruss
Alfons schrieb:> Hallo Ulli,>> so, ich hab das Ding jetzt so weit, dass er bis zur customize_machine()> startet. Der Timer wird initialisiert und "tickt" dann nachher auch ;-)> kann man sehen auf dem Terminal. Und nach einigen (5 oder so)> Timer-Ticks kommt dann die machine_init(). Sieht also schon mal gut aus.> Heute werde ich da noch die of_platform_populate() rein schreiben bei> der machine_ini(), und dann sollte auch der UART usw. korrekt> funktionieren nachher oder?
Wenn der IRQ für den UART funktioniert, dann ja.
Im Fehlerfall würde ich dort erstmal suchen, zuerst sehen ab der IRQ
auch "requestet" wird
siehe
/drivers/tty/serial/8250/8250_core.c
Funktion
ggf. kann man hier noch ein printk einfügen.
Oder sich was andere ausdenken ..., ggf. den Output über earlyprintk
laufen lassen (hier den direkten Einsprungpunkt suchen und nutzen !)
Debugen per gdb und Co. ist hier schwer
git grep
Und einige Terminals sind hier nützlich.
> of_platform_populate() "nimmt" sich, so wie> ich das sehen kann, den Device Tree vor und schaut da drin, welche> Devices es so gibt und initialisiert die mal. Richtig?>
Soweit richtig
> Ein Problem habe ich allerdings noch immer. WO muss ich den Device Tree> ablegen? Ich habe mal versucht, die dtb-Datei als binäre Daten im Flash> abzulegen. Das funktionierte nicht, offenbar muss sie im RAM sein.
Laut Doku soll dies auch im RAM liegen. Ich tippe darauf das nacher
vielleicht die Sache "freigegeben" wird (muss aber nicht sein).
> Lede> ich die Datei aber im RAM unterhalb von 0xa0000000 ab, so funktioniert> gar nichts; dann bleibt er schon bei bootmem_init() hängen, weil er> meint, von 0x40000000 bis 0xa4000000 sei durchgehender Speicher, aber> ich habe den ja nicht contiguous, sondern mit "Löchern" drin :-( also> muss ich den Device Tree ins SDRAM speichern, und dort besteht irgendwie> immer die Gefahr, dass der Kernel ihn selbst überschreibt... Hast du> eine Idee?>
Zur Zeit noch nicht.
Das mit den memory holes ist ja übel.
Zwischendurch ist mir eingefallen was es vielleicht mit dem
(DIS)CONTINOUS memory allocation zu tun hat.
Das war glaube ich eine "Erfindung" von Samusung für deren Video Chip
auf dem Smartphone/Tablet um hier Fenster effektiv zu
kopieren/verschieben.
Genauers weiss ich aber nicht mehr, nur das es im diesem Fall sogar
ein Video von einer Hackerkonferenz gab, wo dieses Feature vorgestellt
wurde. Da wurde erzählt wie es Mainline wurde, Samsung wollte da andere
Wege gehen ...
Warum jetzt von der HW so viele Löcher drin sind ist seltsam. Bei dieser
Config kommen garantiert Probleme vor mit der Speicherverwaltung.
Was passiert wenn du am Ende eines Bereiches bist und der Userspace
(ggf. auch Kernel) mach ein realloc().
Auch sind andere Sachen vorstellbar, ich kann mich aus MS-DOS Zeiten
noch dran erinnern, das man die memalloc INT Aufruf "tunen" konnte. Nach
FIRST, BEST, LAST Speicherbereichen. Die 8086 CPU hatte ja auch keine
MMU :(, da wurde halt der Speicher "knapp" weil zuviele kleine Bereich
alloziert wurden.
Zwischendurch bin ich wegen dem append DT und initramfs weitergekommen
und kann sagen es geht nicht, weil da einige Pointer verkehrt
berechnet werden. Was aber auch in der Doku richtig (für mich aber
leider falsch) ist :(
Dazu musste ich etwas länger nachdenken, dreimal den Compiler
anwerfen und das Ergebnis ansehen. Kein Test auf der HW war nötig.
Jetzt muss ich nur noch sehen ob ich die Sache im Build patchen kann. So
wie ich es haben will, dann ist es auch etwas universeller ...
> Gruss
Hi Ulli,
also dann ist es normal und richtig, dass die Memory-Verwaltung nicht
korrekt funktioniert, wenn so grosse Löcher im Memory vorhanden sind?
sehr seltsam. Aber gut, dann muss ich damit leben, dass das interne RAM
nicht nutzbar ist.
Wegen dem appended DTB - das funktioniert also mit dem offiziellen
Kernel nicht ? Das ist auch gut zu wissen. Dann muss ich damit nichts
mehr rum pröbeln. Muss nur noch rausfinden, WO der DTB abgelegt werden
muss, ob am Anfang (Offset 0 wohl kaum) oder am Ende (0xa3fff000 oder
sowas). In der Mitte wohl kaum, da wird der ja überschrieben...
Gruss
Alfons schrieb:> Hi Ulli,>> also dann ist es normal und richtig, dass die Memory-Verwaltung nicht> korrekt funktioniert, wenn so grosse Löcher im Memory vorhanden sind?> sehr seltsam. Aber gut, dann muss ich damit leben, dass das interne RAM> nicht nutzbar ist.
Das interne RAM (64kib ??) ist laut dem Kernel auf google, für die
Diskriptoren von Ethernet (und USB ?) genutzt. Status in uClinux und
mainline Kernel nicht bekannt.
Mit den memory Holes ist von mir nur eine Vermutung, weil ich ja keine
MMU habe die mir den Speicher "verschiebt".
Ich würde erstmal die größten zusammenhängen Speicher verwenden und
nicht mehr. Dann wenn der Kernel sauber läuft (also bis in den
Userspace oder ins vfs), das mit den Holes testen.
Ich habe damit potenzielle Fehlerquellen weniger.
>> Wegen dem appended DTB - das funktioniert also mit dem offiziellen> Kernel nicht ? Das ist auch gut zu wissen. Dann muss ich damit nichts> mehr rum pröbeln. Muss nur noch rausfinden, WO der DTB abgelegt werden> muss, ob am Anfang (Offset 0 wohl kaum) oder am Ende (0xa3fff000 oder> sowas). In der Mitte wohl kaum, da wird der ja überschrieben...>
Der Speicherbereich vom DTB wird sowieso nacher "überschrieben"
Nach dem machine_init() und Co. ist der DTB wertlos.
Auch sollten die Device Treiber beim Init nur minimal Speicher
anfordern. Erst beim open() wird/sollte der größte Teil alloziert
werden.
z.B.
ifconfig up
macht ein net_if->open()
und da werden die ganzen Buffer alloziert.
append DTB und initramfs.
append DTB geht alleine problemlos, das ist aber auch erst ab 3.9-rc1
(mainline) drin, soweit ich es gesehen habe.
Wenn jetzt append DTB und initramfs (auch nur die Option ?) aktiviert
ist, wird das "integrierte" cpio Archiv leider in der Berechnung des
Offsets auf den DTB vergessen. Und das auch nur deshalb weil alleine
dazu nur die Größe von zImage (oder Image steht irgendwo im Code ;-) )
genommen wird.
Genaueres kann ich aber erst in ein paar Tagen sagen. Das habe ich
allein aus der Größe von vmlinux und den Files im usr Verzeichnis
gesehen.
Wie gesagt zuerst hatte ich auf der HW nur
"booting Linux"
gesehen, und das kommt von "earlyprintk" danach kam nichts mehr.
Und ich möchte mein DTB an dem zImage mit intergrierten initranmfs
cpio Archiv hängen. Also
zImage + cpio + DTB
Alles andere ist in meinem Sinne Blödsinn, ich kann dann die HW Platform
nicht einfach ändern.
Ein
zImage + DTB + cpio
ginge auch ist aber kompliziert, da sich ja die Größe vom DTB ändern
kann.
Mal sehen ...
Was mir zwischendurch durch den Ausflug nach MS-DOS eingefallen ist :
Du hast doch auf SoC eine Menge freier I/O Pins ...
Du kannst doch einen vielleicht dafür benutzten um dir eine "Debug"
Ausgabe für den UART IRQ zu basteln.
Einfach bei jedem Interrupt den Output toggeln ...
So habe ich in etwa früher auf dem C64 die Interrupt Routinen "debuged",
da habe ich den Rahmen von Bildschirm immer geändert.
Schau erstmal das der Kernel nur mit UART, RAM ggf. MTD compiliert wird.
Alle anderen Sachen raus, der DT kann ruhig komplett sein.
Ich weiss jetzt nicht ob du schon mit git angefangen hasst.
Aber dazu noch ein Tipp von mir :
Wenn du soweit bist mach für jede Änderung die logisch ist, auch wenn
es nur eine Zeile ist, ein git add/commit.
Damit kannst zu auch ohne HW coden, bzw. brauchst den Compiler nicht
laufen zu lassen. Die Zeiten für TFTP und Co. rechne ich auch mal dazu.
Ich habe da mal einen Treiber "überarbeitet" und erst nach einiger Zeit
merkt (als ich einen HW Test machte) das das ein Fehler im Code war.
Ein git bisect hatte mir in dem Fall geholfen.
Ich habe ingesammt Zeit gespart und brauchte unterwegs die HW nicht mit
mir herum schleppen ;-)
> Gruss
* Some debugging routines (useful if you've got MM problems and
19
* printk isn't working). For DEBUGGING ONLY!!! Do not leave
20
* references to these in a production kernel!
21
*/
Wird aktiviert mit "Kernel low-level debugging functions" in Hacking.
Die Schnittstelle wird in head.S in arch/arm/kernel
suche nach dem addruart Makro usw.
Den Aufruf dazu muss du mit deiner HW anpassen.
Das DING läuft vor earlyprintk
Hi Ulli,
ich so danke für deine Ausführungen. Ich bin jetzt auch wieder einen
Schritt weiter. Also das mit den Löchern im Memory funktioniert wirklich
nicht, da kann ich machen was ich will. Aber, was jetzt geht - er bootet
reproduzierbar bis rest_init(); in der init/main.c!!! Das Problem,
warum es bisher nicht sauber gelaufen ist, war bei meiner HW. Ich hatte
vorher noch nie wirklichen Code aus dem externen Flash laufen lassen,
sondern immer nur aus dem SDRAM, und das hat auch immer funktioniert.
Aus dem Flash geht es jetzt auch, wenn man den Memorycontroller
richtig initialisiert vor dem booten :-D ich musste Burst- Zugriffe
aktivieren und ein paar Waitstates mehr einfügen, und siehe da, der
Timer wird initialisiert und tickt, und er kommt immer reproduzierbar
bis rest_init() hoch. Super! Jetzt muss ich nur noch rausfinden, was
dann passiert.
Mein DT wird mit of_platform_populate() anscheinend auch "angeguckt",
aber der UART scheint noch nicht zu funktionieren, da hakt noch was.
Eine Debug-Ausgabe sagt zwar, dass die Init des 8250 aufgerufen wird,
mehr passiert dann allerdings auch nicht. Morgen muss ich dem noch
weiter auf den Grund gehen, erstmal Feierabend machen.
Zu deinem Vorschlag mit Git - selbstverständlich habe ich eine
Versionsverwaltung. Ich benutze allerdings SVN, weil ich da schon alles
drin habe und ich alles beieinander haben möchte. Also habe ich den Code
mal da eingechekt.
Gruss
In rest_init() wird wie der Name es sagt /sbin/init gestartet.
Es gehen auch andere Programme :
Ist hier zu lesen Zeil 851 in init/main.c
1
if(!run_init_process("/sbin/init")||
2
!run_init_process("/etc/init")||
3
!run_init_process("/bin/init")||
4
!run_init_process("/bin/sh"))
Am einfachsten ist es direkt die Shell zu starten.
Ab hier hast du aber schon zwei Prozesse am laufen ...
Ja SVN hatte ich auch mal benutzt, auch zu Zeiten wo ich mit dem Kernel
angefangen Kernel habe.
Als ich später mal ein paar Branches hatte und die wollte ich dann
Mergen, hat mein Kleinhirn die weisse Fahne gehisst.
Der umstiegt von SVN nach git hatte denn etwas lange gedauert, da ich
ja in dem File und/oder Directory Schema gedacht habe.
Jetzt würde ich nichts anderes verwenden.
Es gibt auch hg und bazar die sind irgendwie ähnlich.
So zum Thema DT und initramfs kannn ich jetzt sagen :
Soweit ein kleine cpio Archiv vorhanden ist, startet der Kernel
"normal", findet aber ein korruptes Archiv und entpackt dies nicht.
Wenn das RootFS größer ist (um 2MiB gepackt), dann kommt nur
"Linux booting"