Forum: Compiler & IDEs Embedded Linux Kernel debuggen


von Tobias P. (hubertus)


Lesenswert?

Hallo zusammen,

ich bin dran, ein Embedded Linux zum Laufen zu bringen, oder versuche es 
zumindest. :-)
Ich bin schon mal soweit, dass ich ein xipImage kriege, und das bootet 
auch teilweise, jedenfalls kann ich mir printk() Meldungen ausgeben. 
Jedoch irgendwo noch bevor der init-Prozess gestartet wird, läuft was 
schief, und ich habe noch nicht rausgefunden, was.
Jetzt die Frage - kann ich diesen Kernel einfach normal mit GDB 
debuggen?

Es handelt sich um ein ARM7 System, der Kernel soll vom ext. Flash 
direkt in-place ausgeführt werden, also ohne dekompression etc.

Zum Debuggen möchte ich gerne ddd benutzen; was muss ich tun, um die 
Symbole in ddd geladen zu kriegen? "Normale" Programme kann ich auf dem 
Target so debuggen, aber beim Kernel bin ich mir nicht so sicher.

(Dass es bei multithreading dann schwierig wird, ist natürlich klar, 
aber solange der Kernel nicht richtig hoch kommt, sollte es so mit ddd 
ja klappen, oder?)


Gruss Tobias

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Moin Tobias,

da ich bald das selbe Problem haben werde und gerade beim einlesen bin, 
bin ich gerade über kgdb gestolpert.


http://scottt.tw/linux-tutorials/

letztes tutorial. kgdb scheint ein gdb modul für den Kernel zu sein. Wie 
gesagt ich hab da auch noch keine Erfahrung, Kenne Linux bisher nur als 
Desktop Nutzer und da auch nur wenig von console usw.

Falls du für mich n Tip hast wo man sich gut einlesen kann gern :)

MfG

Tec

von meckerziege (Gast)


Lesenswert?

Musst du wirklich so tief einsteigen?

Was kommt denn als Fehler bevor es nicht mehr weitergeht? Versuch mal 
alles was du nicht brauchst zu deaktivieren bzw. gibts da auch afaik ein 
paar Optionen, dass er die Module nicht automatisch beim Hochfahren läd.

von abc (Gast)


Lesenswert?

Tobias Plüss schrieb:
> Ich bin schon mal soweit, dass ich ein xipImage kriege, und das bootet
> auch teilweise, jedenfalls kann ich mir printk() Meldungen ausgeben.
> Jedoch irgendwo noch bevor der init-Prozess gestartet wird, läuft was
> schief, und ich habe noch nicht rausgefunden, was.
> Jetzt die Frage - kann ich diesen Kernel einfach normal mit GDB
> debuggen?

Pah, das ist Highlevel :-)

Kernel mit Debug-Symbols compilieren und dann den gdb mit JTAG anbinden. 
Da kommst du wirklich bis zur Drahtebene.

http://elinux.org/Debugging_The_Linux_Kernel_Using_Gdb

von imonbln (Gast)


Lesenswert?

Tobias Plüss schrieb:
> ich bin dran, ein Embedded Linux zum Laufen zu bringen, oder versuche es
> zumindest. :-)
jeder hat mal angefangen, also mach nur weiter

> Ich bin schon mal soweit, dass ich ein xipImage kriege, und das bootet
> auch teilweise, jedenfalls kann ich mir printk() Meldungen ausgeben.

fein das ist doch schon mal was.

> Jedoch irgendwo noch bevor der init-Prozess gestartet wird, läuft was
> schief, und ich habe noch nicht rausgefunden, was.

Wie verhält sich das "läuft was schief" genau?
Endlesslop, Crashdump etc.. beschrieb das mal etwas genauer um dir zu 
helfen ist das entscheidend, vielleicht kann man an diesen Informationen 
schon das Problem soweit eingrenzen das man das schwere geschütz 
Debugger im Schrank lassen kann. ggf kannst du die Aussgabe der 
Rootconsole mitzuschneiden. (gnu/screen kann das zum Beipiel)

> Jetzt die Frage - kann ich diesen Kernel einfach normal mit GDB
> debuggen?

Nein das geht nicht. es gibt wie schon ewähnt den kgdb, aber der geht 
auch nicht immer einfach so. Ausserdem brauchts du auf den host ein gdb 
welcher für das Taget ARM7 ist. Alles andere ist quatsch. Wichtig ist 
auch die System.map dort liegen die debugg informationen für dein 
Kernel.

Alternativ liefern auch Hersteller wie Lauterbach, Windriver, Montavista 
und der erzeuger deines BSP meistens bessere oder schlechtere Tools für 
das Kernel debuggen.
Der Lauterbach debugger  ist toll aber mit mehren Kilo Euros so teuer, 
das man denn auch nur dann kauft wenn man das Hauptberuflich macht.

>
> Es handelt sich um ein ARM7 System, der Kernel soll vom ext. Flash
> direkt in-place ausgeführt werden, also ohne dekompression etc.
>
geht, für das debuggen und Entwickeln ist es aber meisten eleganter, den 
Bootloader zu sagen den Kernel via TFTP zu laden das geht in der Regel 
schneller mal was auszu probieren. Btw das root als NFS ist aus denn 
grund auch nicht schlecht.

> Zum Debuggen möchte ich gerne ddd benutzen; was muss ich tun, um die
> Symbole in ddd geladen zu kriegen? "Normale" Programme kann ich auf dem
> Target so debuggen, aber beim Kernel bin ich mir nicht so sicher.

Auch das geht mit den passenden Arm7 gdb und denn kernel mit kgdb.
Ich glaube der ddd parameter war --target-*

Aber wichtiger bei solchen Problemen ist ddd als "debuggen druch Denken" 
zu übersetzten und sich nicht auf seine GUI zu verlassen, wie ob schon 
angedeutet kann man bie vielen Fehlern durch scharfes Hinsehen und 
logisch denken vieles schon erschlagen bevor andere Ihren gdb und ddd 
zum laufen gebracht haben. Ausserdem  behaupten einige das man mit einen 
debugger die symtome bekämpft und nicht die Ursachen.

von Tobias P. (hubertus)


Lesenswert?

Hallo zusammen,

erstmal danke für eure zahlreichen Antworten!
Nun, einen JTAG-Debugger für mein Target sowie eine passende GDB 
executable habe ich natürlich. Das funktioniert auch, habe ich für 
"gewöhnliche" Programme schon getestet. Was ich vorerst mal tun will, 
ist ja nicht einmal, irgendwelches Scheduler-Zeugs zu testen, sondern 
ich will zunächst nur mal nachvollziehen, was denn nicht geht.
Da ich die Hardware selber gebaut habe, gibt es auch kein fertiges BSP, 
was ich einfach hernehmen kann und das läuft, sondern ich musste da 
selber was schreiben gemäss "ARM Linux porting guide".

Mein Kernel bootet eigentlich soweit hoch, dass er bis dort kommt, wo 
/sbin/init aufgerufen werden sollte. Mein Problem ist halt, dass der 
UART-TReiber bisher auch noch nicht richtig geladen wurde - ich habe 
einen 16c550 kompatiblen UART, aber aus irgend einem Grunde geht 
printk() nicht ordentlich, sondern ich habe mir mit early_printk() was 
zurechtgebogen. :-/
Auf jeden Fall habe ich meinen Tick-Interrupt mal so gemacht, dass bei 
jedem Interrupt eine Meldung via early_printk() auf der Seriellen 
ausgegeben wird; den Timer habe ich mal mit 10 Hz angesetzt, was locker 
passt. Der Tick Interrupt kommt dann einige 100 mal, bis der Kernel 
schliesslich versucht, init zu laden, was anscheinend fehl schlägt, und 
dann stürzt die Kiste ab (Reset). Sieht mir ganz danach aus, als ob da 
irgendwie ein ungültiger Pointer oder sowas wäre, aber bis jetzt konnte 
ich es noch nicht so ganz nachvollziehen.... :-(


Ich will heute Abend mal mit dem Tutorial versuchen, den GDB anzuwerfen 
und mir mit ddd das mal anzuschauen, bin gespannt ob ich was sehe 
(wenigstens unversucht will ich es nicht lassen ;-) ).

Gruss

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Keine Ahnung, ob's auf Dein Problem passt, aber vielleicht Hilft's ja:

Den Thread kennst Du?

Beitrag "Linux Kernel compilieren"

von Tobias P. (hubertus)


Lesenswert?

Moin zusammen,

danke nochmals für eure Hilfe.

Was ich in der Zwischenzeit versucht habe:
ich habe ein xipImage neu erstellt und dieses ins Flash geladen. Das 
xipImage bootet (halt fehlerhaft noch bis jetzt) und ich wollte mal den 
Debugger anwerfen. Wie erwähnt habe ich für mein Target einen J-Link mit 
GDB-Server. Das Debuggen funktioniert so, habe ich mit früheren 
Programmen schon getestet, allerdings ist mir nicht klar, welche der 
vielen beim Compilieren erzeugten Dateien ich im Debugger laden muss, 
damit ich die Symbole geladen kriege. xipImage enthält keine Symbole, 
ebenso wenig wie vmlinux. Wo sind denn diese Symbole drin?

Dann noch was anderes.
Ich habe bemerkt, dass mein Kernel eigentlich korrekt booten würde, wenn 
ich im Timerinterrupt die UART-Ausgaben weglasse. Stattdessen lasse ich 
bei jedem Timer-Tick einen Pin toggeln; auf dem Oszi lässt sich dies 
hervorragend nachvollziehen und der Timer-Tick scheint zu funktionieren!

Allerdings ist der Timer das einzige, was mein Kernel bis jetzt im 
Stande ist, zu initialisieren :-) Zwar habe ich einen m.E. korrekten 
"Device Tree" erstellt, wie dies gefordert wird, aber dort drin werden 
meine Devices nicht gefunden, z.B. der UART wird nicht initialisiert 
etc. Was könnte da das Problem sein? Wenn ich es halt debuggen könnte, 
wäre es schon viel einfacher, aber das geht halt leider noch nicht, 
daher kann ich auch nur eine so schwammige Fehlerbeschreibung geben :-(

von Hans Ulli K. (Gast)


Lesenswert?

Hallo

Wenn ich das richtig lese hast du ein ARM7 also noch ohne MMU ?? oder

von Tobias P. (hubertus)


Lesenswert?

Ja genau!

von Hans Ulli K. (Gast)


Lesenswert?

Ich würde mal drauf tippen das irgendwas mit der Config vom 16550 nicht 
stimmt.

Hast du den DeviceTree mit r2 an den Kernel übergeben ?
Die Symbole sind in der Datei System.map im Builddir vom Kernel.
Benutzt du den vanilla Kernel oder den von uClinx.org ?

Schau mal bei beiden nach welche Platform deiner CPU/SoC am nächsten 
kommt. Das ARM Porting Guide ist eigentlich dafür gedacht wenn du bei 
Null anfangen musst.

von Tobi (Gast)


Lesenswert?

Nur mal so am Rande.
Versuch doch den Kernel mit dem Qemu laufen zu lassen.

Gruss,
Tobi

von Tobias P. (hubertus)


Lesenswert?

Hallo zusammen,

so, ich bin nun ein ganzes Stück weiter!
Ich konnte nun alle meine early_print() raus schmeissen, denn mein 
Kernel kann jetzt so weit booten, dass der UART erkannt wird und die 
normalen Kernel-Meldungen erscheinen!
1
Booting Linux on physical CPU 0x0
2
Linux version 3.8.5+ (tobias@zap) (gcc version 4.7.3 20130312 (release) [ARM/emb
3
edded-4_7-branch revision 196615] (GNU Tools for ARM Embedded Processors) ) #135
4
 Wed May 22 21:20:48 CEST 2013
5
CPU: ARM7TDMI [41007700] revision 0 (ARMv3), cr=00000000
6
CPU: VIVT data cache, VIVT instruction cache
7
Machine: LPC24XX SoC (Flattened Device Tree), model: LPC2468 Board
8
bootconsole [earlycon0] enabled
9
init early
10
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 12192
11
Kernel command line: earlyprintk console=ttyS0
12
PID hash table entries: 256 (order: -2, 1024 bytes)
13
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
14
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
15
Memory: 48MB = 48MB total
16
Memory: 48432k/48432k available, 720k reserved, 0K highmem
17
Virtual kernel memory layout:
18
    vector  : 0xa0000000 - 0xa0001000   (   4 kB)
19
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
20
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
21
    lowmem  : 0xa0000000 - 0xa3000000   (  48 MB)
22
      .text : 0x80000000 - 0x8011e024   (1145 kB)
23
      .init : 0xa000a000 - 0xa000d000   (  12 kB)
24
      .data : 0xa0008000 - 0xa001c740   (  82 kB)
25
       .bss : 0xa001c740 - 0xa004370c   ( 156 kB)
26
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
27
NR_IRQS:16 nr_irqs:16 16
28
OF: no ranges; cannot translate
29
System timer is /soc/timer@E0004000
30
OF: no ranges; cannot translate
31
Kernel panic - not syncing: Can't remap registers
32
Backtrace:
33
[<80002f04>] (dump_backtrace+0x0/0x104) from [<800ebab0>] (dump_stack+0x18/0x1c)
34
 r6:a001c9c8 r5:a000aa20 r4:a00a47f0 r3:00000001
35
[<800eba98>] (dump_stack+0x0/0x1c) from [<800ebb34>] (panic+0x80/0x1c4)
36
[<800ebab4>] (panic+0x0/0x1c4) from [<8012b0ec>] (bcm2835_time_init+0x88/0xb8)
37
 r3:ffffffff r2:ffffffea r1:ffffffff r0:8011b38e
38
 r7:a00a4be0
39
[<8012b064>] (bcm2835_time_init+0x0/0xb8) from [<80120fe0>] (time_init+0x28/0x38
40
)
41
 r4:a001c740
42
[<80120fb8>] (time_init+0x0/0x38) from [<8011e6f8>] (start_kernel+0x18c/0x2b4)
43
[<8011e56c>] (start_kernel+0x0/0x2b4) from [<8000001c>] (0x8000001c)
44
 r7:a0013e1c r6:a000aa1c r5:a001301c r4:00000000

leider erkennt ihr, dass nicht alles ganz so funktioniert; das "Register 
remapping" scheint nicht zu funktionieren. Ich schätze, wenn ich keine 
MMU habe, dann wird auch map_io() vom Machine Record nie aufgerufen, 
richtig? und ohne MMU brauche ich auch kein Remapping?
Wie kriege ich dann jeweils die Basisadresse meiner Devices?

von Hans Ulli K. (Gast)


Lesenswert?

Hast du denn schon mal nach der Fehlermeldung in den Sourcen gegreped 
...
Nein, da finde ich folgende Zeile
1
drivers/clocksource/bcm2835_timer.c:107:                panic("Can't remap registers");

Im Makefile drivers/clocksource/Makefile finde ich denn das
1
obj-$(CONFIG_ARCH_BCM2835)  += bcm2835_timer.o
Da ist wohl was mit deiner Config falsch.
Nimm erstmal ARCH_MULTIPLATFORM raus.

von Tobias P. (hubertus)


Lesenswert?

Hi Hans Ulli,
nein die Fehlermeldung kommt von meinem Code, habe da was kopiert und 
auf meine Bedürfnisse angepasst.
Er scheitert halt beim Statement hier:
1
  node = of_find_matching_node(NULL, timer_match);
2
  if(node == NULL) {
3
    panic("can't find node!");
4
  }
5
  base = of_iomap(node, 0);
6
  
7
  /* mapping successful? */
8
  if(base == NULL)
9
  {
10
    panic("Can't remap registers");
11
  }

Die node für den Timer findet er also, das macht er korrekt. Aber 
of_iomap() schlägt fehl. Aber die Frage ist halt, ob ich das wirklich 
brauche, auch wenn ich keine MMU habe?




Edit:
mein KConfig sieht so aus:
1
depends on !MMU
2
select CLKSRC_MMIO
3
select COMMON_CLK
4
select GENERIC_CLOCKEVENTS
5
select GENERIC_IRQ_CHIP
6
select IRQ_DOMAIN
7
# select PINCTRL
8
select NO_IOPORT
9
#select CONFIG_CPU_CP15
10
select USE_OF
11
select CONFIG_DEBUG_LL
12
#  select GENERIC_CLOCKEVENTS
13
select MULTI_IRQ_HANDLER
14
select SPARSE_IRQ
Also nichts mit Multiplattform.

von Hans Ulli K. (Gast)


Lesenswert?

Tobias Plüss schrieb:
> Die node für den Timer findet er also, das macht er korrekt. Aber
> of_iomap() schlägt fehl. Aber die Frage ist halt, ob ich das wirklich
> brauche, auch wenn ich keine MMU habe?
>
of_iomap brauchst du hier nicht, weil wie gesagt keine MMU.
Aber du brauchst ja deine BASE Addresse vom Device aka Timer.
In der Funktion of_iomap () ist auch die Lösung zu finden ...
1
void __iomem *of_iomap(struct device_node *np, int index)
2
{
3
  struct resource res;
4
5
  if (of_address_to_resource(np, index, &res))
6
    return NULL;
7
8
  return ioremap(res.start, resource_size(&res));
9
}

Wenn du folgenden Teil benutzt :
1
  struct resource res;
2
3
  if (of_address_to_resource(np, index, &res))
4
    return NULL;
liegt in res.start deine BASE Addresse.

In einigen (alten) Treiberen wurde nach dem "get_resource" noch ioremap 
"zu Fuss" gemacht"

> Also nichts mit Multiplattform.

War meine erste Annahme nach einigem grepen
Was mich auch noch stutzig mach(te) war/ist folgende Ausgabe.

bcm2835_time_init

von Hans Ulli K. (Gast)


Lesenswert?

Hmmm ...

kennst du ein gutes und preisgünstiges Board ??
Wichtig ist auch das es ein Gehäuse dafür gibt, ich habe keine Lust zum 
basteln.

Vielleicht würde es mich mal reizen mal mit einem NOMMU System zu 
spielen.
Ich kenne jetzt schon MIPS und ARM Systeme aber alles mit MMU ...

Die Netzwerkperformance (Ethernet/Wifi) und USB dürften wohl 
unterirdisch sein.

Achja
Den CodingStyle solltest du mal überdenken ...
Die geschweiften Klammer sind nicht K&R.

Was jetzt mit den Spaces vor und nach den Klammern ist, lass ich ertsmal 
da ich es selbst nach einigen Jahren(zehnten ?) noch nicht verinnerlicht 
habe .

von Tobias P. (hubertus)


Lesenswert?

Hallo Hans Ulli,
danke für den Hinweis. Das habe ich auch schon gesehen, aber war mir 
nicht sicher. Aber danke für deine Bestätigung, ich habe es jetzt bei 
mir so implementiert!

Was ich mich noch frage:

Es gibt ja die Timer-Initfunktion, welche auch im machine Record 
vermerkt wird (mit der sys_timer-Struktur). Meine Timer-Init sieht jetzt 
wie folgt aus:
1
static void __init timer_init(void)
2
{
3
  struct device_node *node = NULL;
4
  struct resource res;
5
  int irq;
6
7
  do {
8
    /* get a node from the device tree */
9
    node = of_find_matching_node(NULL, lpc24xx_timer_match);
10
    
11
    /* check whether this timer is configured as system timer */
12
    if(of_property_read_bool(node, "system-timer"))
13
    {
14
      /* system-timer property is set. use this as the system timer. */
15
      printk(KERN_ALERT "System timer is %s\n", node->full_name);
16
      
17
      /* determine the base address */
18
      if(of_address_to_resource(node, 0, &res))
19
      {
20
        panic("Cannot determine timer base address");
21
      }
22
23
      /* check the base address */
24
      if(res.start == 0)
25
      {
26
        /* resource is invalid */
27
        panic("%s: unable to map timer registers\n", node->full_name);
28
      }
29
      
30
      /* timer rate is 100 per sec */
31
      setup_sched_clock(timer_read, 32, 100);
32
      
33
      /* setup the mmio clock source */
34
      clocksource_mmio_init((void*)(res.start + TCR_OFFSET), node->name,
35
        100, 300, 32, clocksource_mmio_readl_up);
36
      
37
      /* get the hardware irq number */
38
      irq = irq_of_parse_and_map(node, 0);
39
      if(irq <= 0)
40
      {
41
        panic("Can't parse IRQ");
42
      }
43
      
44
      /* allocate space for the internal variables */
45
      timer = kzalloc(sizeof(struct lpc_timer), GFP_KERNEL);
46
      if(timer == NULL)
47
      {
48
        panic("Can't allocate timer struct\n");
49
      }
50
      
51
      /* set all register addresses */
52
      timer->control = (void*)(res.start + TCR_OFFSET);
53
      timer->intreg = (void*)(res.start + IR_OFFSET);
54
      timer->match = (void*)(res.start + MR0_OFFSET);
55
      timer->matchcontrol = (void*)(res.start + MCR_OFFSET);
56
      
57
      /* set the irq properties */
58
      timer->act.name = node->full_name;
59
      timer->act.flags = IRQF_TIMER | IRQF_SHARED;
60
      timer->act.dev_id = timer;
61
      timer->act.handler = timer_handler;
62
      
63
      /* set the event properties */
64
      timer->evt.name = node->name;
65
      timer->evt.rating = 300;
66
      timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
67
      timer->evt.set_mode = set_timer_mode;
68
      timer->evt.set_next_event = set_timer_event;
69
      timer->evt.cpumask = cpumask_of(0);
70
71
      /* setup the interrupt */
72
      if(setup_irq(irq, &timer->act) != 0)
73
      {
74
        panic("Cannot setup the timer IRQ");
75
      }
76
      
77
      /* configure the clock events */
78
      clockevents_config_and_register(&timer->evt, 100, 0xf, 0xffffffff);
79
      
80
      printk(KERN_ALERT "System timer %s (IRQ %d)\n", node->full_name, irq);
81
      
82
      return;
83
      
84
      
85
      
86
      
87
      /*T0TCR &= ~0x01;
88
      T0MR0 = 72000-1;
89
      T0MCR |= 0x03;
90
      setup_irq(4, &act);
91
      VICIntEnable |= (1u << 4);
92
      T0IR = 0x01;
93
      T0TCR = 0x02;
94
      T0TCR = 0x01;
95
      FIO2DIR |= 1;*/
96
    }
97
  } while(node != NULL);
98
  
99
  /* check whether a node was found */
100
  if(node == NULL)
101
  {
102
    panic("No system timer found");
103
  }
104
}

Testen konnte ich es noch nicht, aber es erscheint mir nun alles relativ 
plausibel. Was ich damit machen will - im Device Tree habe ich bei einem 
Timer einen Property "system-timer;" erstellt. Denjenigen Timer suche 
ich heraus, und benutze den dann. Dann ermittle ich aus dem Device Tree 
die Basisadresse des Timers, und lege Pointer auf die einzelnen Register 
in der Struktur timer ab (bei /* set all register addresses */).

Jetzt habe ich hierzu noch ein paar Fragen:
1. zu welchem Zeitpunkt soll ich den Timer wirklich initialisieren, 
sodass der auch im Stande ist, Interrupts zu generieren? Ich habe mal 
unten als Kommentar eingefügt, an welcher Stelle ich das machen würde. 
Sicher bin ich mir aber nicht; im Code für den BCM2835 (bcm2835_timer.c) 
kann ich nicht erkennen, wo da der Timer wirklich gestartet wird.

2. setup_sched_clock(): wozu genau braucht man das? verstehe ich das 
richtig, dass der Scheduler die dort angegebene Callbackfunktion 
aufruft, und so die verstrichene Zeit zu bestimmen? rate (letzter 
Parameter) ist die Anzahl der Timerinterrupts pro Sekunde?

3. clocksource_mmio_init(): sieht für mich irgendwie nach dem selben aus 
wie setup_sched_clock(). Wozu dient das?

Hoffe du hilfst mir weiter. :-)
Vielen Dank & Gruss

von Martin (Gast)


Lesenswert?

Portierst/entwickelst Du für einen NXP Prozessor?
Darf man Fragen für welchen?

von Hans Ulli K. (Gast)


Lesenswert?

Ich antworte erstmal schnell auf die Fragen ...
Der Rest folgt dann noch heute Abend

Tobias Plüss schrieb:
> Jetzt habe ich hierzu noch ein paar Fragen:
> 1. zu welchem Zeitpunkt soll ich den Timer wirklich initialisieren,
> sodass der auch im Stande ist, Interrupts zu generieren? Ich habe mal
> unten als Kommentar eingefügt, an welcher Stelle ich das machen würde.
> Sicher bin ich mir aber nicht; im Code für den BCM2835 (bcm2835_timer.c)
> kann ich nicht erkennen, wo da der Timer wirklich gestartet wird.

Das müsste normalerweise noch dem init des Kernels ablaufen.
Also nach CPU, MMU init, davor kommt noch die Meldung mit BogoMips.

Der Timer wird ja auch benutzt um den internen udelay zu kalibieren, 
diesen braucht auch zum Teil beim Device Init.

>
> 2. setup_sched_clock(): wozu genau braucht man das? verstehe ich das
> richtig, dass der Scheduler die dort angegebene Callbackfunktion
> aufruft, und so die verstrichene Zeit zu bestimmen? rate (letzter
> Parameter) ist die Anzahl der Timerinterrupts pro Sekunde?
>

Ja.
Soweit ich das auf ich schnelle in verschiedene Sourcen Lese korreliert 
das mit der Anzahl der Zyklen bis zum "Timerüberlauf" siehe Timer in
arch/arm/mach-sa1100/time.c
obwohl ich eigentlich zu den Sourcen in
arch/arm/mach-lpc32xx/timer.c
tendiere, das ist näher am LPC24XX.
Ich würde da ggf. einen Mix von allen dreien machen


> 3. clocksource_mmio_init(): sieht für mich irgendwie nach dem selben aus
> wie setup_sched_clock(). Wozu dient das?
>

Aus dem Kopf wusste ich es auch nicht aber
gitk drivers/clocksource/mmio.c
gibt schon mal den Anfang
1
Autor: Russell King <rmk+kernel@arm.linux.org.uk>  2011-05-08 15:06:52
2
Eintragender: Russell King <rmk+kernel@arm.linux.org.uk>  2011-05-23 19:04:51
3
Zweig: master and many more (566)
4
Folgt auf: master-2011-05-16, v2.6.39
5
Vorgänger von: v3.0-rc1
6
7
    clocksource: add common mmio clocksource
8
    
9
    Add a generic mmio clocksource, covering both 32-bit and 16-bit register
10
    access sizes, for up or down counters.  This can be used to easily
11
    create clocksources for simple counter-based implementations.

So jetzt muss ich erstmal sehen was
readl_relaxed()
heist, readl usw. kenne ich ja schon ...

von Hans Ulli K. (Gast)


Lesenswert?

Martin schrieb:
> Portierst/entwickelst Du für einen NXP Prozessor?
> Darf man Fragen für welchen?

Ich Tippe mal auf das Bootlog
Machine: LPC24XX SoC (Flattened Device Tree), model: LPC2468 Board

von Tobias P. (hubertus)


Lesenswert?

Hallo Hans Ulli,

es gibt News. Der Kernel läuft nun bis hier:
1
Booting Linux on physical CPU 0x0
2
Linux version 3.8.5+ (tobias@zap) (gcc version 4.7.3 20130312 (release) [ARM/emb
3
edded-4_7-branch revision 196615] (GNU Tools for ARM Embedded Processors) ) #204
4
 Thu May 23 23:50:22 CEST 2013
5
CPU: ARM7TDMI [41007700] revision 0 (ARMv3), cr=00000000
6
CPU: VIVT data cache, VIVT instruction cache
7
Machine: LPC24XX SoC (Flattened Device Tree), model: LPC2468 Board
8
bootconsole [earlycon0] enabled
9
init early
10
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 12192
11
Kernel command line: earlyprintk console=ttyS0
12
PID hash table entries: 256 (order: -2, 1024 bytes)
13
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
14
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
15
Memory: 48MB = 48MB total
16
Memory: 48432k/48432k available, 720k reserved, 0K highmem
17
Virtual kernel memory layout:
18
    vector  : 0xa0000000 - 0xa0001000   (   4 kB)
19
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
20
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
21
    lowmem  : 0xa0000000 - 0xa3000000   (  48 MB)
22
      .text : 0x80000000 - 0x80124024   (1169 kB)
23
      .init : 0xa000a000 - 0xa000d000   (  12 kB)
24
      .data : 0xa0008000 - 0xa001c7e0   (  82 kB)
25
       .bss : 0xa001c7e0 - 0xa00437b8   ( 156 kB)
26
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
27
NR_IRQS:16 nr_irqs:32 32
28
alloc vic
29
OF: no ranges; cannot translate
30
calc vic reg addr
31
1System timer is /soc/timer@E0004000
32
OF: no ranges; cannot translate
33
vic_xlate: intspec[0] = 4, intspec[1] = 0.
34
irq of parse done 
35
1System timer /soc/timer@E0004000 (IRQ 36)
36
1Initialising system timer
37
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 4294967286ms
38
Console: colour dummy device 80x30
39
Calibrating delay loop... 94.61 BogoMIPS (lpj=473088)
40
pid_max: default: 32768 minimum: 301
41
Mount-cache hash table entries: 512
42
Internal error: Oops - undefined instruction: 0 [#1] ARM
43
CPU: 0    Not tainted  (3.8.5+ #204)
44
PC is at 0xfffffffc
45
LR is at 0xa001c958
46
pc : [<fffffffc>]    lr : [<a001c958>]    psr: 60000053
47
sp : a001c958  ip : 00000000  fp : a2c29f04
48
r10: 00000001  r9 : 00000000  r8 : a2c1da0c
49
r7 : 0000000f  r6 : 000080d0  r5 : a2c01400  r4 : a2c25e00
50
r3 : 00000000  r2 : 00000000  r1 : 00000000  r0 : a2c26000
51
Flags: nZCv  IRQs on  FIQs off  Mode SVC_32  ISA ARM  Segment kernel
52
Process (null) (pid: -481230803, stack limit = 0xe24ff43e)

Das initialisieren des Timers funktioniert, der Interrupt wird 
aufgerufen. Soweit klappt es also! aber mit dem Clockevents oder so 
scheint noch was nicht gut zu sein - das muss ich morgen rausfinden.

Gruss

von Tobias P. (hubertus)


Lesenswert?

Hallo zusammen,

ich bin zwischenzeitlich etwas weiter gekommen. Mein Bootloag sieht 
jetzt so aus:
1
Booting Linux on physical CPU 0x0
2
Linux version 3.8.5+ (tobias@zap) (gcc version 4.7.3 20130312 (release) [ARM/emb
3
edded-4_7-branch revision 196615] (GNU Tools for ARM Embedded Processors) ) #247
4
 Sun May 26 14:56:20 CEST 2013
5
CPU: ARM7TDMI [41007700] revision 0 (ARMv3), cr=00000000
6
CPU: VIVT data cache, VIVT instruction cache
7
Machine: LPC24XX SoC (Flattened Device Tree), model: LPC2468 Board
8
bootconsole [earlycon0] enabled
9
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 12192
10
Kernel command line: earlyprintk console=/dev/console
11
PID hash table entries: 256 (order: -2, 1024 bytes)
12
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
13
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
14
Memory: 48MB = 48MB total
15
Memory: 48432k/48432k available, 720k reserved, 0K highmem
16
Virtual kernel memory layout:
17
    vector  : 0xa0000000 - 0xa0001000   (   4 kB)
18
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
19
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
20
    lowmem  : 0xa0000000 - 0xa3000000   (  48 MB)
21
      .text : 0x80000000 - 0x80123024   (1165 kB)
22
      .init : 0xa000a000 - 0xa000d000   (  12 kB)
23
      .data : 0xa0008000 - 0xa001c800   (  82 kB)
24
       .bss : 0xa001c800 - 0xa00437e4   ( 156 kB)
25
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
26
NR_IRQS:16 nr_irqs:32 32
27
System timer is /soc/timer@E0004000
28
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 4294967286ms
29
Console: colour dummy device 80x30
30
Calibrating delay loop... 55.29 BogoMIPS (lpj=276480)
31
pid_max: default: 32768 minimum: 301
32
Mount-cache hash table entries: 512
33
bio: create slab <bio-0> at 0
34
io scheduler noop registered (default)
35
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
36
brd: module loaded
37
turn off boot console earlycon0

Ich hab die Busybox compiliert und ein root file system kreiert. Das 
wird anscheinend auch geladen, aber man sieht es nicht, weil der UART 
nicht zu funktionieren scheint :-) warum auch immer. Was müsste man da 
wohl noch tun?

BTW, was ist das Modul "brd" ?

Gruss

von Tobi (Gast)


Lesenswert?

Moin,

anstatt ständig Kernel Logs zu posten wäre es ganz schön zu wissen was 
du gemacht hast um es zum Laufen zu bringen. Quasi für die Nachwelt.

Gruss,
Tobi

von Hans Ulli K. (Gast)


Lesenswert?

Tobias Plüss schrieb:
> BTW, was ist das Modul "brd" ?
>

einfach mal nach grepen ...
1
elektroman@X200s ~/linux-master $ find -name 'brd*'
2
./drivers/block/brd.c
3
./drivers/staging/tidspbridge/include/dspbridge/brddefs.h

Und dann ...
1
elektroman@X200s ~/linux-master $ grep brd.o drivers/block/Makefile 
2
obj-$(CONFIG_BLK_DEV_RAM)  += brd.o
Das ist der Treiber die RAMDISK.

Wenn ich das Log richtig lese (wobei mir irgendwie noch einige Zeilen 
fehlen)
ist das RootFS schon da, weil ja das brd (RAMDISK_DEV) geladen wird.

von Hans Ulli K. (Gast)


Lesenswert?

Tobi schrieb:
> Moin,
>
> anstatt ständig Kernel Logs zu posten wäre es ganz schön zu wissen was
> du gemacht hast um es zum Laufen zu bringen. Quasi für die Nachwelt.

gibt es denn überhaupt Interesse ??

Der Tobias Plüss ist erst am Anfang der Anfang der Kernelentwicklung ...

Als Anfang würde ich erst mal dazu raten ein RootFS mal selber zu bauen 
und dann mal auf einem Zielsystem ARM oder MIPS per chroot zu starten 
...

ggf. würde ich auch mal zu Gentoo/Sabayon raten, da es dort eine sehr 
gute Unterstüzung für CrossCompiler Development eingebaut ist.

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.