Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

Del 3: NĂ€stan laddar Linux frĂ„n SD-kort till RocketChip I den föregĂ„ende delen en har blivit implementerad en mer eller mindre fungerande minneskontroller, nĂ€rmare bestĂ€mt en omslag runt IP Core frĂ„n Quartus, som fungerar som en adapter till TileLink. Idag i artikeln "Portera RocketChip till ett mindre kĂ€nt kinesiskt kort med Cyclone" fĂ„r du se en fungerande konsol. Processen drog ut pĂ„ tiden: jag trodde att jag snabbt skulle kunna starta Linux och gĂ„ vidare, men sĂ„ blev det inte. I denna del föreslĂ„r jag att vi tittar pĂ„ processen för att starta U-Boot, BBL och de trevande försöken att fĂ„ Linux-kĂ€rnan att initieras. Men det finns en konsol – en U-Boot-konsol, som Ă€r ganska avancerad och har mycket av det du förvĂ€ntar dig frĂ„n en fullfjĂ€drad konsol.

I hÄrdvarudelen tillkommer ett SD-kort som Àr anslutet via SPI-grÀnssnitt, samt UART. I mjukvarudelen kommer BootROM att bytas ut mot xip till sdboot och faktiskt lÀggas till följande laddningssteg (pÄ SD-kortet).

FörbÀttring av hÄrdvarudelen

SÄ, uppgiften: vi behöver gÄ över till ett "stort" kÀrn och ansluta UART (frÄn Raspberry) och SD-adapter (en viss platta frÄn Catalex med sex stift: GND, VCC, MISO, MOSI, SCK, CS).

I princip var allt ganska enkelt. Men innan jag insĂ„g det, blev jag lite kastad fram och tillbaka: efter förra gĂ„ngen beslutade jag att det Ă„terigen var dags att bara blanda in i System nĂ„got som HasPeripheryUART (och i implementeringen dĂ€rmed), samma för SD-kortet – och allt skulle vara klart. Sedan beslöt jag mig för att se hur det var implementerat i en "seriös" design. SĂ„, vad har vi hĂ€r av seriöst? Arty verkar inte passa – det Ă„terstĂ„r monstret unleahshed.DevKitConfigs. Och plötsligt upptĂ€ckte jag att det fanns överallt nĂ„gra overlay, som lĂ€ggs till via parameternycklar. Jag misstĂ€nker att detta nog Ă€r mycket flexibelt och konfigurerbart, men jag skulle vilja ha nĂ„got för att starta Ă„tminstone... Har ni nĂ„got liknande, men bara enklare och mer lurt?.. DĂ€r stötte jag pĂ„ vera.iofpga.FPGAChip för Microsemi FPGA och jag punkterade pĂ„ citat och försökte göra min egen implementation genom analogi, eftersom hĂ€r finns mer eller mindre hela "systemkortets" layout i en fil.

Det visade sig verkligen att man bara behövde lÀgga till i System.scala raderna

class System(implicit p: Parameters) extends RocketSubsystem
...
  with HasPeripherySPI
  with HasPeripheryUART
...
{
  val tlclock = new FixedClockResource("tlclk", p(DevKitFPGAFrequencyKey))
  ...
}

class SystemModule[+L <: System](_outer: L)
  extends RocketSubsystemModuleImp(_outer)
...
    with HasPeripheryUARTModuleImp
    with HasPeripheryGPIOModuleImp
...

Rad i klassens kropp System lĂ€gger till information om frekvensen som denna del av vĂ„r SoC arbetar vid, i dts-filen. SĂ„ vitt jag förstĂ„r, Ă€r DTS/DTB en statisk motsvarighet till plug-and-play-teknologi för inbyggda enheter: dtrĂ€dets dts-beskrivning kompileras till en binĂ€r dtb-fil och överförs av bootloadern till kĂ€rnan, sĂ„ att den kan stĂ€lla in hĂ„rdvaran korrekt. Intressant nog, utan raden med tlclock syntetiseras allt bra, men att kompilera BootROM (lĂ„t mig pĂ„minna, nu kommer det att bli sdboot) gĂ„r inte — under kompileringen parser den dts-filen och skapar en header med makrot TL_CLK, som gör att den kan stĂ€lla in frekvensdelarna för externa grĂ€nssnitt korrekt.

Det kommer ocksÄ att krÀvas lite justering av "layouten":

Platform.scala:

class PlatformIO(implicit val p: Parameters) extends Bundle {

...

  \/\/ UART
  io.uart_tx := sys.uart(0).txd
  sys.uart(0).rxd := RegNext(RegNext(io.uart_rx))

  \/\/ SD-kort
  io.sd_cs := sys.spi(0).cs(0)
  io.sd_sck := sys.spi(0).sck
  io.sd_mosi := sys.spi(0).dq(0).o
  sys.spi(0).dq(0).i := false.B
  sys.spi(0).dq(1).i := RegNext(RegNext(io.sd_miso))
  sys.spi(0).dq(2).i := false.B
  sys.spi(0).dq(3).i := false.B
}

Registreringskedjor har, Ă€rligt talat, lagts till helt enkelt som en analogi med vissa andra delar av den ursprungliga koden. De ska troligen skydda mot metastabilitet. Kanske finns det redan nĂ„got skydd i vissa block, men först vill jag kunna starta Ă„tminstone "pĂ„ en kvalitetsnivĂ„". En mer intressant frĂ„ga för mig Ă€r — varför MISO och MOSI hĂ€nger pĂ„ olika dq? ОтĐČДта я ĐżĐŸĐșа таĐș Đž ĐœĐ” ĐœĐ°ŃˆŃ‘Đ», ĐœĐŸ, ĐżĐŸŃ…ĐŸĐ¶Đ”, ĐŸŃŃ‚Đ°Đ»ŃŒĐœĐŸĐč ĐșĐŸĐŽ рассчотыĐČаДт ĐžĐŒĐ”ĐœĐœĐŸ ĐœĐ° таĐșĐŸĐ” ĐżĐŸĐŽĐșĐ»ŃŽŃ‡Đ”ĐœĐžĐ”.

Fysiskt har jag helt enkelt tilldelat utgÄngarna i designen till lediga kontakter pÄ kontaktdonen och flyttat hopkopplaren för spÀnningsval till 3.3V.

SD-adapter

Översikt uppifrĂ„n:

Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

Översikt nedifrĂ„n:

Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

Debuggning av programvaran: verktyg

För att börja, lÄt oss diskutera de tillgÀngliga felsökningsverktygen och deras begrÀnsningar.

Minicom

Först mĂ„ste vi pĂ„ nĂ„got sĂ€tt lĂ€sa vad bootloadern och kĂ€rnan skriver ut. För detta i Linux (i detta fall — pĂ„ den som körs pĂ„ RaspberryPi) behöver vi programmet Minicom. Generellt sett, vilket som helst program för arbete med seriell port fungerar.

Observera att nĂ€r du startar, mĂ„ste du ange portens enhetsnamn som -D \/dev\/ttyS0 — efter alternativet , kommer den att lĂ€gga den senaste blocken av masterkedjan i den:. Och den viktigaste informationen: för att avsluta, anvĂ€nd Ctrl-A, X. Jag hade faktiskt en gĂ„ng dĂ„ denna kombination inte fungerade — dĂ„ kan du bara frĂ„n en annan SSH-session sĂ€ga killall -KILL minicom.

Det finns ocksÄ en annan egenskap. Specifikt pÄ Raspberry Pi finns det tvÄ UART:ar, och bÄda portar kan redan vara anpassade för nÄgot: en för Bluetooth, medan den andra som standard visar kÀrnans konsol. Som tur Àr kan detta beteende omkonfigureras. enligt den hÀr manualen..

MinnesÄterstÀllning.

Vid felsökning har jag ibland behövt för att verifiera hypotesen. ladda bootloadern (ursÀkta) i RAM direkt frÄn vÀrden. Kanske kan det göras direkt frÄn GDB, men jag valde den enklare vÀgen: kopierade den nödvÀndiga filen till Raspberry och vidarebefordrade Àven port 4444 via SSH (telnet frÄn OpenOCD) och anvÀnde kommandot. load_image. NÀr du kör det verkar det som om allt har frusit, men i sjÀlva verket «det sover inte, det blinkar bara lÄngsamt»: det laddar filen, det gör det bara med en hastighet av ett par kilobytar per sekund.

Egenskaper hos att placera breakpoints.

MÄnga kanske aldrig har tÀnkt pÄ detta vid felsökning av vanliga program, men breakpoints sÀtts inte alltid hÄrdvarumÀssigt. Ibland innebÀr det att tillfÀlligt skriva en sÀrskild instruktion pÄ rÀtt plats. direkt i maskinkoden.Till exempel fungerade det sÄ med den standardkommandot b i GDB. HÀr Àr vad som följer av detta:

  • du kan inte sĂ€tta en punkt inne i BootROM eftersom ROM
  • det gĂ„r att sĂ€tta en breakpoint pĂ„ koden som laddas in i RAM frĂ„n SD-kortet, men du mĂ„ste vĂ€nta tills den har laddats. Annars kommer vi inte att skriva över en bit av koden, utan bootloadern kommer att skriva över vĂ„r breakpoint.

Jag Àr sÀker pÄ att man tydligt kan be om att anvÀnda hÄrdvarubaserade breakpoints, men de Àr ÀndÄ begrÀnsade i antal.

Snabb omkoppling av BootROM.

I det inledande skedet av felsökningen finns ofta en önskan att fixa BootROM och försöka igen. Men det finns ett problem: BootROM Àr en del av designen som laddas in i FPGA:n, och dess syntes tar nÄgra minuter (och detta efter nÀstan omedelbar kompilering av sjÀlva BootROM-avbildningen frÄn C och assembler...). Som tur Àr Àr allt faktiskt mycket snabbare: sekvensen av ÄtgÀrder Àr sÄdan:

  • Ă„tergenerera bootrom.mif (jag bytte till MIF istĂ€llet för HEX, eftersom jag alltid hade problem med HEX, medan MIF Ă€r det ursprungliga ALTERA-formatet)
  • i Quartus sĂ€ger Bearbetning -> Uppdatera minnesinitialiseringsfilen.
  • i punkten Assembler (i vĂ€nstra kolumnen Uppgifter) ge kommandot Starta om igen.

Allt som allt - ett par tiotal sekunder.

Förberedelse av SD-kort.

HÀr Àr allt relativt enkelt, men du behöver ha tÄlamod och ungefÀr 14Gb diskutrymme:

git clone https://github.com/sifive/freedom-u-sdk
git submodule update --recursive --init
make

DÀrefter behöver du sÀtta i ett rent, det vill sÀga, utan nÄgot viktigt, SD-kort och utföra

sudo make DISK=/dev/sdX format-boot-loader


 dĂ€r sdX — enheten som tilldelats kortet. VARNING: Data pĂ„ kortet kommer att raderas, skrivas över och helt enkelt försvinna! Det Ă€r nog ingen bra idĂ© att göra hela byggprocessen som sudo, för dĂ„ kommer alla byggartefakter att tillhöra root, och bygget mĂ„ste göras som sudo konstant.

Resultatet Àr ett kort som Àr partitionerat i GPT med fyra partitioner, dÀr en av dem har FAT med uEnv.txt och en bootbar bild i FIT-format (den innehÄller flera delbilder, var och en med sin laddningsadress), den andra partitionen Àr tom och avsedd att formateras i Ext4 för Linux. De andra tvÄ partitionerna Àr mysteriska: pÄ en lagrar U-Boot (dess förskjutning Àr, sÄvitt jag förstÄr, kodad i BootROM), pÄ den andra verkar dess miljövariabler bo, men jag anvÀnder dem inte Àn.

NivÄ ett, BootROM

Det finns ett ordsprĂ„k som sĂ€ger: "Om det finns dans kring trummor i programmering, sĂ„ Ă€r det Ă€ven med brandslĂ€ckare i elektronik". Det handlar inte ens om att jag en gĂ„ng nĂ€stan brĂ€nde kortet, eftersom jag trodde att "NĂ„vĂ€l, GND Ă€r ju samma som lĂ„g nivĂ„" (ett motstĂ„nd skulle uppenbarligen inte ha skadat...) Det handlar snarare om att om hĂ€nderna inte vĂ€xer frĂ„n rĂ€tt stĂ€lle, fortsĂ€tter elektroniken att överraska: nĂ€r jag lödde kontakten pĂ„ kortet, kunde jag inte fĂ„ kontakterna att löda ordentligt — pĂ„ videoklipp visar de hur lödtennet bara flyter ut över hela anslutningen, bara sĂ€tt lödkolven pĂ„, men hos mig "fastnade" det hur som helst. Ja, kanske lödtennet inte passade temperaturen pĂ„ lödkolven, kanske nĂ„got annat
 I allmĂ€nhet, nĂ€r jag sĂ„g att jag hade ett dussin kontakter, gav jag upp och började felsöka. Och hĂ€r började det mystiska: jag kopplade RX/TX frĂ„n UART:en, laddade firmware — det stĂ„r

INIT
CMD0
ERROR

NĂ„vĂ€l, allt Ă€r logiskt — jag hade inte kopplat in SD-kortmodulen. Jag Ă„tgĂ€rdar situationen, laddar firmware... Och tystnad... Vad jag Ă€n tĂ€nkte pĂ„, men problemet var enkelt: en av benen pĂ„ modulen behövde kopplas till VCC. I mitt fall stöddes 5V för strömförsörjning av modulen, sĂ„ jag, utan att tveka, kopplade den trĂ„d som strĂ€ckte sig frĂ„n modulen till motsatt sida av kortet. Som resultat blev den dĂ„ligt lödda kontakten sned. bara förlorade kontakt med UART. facepalm.jpg I allmĂ€nhet, "en dĂ„lig skalle ger inte benen ro", och sneda hĂ€nder — skallen...

Till slut sÄg jag det lÀngtade i Minicom

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

Dessutom rör sig laddningsindikatorn. Det pÄminner mig om skoltiden och den lÄngsamma laddningen av MinuetOS frÄn disketten. Det enda som saknas Àr att diskettstationen inte skrapar.

Problemet Àr att efter meddelandet BOOT hÀnder inget. Det var dags att koppla upp via OpenOCD pÄ Raspberry, med GDB pÄ vÀrden och se vad det handlar om.

För det första visade anslutningen med GDB genast att $pc (programrĂ€knare, adressen för den aktuella instruktionen) flyger ivĂ€g till 0x0 — troligen hĂ€nder detta efter flera fel. SĂ„ snart som meddelandet visas BOOT lĂ€gger vi till en oĂ€ndlig loop. Det kommer att försena det en stund...

diff --git a/bootrom/sdboot/sd.c b/bootrom/sdboot/sd.c
index c6b5ede..bca1b7f 100644
--- a/bootrom/sdboot/sd.c
+++ b/bootrom/sdboot/sd.c
@@ -224,6 +224,8 @@ int main(void)

        kputs("BOOT");

+    while(*(volatile char *)0x10000){}
+
        __asm__ __volatile__ ("fence.i" : : : "memory");
        return 0;
 }

En sÄ hÀr listig kod anvÀnds "för tillförlitlighet": jag har hört nÄgonstans att oÀndliga loopar kan vara Undefined Behavior, och hÀr lÀr kompilatorn knappast förstÄ. 0x10000 Jag pÄminner om att BootROM finns.

Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

Man skulle kunna förvĂ€nta sig, vad förvĂ€ntar man sig — en hĂ„rd inbyggd lösning, vad Ă€r det för kĂ€llkod hĂ€r. Men i den artikeln debatten var att författa C-kod... Kreks-feks-peks:

(gdb) file builds/zeowaa-e115/sdboot.elf
Ett program debuggas redan.
Är du sĂ€ker pĂ„ att du vill Ă€ndra filen? (y eller n) y
LÀser symboler frÄn builds/zeowaa-e115/sdboot.elf... klart.

Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

Det behöver laddas inte MIF-filen eller bin, utan den ursprungliga versionen i ELF-format.

Nu kan man med en viss chans gissa adressen dÀr exekveringen fortsÀtter (detta Àr ytterligare en anledning till varför kompilatorn inte borde ha gissat att loopen Àr oÀndlig). Kommandot

set variable $pc=0xADDR

tillĂ„ter att Ă€ndra registrets vĂ€rde pĂ„ sprĂ„ng (i detta fall — adressen för den aktuella instruktionen). Med detta kan man ocksĂ„ Ă€ndra vĂ€rden som sparats i minnet (och minnesmĂ€ppade register).

Till slut kom jag fram till slutsatsen (Àr osÀker pÄ om den Àr korrekt) att vi har "sd-kortavbilden av det systemet", och man ska inte gÄ till början av de laddade data utan till 0x89800 nÄgra byte lÀngre:

diff --git a/bootrom/sdboot/head.S b/bootrom/sdboot/head.S
index 14fa740..2a6c944 100644
--- a/bootrom/sdboot/head.S
+++ b/bootrom/sdboot/head.S
@@ -13,7 +13,7 @@ _prog_start:
   smp_resume(s1, s2)
   csrr a0, mhartid
   la a1, dtb
-  li s1, PAYLOAD_DEST
+  li s1, (PAYLOAD_DEST + 0x89800)
   jr s1

   .section .rodata

Det kan ocksĂ„ ha pĂ„verkats av att jag, utan en onödig 4Gb-kort till hands, tog ett 2Gb-kort och bytte ut det i Makefile med en del trial and error. DEMO_END=11718750 till DEMO_END=3078900 (sök inte efter mening i det specifika vĂ€rdet — det finns inget, det Ă€r bara sĂ„ att bilden nu fĂ„r plats pĂ„ kortet).

NivÄ tvÄ, U-Boot

Nu "faller" vi fortfarande, men har redan nÄtt adressen 0x0000000080089a84. HÀr mÄste jag erkÀnna: faktiskt gÄr redogörelsen inte "med alla stopp", utan skrivs delvis "efterÄt", sÄ hÀr har jag redan lyckats lÀgga till den rÀtta dtb-filen frÄn vÄr SoC, och rÀttat i instÀllningarna. HiFive_U-Boot variabel CONFIG_SYS_TEXT_BASE=0x80089800 (i stÀllet för 0x08000000), sÄ att laddningsadressen överensstÀmmer med den faktiska. Nu laddar vi en karta pÄ nÀsta nivÄ med en annan bild:

(gdb) file ..\/freedom-u-sdk\/work\/HiFive_U-Boot\/u-boot
(gdb) tui en

Och vi ser:

   │304     *                                               │
   │305      * fĂ€lla intĂ€de                                    │
   │306      *\/                                              │
   │307     trap_entry:                                      │
   │308         addi sp, sp, -32*REGBYTES                    │
  >│309         SREG x1, 1*REGBYTES(sp)                      │
   │310         SREG x2, 2*REGBYTES(sp)                      │
   │311         SREG x3, 3*REGBYTES(sp)                      │

Vi hoppar mellan raderna 308 och 309. Och inte helt ovÀntat, med tanke pÄ att i $sp ligger vÀrdet 0xfffffffe31cdc0a0. TyvÀrr "springer" det Àven bort pÄ grund av raden 307. SÄ vi provar att sÀtta en stopppunkt pÄ trap_entry, och sedan ÄtergÄ till 0x80089800 (U-Boots intrÀdespunkt), och hoppas att det inte krÀver korrekt instÀllda register innan övergÄngen... Det verkar fungera:

(gdb) b trap_entry
Breakpoint 1 at 0x80089a80: file \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S, line 308.
(gdb) set variable $pc=0x80089800
(gdb) c
FortsÀtter.

Breakpoint 1, trap_entry () at \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S:308
(gdb) p\/x $sp
$4 = 0x81cf950

En ganska dÄlig stackpekare, fÄr man sÀga: den pekar faktiskt bortom RAM (om vi inte redan har adressöversÀttning, men vi hoppas pÄ det enkla alternativet).

Vi provar att byta pekaren till 0x881cf950. Slutligen kommer vi fram till att handle_trap anropas och anropas, medan vi gÄr in i _exit_trap med argumentet epc=2148315240 (i decimalform):

(gdb) x/10i 2148315240
   0x800cb068 :     lbu     a4,0(a5)
   0x800cb06c :     bnez    a4,0x800cb078 
   0x800cb070 :     sub     a0,a5,a0
   0x800cb074 :     ret
   0x800cb078 :     addi    a5,a5,1
   0x800cb07c :     j       0x800cb064 
   0x800cb080 : addi    sp,sp,-32
   0x800cb084 :       sd      s0,16(sp)
   0x800cb088 :       sd      ra,24(sp)
   0x800cb08c :      li      s0,0

Vi sÀtter en breakpoint pÄ strnlen, fortsÀtter och ser:

(gdb) bt
#0 strnlen (s=s@entry=0x10060000 "", count=18446744073709551615) at lib/string.c:283
#1 0x00000000800cc14c in string (buf=buf@entry=0x881cbd4c "", end=end@entry=0x881cc15c "", s=0x10060000 "", field_width=, precision=, flags=) at lib/vsprintf.c:265
#2 0x00000000800cc63c in vsnprintf_internal (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=0x800d446e "s , epc x , ra lxn", fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=0x881cc1a0,
 args@entry=0x881cc188) at lib/vsprintf.c:619
#3 0x00000000800cca54 in vsnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) at lib/vsprintf.c:710
#4 0x00000000800cca68 in vscnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) at lib/vsprintf.c:717
#5 0x00000000800ccb50 in printf (fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn") at lib/vsprintf.c:792
#6 0x000000008008a9f0 in _exit_trap (regs=, epc=2148315240, code=) at arch/riscv/lib/interrupts.c:92
#7 handle_trap (mcause=, epc=, regs=) at arch/riscv/lib/interrupts.c:55
#8 0x0000000080089b10 in trap_entry () at /hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot/arch/riscv/cpu/HiFive/start.S:343
Backtrace stopped: frame did not save the PC

Det verkar som _exit_trap vill ge debuginformation om den intrÀffade undantaget, men lyckas inte. SÄ, nÄgot visar Äterigen inte kÀllorna. set directories ../freedom-u-sdk/HiFive_U-Boot/ O! Nu visas de!

LÄt oss starta en gÄng till och se pÄ stackspÄret för att hitta orsaken till det ursprungliga problemet som orsakade det första felet (mcause == 5). Om jag förstÄtt rÀtt det som stÄr hÀr pÄ sidan 37, sÄ innebÀr detta undantag Ladda Ätkomstfel. Anledningen verkar vara att hÀr

arch/riscv/cpu/HiFive/start.S:

call_board_init_f:
    li  t0, -16
    li  t1, CONFIG_SYS_INIT_SP_ADDR
    and sp, t1, t0  /* tvinga 16-byte justering */

#ifdef CONFIG_DEBUG_UART
    jal debug_uart_init
#endif

call_board_init_f_0:
    mv  a0, sp
    jal board_init_f_alloc_reserve
    mv  sp, a0
    jal board_init_f_init_reserve

    mv  a0, zero /* a0 <--- boot_flags = 0 */
    la t5, board_init_f
    jr t5       /* hoppa till board_init_f() */

$sp har det felaktiga vĂ€rdet, och inne i board_init_f_init_reserve uppstĂ„r ett fel. Det verkar som att skulden ligger hos: variabeln med det tydliga namnet CONFIG_SYS_INIT_SP_ADDR. Den definieras i filen HiFive_U-Boot/include/configs/HiFive-U540.hVid nĂ„got tillfĂ€lle övervĂ€gde jag till och med om det vore enklare att justera processorn istĂ€llet för att finjustera bootloadern — men sen insĂ„g jag att det mer liknade ett artefakt frĂ„n ofullstĂ€ndiga instĂ€llningar för en annan minneskonfiguration, och man kan försöka göra sĂ„ hĂ€r:#if 0-

diff --git a/include/configs/HiFive-U540.h b/include/configs/HiFive-U540.h
index ca89383..245542c 100644
--- a/include/configs/HiFive-U540.h
+++ b/include/configs/HiFive-U540.h
@@ -65,12 +65,9 @@
 #define CONFIG_SYS_SDRAM_BASE  PHYS_SDRAM_0
 #endif
 #if 1
-
 #define CONFIG_NR_DRAM_BANKS 1
+#define CONFIG_NR_DRAM_BANKS   1
 #define PHYS_SDRAM_0   0x80000000              /* SDRAM Bank #1 */
-#define PHYS_SDRAM_1   
-       (PHYS_SDRAM_0 + PHYS_SDRAM_0_SIZE)      /* SDRAM Bank #2 */
-#define PHYS_SDRAM_0_SIZE      0x80000000      /* 2 GB */
-#define PHYS_SDRAM_1_SIZE      0x10000000      /* 256 MB */
+#define PHYS_SDRAM_0_SIZE      0x40000000      /* 1 GB */
 #define CONFIG_SYS_SDRAM_BASE  PHYS_SDRAM_0
 #endif
 /*
@@ -81,7 +78,7 @@
 #define CONSOLE_ARG                            "console=ttyS0,115200 "

 /* Init Stack Pointer */
-#define CONFIG_SYS_INIT_SP_ADDR                (0x08000000 + 0x001D0000 - 
+#define CONFIG_SYS_INIT_SP_ADDR                (0x80000000 + 0x001D0000 - 
                                        GENERATED_GBL_DATA_SIZE)

 #define CONFIG_SYS_LOAD_ADDR           0xa0000000      /* partway up SDRAM */

Vid nÄgot tillfÀlle nÄdde antalet workaround:er teknologiska fÀste en kritisk nivÄ. Efter att ha kÀmpat lite kom jag fram till att jag var tvungen att göra en korrekt portering till mitt styrenhet. För detta behöver jag kopiera och justera ett antal filer till vÄr konfiguration.

NÄvÀl, ungefÀr sÄ hÀr

trosinenko@trosinenko-pc:/hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot$ git show --name-status
commit 39cd67d59c16ac87b46b51ac1fb58f16f1eb1048 (HEAD -> zeowaa-1gb)
Author: Anatoly Trosinenko 
Date:   Tue Jul 2 17:13:16 2019 +0300

    Inledande stöd för Zeowaa A-E115FB kort

M       arch/riscv/Kconfig
A       arch/riscv/cpu/zeowaa-1gb/Makefile
A       arch/riscv/cpu/zeowaa-1gb/cpu.c
A       arch/riscv/cpu/zeowaa-1gb/start.S
A       arch/riscv/cpu/zeowaa-1gb/timer.c
A       arch/riscv/cpu/zeowaa-1gb/u-boot.lds
M       arch/riscv/dts/Makefile
A       arch/riscv/dts/zeowaa-1gb.dts
A       board/Zeowaa/zeowaa-1gb/Kconfig
A       board/Zeowaa/zeowaa-1gb/MAINTAINERS
A       board/Zeowaa/zeowaa-1gb/Makefile
A       board/Zeowaa/zeowaa-1gb/Zeowaa-A-E115FB.c
A       configs/zeowaa-1gb_defconfig
A       include/configs/zeowaa-1gb.h

Detaljer kan ses i förrÄdet.

Som det visade sig har registren för vissa enheter pĂ„ detta SiFive-kort olika adresser. Det visade sig ocksĂ„ att U-Boot konfigureras med det bekanta Kconfig-mekanismen frĂ„n Linux-kĂ€rnan — till exempel kan man kommandera make menuconfig, och framför dig kommer en anvĂ€ndarvĂ€nlig textbaserad grĂ€nssnitt med beskrivningar av parametrarna. ? Och sĂ„ vidare. SĂ„, genom att sĂ€tta ihop beskrivningarna av de tvĂ„ plattorna skapade jag en beskrivning av den tredje, slĂ€ppte allt pretentiöst kring PLL-omkonfigurationer (det verkar ha nĂ„got att göra med styrning frĂ„n vĂ€rddatorn via PCIe, men jag Ă€r inte sĂ€ker), fick jag en viss firmware som, under rĂ€tt förhĂ„llanden pĂ„ Mars, gav mig ett meddelande via UART om vilken commit-hash den var sammansatt frĂ„n, och hur mycket DRAM jag hade (men den informationen angav jag sjĂ€lv i headern).

TyvĂ€rr, efter detta slutade plattan vanligtvis att svara via processor JTAG, och att ladda frĂ„n SD-kortet Ă€r, tyvĂ€rr, inte snabbt i min konfiguration. Å andra sidan gav BootROM ibland ett meddelande att ERROR, det gĂ„r inte att starta, och i samma veva dök U-Boot upp. Det slog mig dĂ„: uppenbarligen, efter omstarten sĂ„ rensar inte bitstream i FPGA-minnet, det hinner inte "tappas" och sĂ„ vidare. Kort sagt kan man helt enkelt, nĂ€r meddelandet LOADING / dyker upp, koppla in debuggern och ge kommandot set variable $pc=0x80089800, pĂ„ sĂ„ sĂ€tt hoppa över den lĂ„nga uppstarten (naturligtvis med antagandet att det gick sönder tillrĂ€ckligt tidigt förra gĂ„ngen och inte hann ladda nĂ„got ovanpĂ„ originalkoden).

Förresten, Àr det normalt att processorn fryser helt, och JTAG-debuggern inte kan koppla upp sig med meddelandena

Error: unable to halt hart 0
Error:   dmcontrol=0x80000001
Error:   dmstatus =0x00030c82

VĂ€nta lite! Jag har sett detta förut! NĂ„got liknande hĂ€nder vid en dödlĂ„sning av TileLink, och jag litar inte riktigt pĂ„ författaren av minneskontrollern — jag skrev det sjĂ€lv... Plötsligt, efter den första lyckade omkompileringen av processorn efter att jag redigerade kontrollern sĂ„g jag:

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING
BOOT

U-Boot 2018.09-g39cd67d-dirty (Jul 03 2019 - 13:50:33 +0300)

DRAM:  1 GiB
MMC:
BEFORE LOAD ENVBEFORE FDTCONTROLADDRBEFORE LOADADDRIn:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  3

Vid denna mÀrkliga rad framför In: serial Ignorera detta - jag försökte förstÄ hur det fungerar med processorn som hÀnger. Vad betyder "Det har hÀngt i tio minuter"? Har det Ätminstone lyckats relocera sig och gÄ till startmenyn? En liten avstickare: Àven om U-Boot laddas bland de första 2^24 byte frÄn SD-kortet, kopierar det sig sjÀlv lÀngre bort till en adress som antingen Àr skriven i konfigurationshuvudet eller helt enkelt i de högre adresserna av RAM-minnet, gör en relocation av ELF-symboler, och överför kontrollen dit. SÄ hÀr Àr lÀget: det verkar som om det nivÄer passerats och som bonus fÄtt en processor som inte hÀnger helt efter det.

SÄ, varför fungerar inte timern? Det verkar som klockan överhuvudtaget av nÄgon anledning inte tickar...

(gdb) x/x 0x0200bff8
0x200bff8:      0x00000000

Vad hÀnder om man snurrar visarna manuellt?

(gdb) set variable *0x0200bff8=310000000
(gdb) c

DĂ„:

Tryck pÄ valfri tangent för att stoppa autoboot:  0
MMC_SPI: 0 vid 0:1 hz 20000000 lÀge 0

Resultat: klockan tickar inte. Troligtvis beror detta pÄ att tangentbordsinmatning inte fungerar:

HiFive_U-Boot/cmd/bootmenu.c:

static void bootmenu_loop(struct bootmenu_data *menu,
        enum bootmenu_key *key, int *esc)
{
    int c;

    while (!tstc()) {
        WATCHDOG_RESET();
        mdelay(10);
    }

    c = getc();

    switch (*esc) {
    case 0:
        /* Första tecknet av ANSI escape-sekvensen 'e' */
        if (c == 'e') {
            *esc = 1;
            *key = KEY_NONE;
        }
        break;
    case 1:
        /* Andra tecknet av ANSI '[' */
        if (c == '[') {
...

Problemet visade sig vara att jag överdrivit lite: jag lade till en nyckel i processorconfigurationsfilen:

  case DTSTimebase => BigInt(0)


 med tanke pĂ„ att det standades "om du inte vet - lĂ€mna 0". Och dĂ„ WithNBigCores precis satte den till 1MHz (som för övrigt angavs i U-Boot-konfigurationen). Men jag Ă€r ju fan noga och pedantisk: dĂ€r vet jag inte, hĂ€r 25MHz! I slutĂ€ndan fungerar ingenting. Jag tog bort mina "förbĂ€ttringar" och...

Tryck pÄ valfri tangent för att stoppa autoboot:  0
MMC_SPI: 0 vid 0:1 hz 20000000 lÀge 0
## OkÀnd partionstabellstyp 0
libfdt fdt_path_offset() returnerade FDT_ERR_NOTFOUND
** Ingen partitionstabell - mmc 0 **
## Info: indata storlek = 34 = 0x22
Kör uEnv.txt boot2...
## Fel: "boot2" Àr inte definierad
HiFive-Unleashed #

Man kan till och med skriva in kommandon! Till exempel, efter lite pillande kan man Ă€ntligen gissa sig till att skriva mmc_spi 1 10000000 0; mmc part, genom att minska SPI-frekvensen frĂ„n 20 MHz till 10 MHz. Varför? Tja, i konfigurationen var den maximala frekvensen angiven som 20 MHz, och den Ă€r fortfarande den samma dĂ€r. Men sĂ„vitt jag förstĂ„r fungerar grĂ€nssnitten, Ă„tminstone hĂ€r, sĂ„ hĂ€r: koden delar frekvensen av hĂ„rdvarumodulen (hos mig Ă€r det alltid 25 MHz) med den mĂ„linriktade, och sĂ€tter det resulterande vĂ€rdet som dividerare i den aktuella kontrollregistret. Problemet Ă€r att om för 115200 Hz UART skulle vara ungefĂ€r det som behövs, sĂ„ om man exakt delar 25000000 med 20000000 fĂ„r man 1, dvs. det kommer att fungera vid 25 MHz. Kanske Ă€r det okej, men om det finns begrĂ€nsningar sĂ€tts, mĂ„ste det vara nödvĂ€ndigt för nĂ„gon (men det Ă€r inte sĂ€kert)... I allmĂ€nhet Ă€r det lĂ€ttare att sĂ€tta dit det och gĂ„ vidare – lĂ„ngt och tyvĂ€rr för lĂ€nge. 25 MHz Ă€r ingen Core i9 för dig.

KonsolutgÄng

HiFive-Unleashed # env edit mmcsetup
edit: mmc_spi 1 10000000 0; mmc part
HiFive-Unleashed # boot
MMC_SPI: 1 at 0:1 hz 10000000 mode 0

Partition Map for MMC device 0  --   Partition Type: EFI

Part    Start LBA       End LBA         Name
        Attributes
        Type GUID
        Partition GUID
  1     0x00000800      0x0000ffde      "Vfat Boot"
        attrs:  0x0000000000000000
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        type:   data
        guid:   76bd71fd-1694-4ff3-8197-bfa81699c2fb
  2     0x00040800      0x002efaf4      "root"
        attrs:  0x0000000000000000
        type:   0fc63daf-8483-4772-8e79-3d69d8477de4
        type:   linux
        guid:   9f3adcc5-440c-4772-b7b7-283124f38bf3
  3     0x0000044c      0x000007e4      "uboot"
        attrs:  0x0000000000000000
        type:   5b193300-fc78-40cd-8002-e86c45580b47
        guid:   bb349257-0694-4e0f-9932-c801b4d76fa3
  4     0x00000400      0x0000044b      "uboot-env"
        attrs:  0x0000000000000000
        type:   a09354ac-cd63-11e8-9aff-70b3d592f0fa
        guid:   4db442d0-2109-435f-b858-be69629e7dbf
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
2376 bytes read in 0 ms
Running uEnv.txt boot2...
15332118 bytes read in 0 ms
## Loading kernel from FIT Image at 90000000 ...
   Using 'config-1' configuration
   Trying 'bbl' kernel subimage
     Description:  BBL/SBI/riscv-pk
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x900000d4
     Data Size:    74266 Bytes = 72.5 KiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x80000000
     Entry Point:  0x80000000
     Hash algo:    sha256
     Hash value:   28972571467c4ad0cf08a81d9cf92b9dffc5a7cb2e0cd12fdbb3216cf1f19cbd
   Verifying Hash Integrity ... sha256+ OK
## Loading fdt from FIT Image at 90000000 ...
   Using 'config-1' configuration
   Trying 'fdt' fdt subimage
     Description:  unavailable
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x90e9d31c
     Data Size:    6911 Bytes = 6.7 KiB
     Architecture: RISC-V
     Load Address: 0x81f00000
     Hash algo:    sha256
     Hash value:   10b0244a5a9205357772ea1c4e135a4f882409262176d8c7191238cff65bb3a8
   Verifying Hash Integrity ... sha256+ OK
   Loading fdt from 0x90e9d31c to 0x81f00000
   Booting using the fdt blob at 0x81f00000
## Loading loadables from FIT Image at 90000000 ...
   Trying 'kernel' loadables subimage
     Description:  Linux kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x900123e8
     Data Size:    10781356 Bytes = 10.3 MiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x80200000
     Entry Point:  unavailable
     Hash algo:    sha256
     Hash value:   72a9847164f4efb2ac9bae736f86efe7e3772ab1f01ae275e427e2a5389c84f0
   Verifying Hash Integrity ... sha256+ OK
   Loading loadables from 0x900123e8 to 0x80200000
## Loading loadables from FIT Image at 90000000 ...
   Trying 'ramdisk' loadables subimage
     Description:  buildroot initramfs
     Type:         RAMDisk Image
     Compression:  gzip compressed
     Data Start:   0x90a5a780
     Data Size:    4467411 Bytes = 4.3 MiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x82000000
     Entry Point:  unavailable
     Hash algo:    sha256
     Hash value:   883dfd33ca047e3ac10d5667ffdef7b8005cac58b95055c2c2beda44bec49bd0
   Verifying Hash Integrity ... sha256+ OK
   Loading loadables from 0x90a5a780 to 0x82000000

Okej, vi har nÄtt en ny nivÄ, men det hÀnger fortfarande. Och ibland spottar det ut undantag. Man kan se mcause om man fÄngar koden vid den angivna adressen $pc och efter si hamna pÄ trap_entry. Handlaren i U-Boot kan bara skriva ut för mcause = 0..4, sÄ var beredd pÄ att fastna i en felaktig inlÀsning. HÀr gick jag in i konfigurationen, började kolla vad jag hade Àndrat, och kom ihÄg: dÀr i conf/rvboot-fit.txt stÄr det:

fitfile=image.fit
# nedan mÄste matcha vad som finns i FIT (ugha)

LĂ„t oss göra alla filer överensstĂ€mmande, vi ersĂ€tter kommandoraden för kĂ€rnan ungefĂ€r sĂ„ hĂ€r, eftersom det finns misstankar om att SIF0 — Ă€r en utmatning nĂ„gonstans via PCIe:

-bootargs=console=ttySIF0,921600 debug
+bootargs=console=ttyS0,125200 debug

Och dessutom byter vi hash-algoritmen frÄn SHA-256 till MD5: jag behöver ingen kryptostyrka (speciellt under felsökning), det sÀgs ta fruktansvÀrt lÄng tid, och för att fÄnga upp integritetsfel under inlÀsning Àr MD5 mer Àn tillrÀckligt. SÄ vad blev resultatet? Vi kunde passera det föregÄende steget betydligt snabbare (pÄ grund av den enklare hashningen), och nÀsta steg öppnades:

...
   Verifierar hashintegritet ... md5+ OK
   Laddar lastfiler frÄn 0x90a5a758 till 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
chosen {
        linux,initrd-end = ;
        linux,initrd-start = ;
        riscv,kernel-end = ;
        riscv,kernel-start = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
chosen {
        linux,initrd-end = ;
        linux,initrd-start = ;
        riscv,kernel-end = ;
        riscv,kernel-start = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
   Laddar kÀrnbild ... OK
Startar kÀrnan om
3

Men klockorna tickar inte...

(gdb) x/x 0x0200bff8
0x200bff8:      0x00000000

Ups, det verkar som att justeringen av klockan var ett placebo, Àven om det dÄ verkade hjÀlpa. Nej, vi mÄste sjÀlvklart fixa det, men lÄt oss först vrida visarna manuellt och se vad som hÀnder:

0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=1000000
(gdb) c
FortsÀtter.
^C
Programmet fick signal SIGINT, avbruten.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=2000000
(gdb) c
FortsÀtter.
^C
Programmet fick signal SIGINT, avbruten.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=3000000
(gdb) c
FortsÀtter.

Under tiden...

   Laddar kÀrnbild ... OK
Startar kÀrnan om
3
2
1
0
## Startar applikation vid 0x80000000 ...

Nej dĂ„, jag gĂ„r för att automatisera klockan — annars kanske den försöker kalibrera timern!

Och adressen för den aktuella instruktionen pekar under tiden nÄgonstans pÄ

0000000080001c20 :
    80001c20:   1141                    addi    sp,sp,-16
    80001c22:   e022                    sd      s0,0(sp)
    80001c24:   842a                    mv      s0,a0
    80001c26:   00005517                auipc   a0,0x5
    80001c2a:   0ca50513                addi    a0,a0,202 # 80006cf0 
    80001c2e:   e406                    sd      ra,8(sp)
    80001c30:   f7fff0ef                jal     ra,80001bae 
    80001c34:   8522                    mv      a0,s0
    80001c36:   267000ef                jal     ra,8000269c 
    80001c3a:   00010797                auipc   a5,0x10
    80001c3e:   41e78793                addi    a5,a5,1054 # 80012058 
    80001c42:   639c                    ld      a5,0(a5)
    80001c44:   c399                    beqz    a5,80001c4a 
    80001c46:   72c000ef                jal     ra,80002372 
    80001c4a:   45a1                    li      a1,8
    80001c4c:   4501                    li      a0,0
    80001c4e:   dc7ff0ef                jal     ra,80001a14 
    80001c52:   10500073                wfi
    80001c56:   bff5                    j       80001c52

inuti den laddade Berkeley Boot Loader. Personligen stör jag mig pĂ„ omnĂ€mnandet htif — hostgrĂ€nssnittet som anvĂ€nds för tethered start av kĂ€rnan (det vill sĂ€ga i samarbete med vĂ€rd-ARM), jag hade tĂ€nkt mig en fristĂ„ende lösning. Men om man hittar denna funktion i kĂ€llkoden ser man att inte allt Ă€r sĂ„ illa:

void poweroff(uint16_t code)
{
  printm("Power offrn");
  finisher_exit(code);
  if (htif) {
    htif_poweroff();
  } else {
    send_ipi_many(0, IPI_HALT);
    while (1) { asm volatile ("wfin"); }
  }
}

Uppdrag: starta klockan

Sökning av register i CLINT leder oss till

    val io = IO(new Bundle {
      val rtcTick = Bool(INPUT)
    })

    val time = RegInit(UInt(0, width = timeWidth))
    when (io.rtcTick) { time := time + UInt(1) }

som kopplas in i RTC, eller i den mystiska MockAON, som jag frÄn början tÀnkte: 'Vad har vi hÀr? Oklart? Koppla bort!' Eftersom jag fortfarande inte förstÄr vilken klockmagik som pÄgÄr dÀr, kommer jag helt enkelt att omimplementera denna logik i System.scala:

  val rtcDivider = RegInit(0.asUInt(16.W)) // för sÀkerhets skull stödjer jag upp till 16 GHz, jag Àr optimist :)
  val mhzInt = p(DevKitFPGAFrequencyKey).toInt
  // Anta att frekvensen Àr ett helt antal megahertz
  rtcDivider := Mux(rtcDivider === (mhzInt - 1).U, 0.U, rtcDivider + 1.U)
  outer.clintOpt.foreach { clint =>
    clint.module.io.rtcTick := rtcDivider === 0.U
  }

NÀr jag nÀrmar mig Linux-kÀrnan

HÀr har berÀttelsen redan dragit ut pÄ tiden och blivit lite enformig, sÄ jag kommer att beskriva översiktligt:

BBL antog att det skulle finnas ett FDT vid adressen 0xF0000000, men jag hade ju redan rÀttat till det! NÄvÀl, vi letar vidare... Hittade i HiFive_U-Boot/arch/riscv/lib/boot.c, bytte till 0x81F00000, angiven i U-Boot:s laddningskonfiguration.

Sedan klagade BBL över att det inte fanns nĂ„got minne. Min vĂ€g ledde till funktionen mem_prop, visar att riscv-pk/machine/fdt.c: dĂ€rifrĂ„n fick jag veta att jag behövde mĂ€rka noden fdt ram som device_type = "memory" — kanske behöver jag justera CPU-generatorn senare, men för nu skriver jag bara in för hand — jag har Ă€ndĂ„ flyttat den hĂ€r filen manuellt.

Nu har jag fÄtt ett meddelande (visat i formaterad stil, med radbrytningar):

This is bbl's dummy_payload. To boot a real kernel, reconfigure bbl
with the flag --with-payload=PATH, then rebuild bbl. Alternatively,
bbl can be used in firmware-only mode by adding device-tree nodes
for an external payload and use QEMU's -bios and -kernel options.

Verkar som att alternativen anges korrekt riscv,kernel-start och riscv,kernel-end i DTB, men nollor parsas. Debugging query_chosen visade att BBL försöker parsa en 32-bitars adress, men stöter pÄ ett par <0x0 0xADDR>, och det första vÀrdet verkar vara de lÀgre bitarna. Jag lade till i sektionen chosen

chosen {
      #address-cells = ;
      #size-cells = ;
      ...
}

och justerade genereringen av vÀrdena: inte lÀgga till 0x0 som första element.

Dessa 100500 enkla steg gör det lÀtt och enkelt att se hur pingvinen faller:

Dolt innehÄll

   Verifierar hash-integritet ... md5+ OK
   Laddar lastbar frÄn 0x90a5a758 till 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
valda {
        linux,initrd-end = ;
        linux,initrd-start = ;
        riscv,kernel-end = ;
        riscv,kernel-start = ;
        #address-cells = ;
        #size-cells = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() ÄterstÀllde FDT_ERR_NOTFOUND
valda {
        linux,initrd-end = ;
        linux,initrd-start = ;
        riscv,kernel-end = ;
        riscv,kernel-start = ;
        #address-cells = ;
        #size-cells = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
   Laddar kÀrnbild ... OK
Startar kÀrnan i
3
2
1
0
## Startar applikationen vid 0x80000000 ...
bbl loader

                SIFIVE, INC.

         5555555555555555555555555
        5555                   5555
       5555                     5555
      5555                       5555
     5555       5555555555555555555555
    5555       555555555555555555555555
   5555                             5555
  5555                               5555
 5555                                 5555
5555555555555555555555555555          55555
 55555           555555           55555
   55555           55555           55555
     55555           5           55555
       55555                   55555
         55555               55555
           55555           55555
             55555       55555
               55555   55555
                 555555555
                   55555
                     5

           SiFive RISC-V Core IP
[    0.000000] OF: fdt: Ignorerar minnesomrÄde 0x80000000 - 0x80200000
[    0.000000] Linux-version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc-version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Ons Jul 3 21:29:21 MSK 2019
[    0.000000] bootconsole [early0] aktiverad
[    0.000000] Initial ramdisk pÄ: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Zonnintervall:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Flyttbart zonstart för varje nod
[    0.000000] Tidig minnesnodintervall
[    0.000000]   nod   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem-setup nod 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] För nod 0 total sidor: 261632
[    0.000000]   DMA32 zon: 3577 sidor anvÀnda för memmap
[    0.000000]   DMA32 zon: 0 sidor reserverade
[    0.000000]   DMA32 zon: 261632 sidor, LIFO-batch:63
[    0.000000] mjukvaru IO TLB: mappad [mem 0xbb1fc000-0xbf1fc000] (64MB)

(logotypen visar BBL, och det som Àr med tidsstÀmplar - kÀrnan).

Lyckligtvis vet jag inte hur det Àr överallt, men pÄ RocketChip kan man fÄnga trappor direkt frÄn lÄdan nÀr man ansluter en debugger via JTAG - debuggern stannar exakt i den punkten.

Programmet fick signal SIGTRAP, spÄrnings-/avbrottstrapp.
0xffffffe0000024ca i ?? ()
(gdb) bt
#0  0xffffffe0000024ca i ?? ()
TillbakatrÀd stoppat: föregÄende ram identisk med denna ram (korrupt stack?)
(gdb) fil work/linux/vmlinux
Ett program debuggeras redan.
Är du sĂ€ker pĂ„ att du vill Ă€ndra filen? (y eller n) y
LÀser symboler frÄn work/linux/vmlinux... klart.
(gdb) bt
#0  0xffffffe0000024ca i setup_smp () pÄ /hdd/trosinenko/fpga/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:75
#1  0x0000000000000000 i ?? ()
TillbakatrÀd stoppat: ramen sparade inte PC

freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:

void __init setup_smp(void)
{
    struct device_node *dn = NULL;
    int hart;
    bool found_boot_cpu = false;
    int cpuid = 1;

    while ((dn = of_find_node_by_type(dn, "cpu"))) {
        hart = riscv_of_processor_hartid(dn);
        if (hart < 0)
            continue;

        if (hart == cpuid_to_hartid_map(0)) {
            BUG_ON(found_boot_cpu);
            found_boot_cpu = 1;
            continue;
        }

        cpuid_to_hartid_map(cpuid) = hart;
        set_cpu_possible(cpuid, true);
        set_cpu_present(cpuid, true);
        cpuid++;
    }

    BUG_ON(!found_boot_cpu); // < DU ÄR HÄR
}

Som det sades i den gamla anekdoten, CPU inte hittad, kör programvaru-emulering. Eller inte körande. Förlorad i enstaka kÀrna av processorn.

/* The lucky hart to first increment this variable will boot the other cores */
atomic_t hart_lottery;
unsigned long boot_cpu_hartid;

En bra kommentar i linux/arch/riscv/kernel/setup.c — en slags mĂ„lning av ett staket enligt Tom Sawyers metod. Sammanfattningsvis, idag fanns det av nĂ„gon anledning inga vinnare, priset flyttas till nĂ€sta omgĂ„ng...

Jag föreslÄr att vi avslutar den hÀr redan utdragna artikeln.

FortsÀttning följer. I den kommer en kamp med ett lurigt fel som hinner gömma sig om man nÀrmar sig lÄngsamt med singlestep.

Textbaserad screencast av laddningen (extern lÀnk):
Del 3: NÀstan laddar Linux frÄn SD-kort till RocketChip

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster