Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip В forrige del en mere eller mindre arbejdshukommelsescontroller blev implementeret, eller rettere sagt, en wrapper over IP Core fra Quartus, som er en adapter til TileLink. I dag vil du i afsnittet "Vi overfører RocketChip til et lidet kendt kinesisk bord med Cyclone" se en fungerende konsol. Processen tog lidt længere tid: Jeg tænkte allerede, at jeg hurtigt ville starte Linux og komme videre, men det var ikke tilfældet. I denne del foreslår jeg at se på processen med at starte U-Boot, BBL og Linux-kernens frygtsomme forsøg på at initialisere. Men der er en konsol - U-Boot, og ret avanceret, der har meget af det, du ville forvente af en fuldgyldig konsol.

Hardwaren vil omfatte et SD-kort, der er tilsluttet via SPI-interfacet, samt en UART. I softwaredelen vil BootROM blive erstattet med xipsdboot og faktisk er følgende indlæsningstrin blevet tilføjet (på SD-kortet).

Efterbehandling af hardwaren

Så opgaven: du skal skifte til en "stor" kerne og tilslutte en UART (fra Raspberry) og en SD-adapter (vi brugte et kort fra Catalex med seks ben: GND, VCC, MISO, MOSI, SCK, CS) .

I princippet var alt ret simpelt. Men før jeg indså dette, blev jeg smidt lidt fra side til side: efter den forrige gang besluttede jeg, at igen skulle jeg bare blande mig i System noget som HasPeripheryUART (og implementering i overensstemmelse hermed), det samme for SD-kortet - og alt vil være klar. Så besluttede jeg at se, hvordan det blev implementeret i et "seriøst" design. Så hvad er alvorligt ved dette? Arty passer tilsyneladende ikke - monsteret forbliver unleahshed.DevKitConfigs. Og pludselig viste det sig, at der var nogle overlejringer overalt, som blev tilføjet gennem parametre ved hjælp af taster. Jeg gætter på, at dette nok er meget fleksibelt og konfigurerbart, men jeg vil i det mindste gerne køre noget først... Har du ikke det samme, kun enklere og mere irriterende? Det var da jeg stødte på vera.iofpga.FPGAChip til Microsemi FPGA'er og straks adskilte den for tilbud og forsøgte at lave min egen implementering analogt, heldigvis er der mere eller mindre hele "bundkortlayoutet" i én fil.

Det viste sig, at du egentlig bare skal tilføje System.scala linje

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
...

Linje i klassens krop System tilføjer oplysninger om den frekvens, hvormed denne del af vores SoC opererer, til filen dts. Så vidt jeg forstår, er DTS/DTB en statisk analog af plug-and-play-teknologi til indlejrede enheder: dts-beskrivelsestræet kompileres til en binær dtb-fil og overføres af bootloaderen til kernen, så den korrekt kan konfigurere hardware. Interessant, uden linjen med tlclock alt syntetiseres perfekt, men kompilering af BootROM (lad mig minde dig om, nu vil dette allerede være sdboot) vil ikke fungere - under kompileringsprocessen parser den dts-filen og opretter en header med en makro TL_CLK, takket være hvilken han vil være i stand til korrekt at konfigurere frekvensdelere til eksterne grænseflader.

Du skal også rette lidt på "ledningerne":

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 card
  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
}

Registerkæderne, for at være ærlig, blev tilføjet ganske enkelt analogt med nogle andre steder i den originale kode. Mest sandsynligt skal de beskytte mod metastabilitet. Måske i nogle blokke har allerede deres egen beskyttelse, men først vil jeg lancere det i det mindste "på et niveau af høj kvalitet." Et mere interessant spørgsmål for mig er, hvorfor MISO og MOSI hænger på forskelligt dq? Jeg har ikke fundet svaret endnu, men det ser ud til, at resten af ​​koden er afhængig af netop sådan en forbindelse.

Fysisk tildelte jeg simpelthen designstifterne til de frie kontakter på blokken og flyttede spændingsvalgjumperen til 3.3V.

SD adapter

Set fra oven:

Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Set nedefra:

Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Software Debugging: Værktøjer

Lad os først tale om de tilgængelige fejlfindingsværktøjer og deres begrænsninger.

Minicom

Først skal vi på en eller anden måde læse, hvad bootloaderen og kerne outputtet. For at gøre dette på Linux (i dette tilfælde på den på RaspberryPi), har vi brug for Minicom-programmet. Generelt vil ethvert program, der fungerer med en seriel port, duge.

Bemærk venligst, at ved start skal portenhedens navn angives som -D /dev/ttyS0 - efter muligheden -D. Nå, de vigtigste oplysninger: at afslutte, bruge Ctrl-A, X. Jeg havde faktisk et tilfælde, hvor denne kombination ikke virkede – så kan man bare sige fra en nabo-SSH-session killall -KILL minicom.

Der er en funktion mere. Specifikt har RaspberryPi to UART'er, og begge porte kan allerede tilpasses til noget: en til Bluetooth, den anden udsender som standard kernekonsollen. Heldigvis kan denne adfærd tilsidesættes i henhold til denne manual.

Omskrivning af hukommelsen

Når jeg fejlede, for at teste en hypotese, var jeg nogle gange nødt til det indlæs bootloader (undskyld) ind i RAM direkte fra værten. Måske kan dette gøres direkte fra GDB, men til sidst fulgte jeg en simpel sti: Jeg kopierede den nødvendige fil til Raspberry, videresendte også port 4444 via SSH (telnet fra OpenOCD) og brugte kommandoen load_image. Når du gør det, virker det som om alt er frosset, men faktisk "den sover ikke, den blinker bare langsomt": Den downloader filen, den gør det bare med en hastighed på et par kilobyte i sekundet.

Funktioner ved installation af brudpunkter

Mange mennesker har sikkert ikke behøvet at tænke på dette, når de fejlretter almindelige programmer, men brudpunkter er ikke altid sat i hardware. Nogle gange involverer indstilling af et brudpunkt midlertidigt at nedskrive særlige instruktioner på det rigtige sted direkte ind i maskinkoden. Det er for eksempel sådan min standardkommando fungerede b i GDB. Her er hvad der følger:

  • du kan ikke sætte en prik inde i BootROM, fordi ROM
  • Du kan indstille et brudpunkt på koden, der er indlæst i RAM fra SD-kortet, men du skal vente, indtil den er indlæst. Ellers vil vi ikke omskrive et stykke kode, men indlæseren vil omskrive vores breakpoint

Jeg er sikker på, at du eksplicit kan bede om at bruge hardware breakpoints, men der er et begrænset antal af dem alligevel.

Hurtig udskiftning af BootROM

I den indledende fase af fejlretningen er der ofte et ønske om at rette BootROM'en og prøve igen. Men der er et problem: BootROM er en del af designet indlæst i FPGA'en, og dets syntese er et spørgsmål om et par minutter (og dette er efter næsten øjeblikkelig kompilering af selve BootROM-billedet fra C og Assembler...). Heldigvis i virkeligheden alt meget hurtigere: rækkefølgen af ​​handlinger er som følger:

  • regenerer bootrom.mif (jeg skiftede til MIF i stedet for HEX, fordi jeg altid havde nogle problemer med HEX, og MIF er Alters oprindelige format)
  • i Quartus sige Processing -> Update Memory Initialization File
  • på Assembler-elementet (i venstre kolonne af Opgaver) kommandoen Start igen

Alt om alt - et par snese sekunder.

Forberedelse af SD-kortet

Alt her er relativt enkelt, men du skal være tålmodig og have omkring 14 Gb diskplads:

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

Hvorefter du skal indsætte et rent, eller rettere, et, der ikke indeholder noget nødvendigt, SD-kort og udføre

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

… Hvor sdX — enhed, der er tildelt kortet. OBS: dataene på kortet vil blive slettet, overskrevet og generelt! Det er næppe værd at lave hele samlingen nedefra sudofordi så vil alle byggeartefakter tilhøre root, og monteringen skal udføres nedefra sudo konstant.

Resultatet er et kort markeret i GPT med fire partitioner, hvoraf den ene har FAT med uEnv.txt og et bootbart billede i FIT-format (det indeholder flere underbilleder, hver med sin egen downloadadresse), den anden partition er tom, den formodes at være formateret i Ext4 til Linux. To afsnit mere - mystisk: U-Boot lever på den ene (dets offset, så vidt jeg forstår, er hårdkodet i BootROM), på den anden, ser det ud til, dens miljøvariabler lever, men jeg bruger dem ikke endnu.

Niveau et, BootROM

Populær visdom siger: "Hvis der i programmering er dans med en tamburin, så er der i elektronik også dans med en ildslukker." Det handler ikke engang om, at jeg engang næsten brændte brættet og besluttede, at "Nå, GND er det samme lave niveau." (tilsyneladende ville en modstand trods alt ikke skade...) Det handler mere om, at hvis hænderne ikke vokser derfra, så holder elektronikken aldrig op med at bringe overraskelser: når jeg lodde stikket på kortet, kunne jeg stadig ikke lodde kontakterne ordentligt - videoen viser, hvordan loddet direkte spredes over hele forbindelsen skal du bare påføre en loddekolbe, For mig "smede" han tilfældigt. Nå, måske var loddet ikke egnet til temperaturen på loddekolben, måske noget andet... Generelt, da jeg så, at jeg allerede havde et dusin kontakter, gav jeg op og begyndte at fejlfinde. Og så begyndte det mystisk: Jeg tilsluttede RX/TX fra UART, jeg indlæser firmwaren - der står

INIT
CMD0
ERROR

Nå, alt er logisk - jeg tilsluttede ikke SD-kortmodulet. Vi retter op på situationen, indlæser firmwaren... Og tavshed... Hvorfor ombestemte jeg mig ikke, men den lille boks åbnede sig lige: en af ​​modulstifterne skulle forbindes til VCC. I mit tilfælde understøttede modulet 5V til strømforsyning, så uden at tænke to gange tilsluttede jeg ledningen fra modulet til den modsatte side af kortet. Det resulterede i, at det skæve loddede stik blev skævt, og UART-kontakten gik simpelthen tabt. facepalm.jpg Generelt, "et dårligt hoved giver ingen hvile til benene," og skæve hænder giver ingen hvile til hovedet ...

Som et resultat så jeg den længe ventede

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

Desuden bevæger den sig, og indlæsningsindikatoren drejer. Jeg husker straks min skoletid og den afslappede indlæsning af MinuetOS fra en diskette. Medmindre drevet ikke kværner.

Problemet er, at der ikke sker noget efter BOOT-meddelelsen. Dette betyder, at det er tid til at oprette forbindelse via OpenOCD til Raspberry, til GDB på værten og se, hvad det er.

For det første viste forbindelse ved hjælp af GDB det straks $pc (programtæller, adresse på den aktuelle instruktion) flyver til 0x0 - dette sker sandsynligvis efter flere fejl. Derfor umiddelbart efter meddelelsen er udstedt BOOT Lad os tilføje en uendelig løkke. Det vil forsinke ham et stykke tid...

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;
 }

Sådan tricky kode bruges "til pålidelighed": Jeg hørte et sted, at en endeløs løkke er en udefineret adfærd, men det er usandsynligt, at compileren vil gætte (jeg minder dig om, at iflg. 0x10000 lokaliseret BootROM).

Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Det ser ud til, hvad man ellers kan forvente - hårdt indlejret, hvilken slags kildekoder er der? Men i den artikel forfatteren fejlede C-koden... Kreks-fex-pex:

(gdb) file builds/zeowaa-e115/sdboot.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from builds/zeowaa-e115/sdboot.elf...done.

Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Du skal bare downloade ikke MIF-filen eller bin, men den originale version i ELF-format.

Nu kan du med n'te forsøg gætte adressen, hvor eksekveringen vil fortsætte (dette er endnu en grund til, at compileren ikke skulle have gættet, at løkken er uendelig). Hold

set variable $pc=0xADDR

giver dig mulighed for at ændre registerværdien på farten (i dette tilfælde adressen på den aktuelle instruktion). Med dens hjælp kan du ændre værdier skrevet til hukommelsen (og hukommelseskortede registre).

I sidste ende kom jeg til den konklusion (ikke sikker på, hvad der er korrekt), at vi har "et SD-kortbillede af det forkerte system", og vi skal ikke gå til begyndelsen af ​​de downloadede data, men til 0x89800 bytes yderligere:

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

Måske var dette også påvirket af, at jeg ikke havde et unødvendigt 4Gb-kort ved hånden, tog et 2Gb-kort og erstattede det tilfældigt i Makefilen DEMO_END=11718750DEMO_END=3078900 (søg ikke efter mening i en bestemt betydning - der er ingen, det er bare, at nu er billedet placeret på kortet).

Niveau to, U-Boot

Nu er vi stadig "faldende", men vi er allerede på det rigtige sted 0x0000000080089a84. Her må jeg indrømme: faktisk går præsentationen ikke "med alle stop", men er delvist skrevet "efter", så her har jeg allerede nået at indsætte den korrekte dtb-fil fra vores SoC, rette den i indstillingerne HiFive_U-Boot variabel CONFIG_SYS_TEXT_BASE=0x80089800 (i stedet 0x08000000), så downloadadressen matcher den faktiske. Nu indlæser vi kortet over det næste niveau, et andet billede:

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

Og vi ser:

   │304     /*                                               │
   │305      * trap entry                                    │
   │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)                      │

Desuden hopper vi mellem linje 308 og 309. Og det er ikke overraskende, i betragtning af at i $sp ligger meningen 0xfffffffe31cdc0a0. Ak, den "løber væk" også konstant på grund af linje 307. Lad os derfor prøve at sætte et brudpunkt kl. trap_entry, og gå derefter tilbage til 0x80089800 (U-Boots indgangspunkt), og lad os håbe, at det ikke kræver, at registrene er indstillet korrekt, før de hopper... Det ser ud til, at det virker:

(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
Continuing.

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

Stakmarkøren er helt ærligt talt halvdårlig: den peger helt uden om RAM'en (medmindre vi selvfølgelig ikke allerede har adresseoversættelse, men lad os håbe på en simpel mulighed).

Lad os prøve at erstatte markøren med 0x881cf950. Som et resultat kommer vi til den konklusion, at handle_trap ringede og ringede, og samtidig går vi ind _exit_trap med et argument epc=2148315240 (i decimal):

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

Indstil brudpunkt til strnlen, vi fortsætter og 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=<optimized out>, precision=<optimized out>, flags=<optimized out>) 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 %08x , ra %08lxn", fmt@entry=0x800d4458 "exception code: %d , %s , epc %08x , ra %08lxn", 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 %08x , ra %08lxn", 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 %08x , ra %08lxn", args=args@entry=0x881cc188) at lib/vsprintf.c:717
#5  0x00000000800ccb50 in printf (fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc %08x , ra %08lxn") at lib/vsprintf.c:792
#6  0x000000008008a9f0 in _exit_trap (regs=<optimized out>, epc=2148315240, code=<optimized out>) at arch/riscv/lib/interrupts.c:92
#7  handle_trap (mcause=<optimized out>, epc=<optimized out>, regs=<optimized out>) 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 ser ud _exit_trap ønsker at give fejlfindingsoplysninger om den undtagelse, der opstod, men det kan han ikke. Så på en eller anden måde bliver vores kilder ikke vist igen. set directories ../freedom-u-sdk/HiFive_U-Boot/ OM! Nu vist!

Nå, lad os køre det igen og se fra stakken spore årsagen til det oprindelige problem, der forårsagede den første fejl (mcause == 5). Hvis jeg har forstået det der står rigtigt her på side 37, så betyder denne undtagelse Load access fault. Årsagen ser ud til at være den her

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

call_board_init_f:
    li  t0, -16
    li  t1, CONFIG_SYS_INIT_SP_ADDR
    and sp, t1, t0  /* force 16 byte alignment */

#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       /* jump to board_init_f() */

$sp har den samme forkerte betydning, og indeni board_init_f_init_reserve der opstår en fejl. Det ser ud til, at dette er synderen: en variabel med et utvetydigt navn CONFIG_SYS_INIT_SP_ADDR. Det er defineret i filen HiFive_U-Boot/include/configs/HiFive-U540.h. På et tidspunkt tænkte jeg endda, måske, jamen, jeg skulle tilføje en boot-loader til processoren - måske ville det være nemmere at reparere processoren lidt? Men så så jeg, at det var mere som en artefakt fra ikke helt færdig#if 0-specifikke indstillinger for en anden hukommelseskonfiguration, og du kan prøve at gøre dette:

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 */

På et tidspunkt antallet af krykker teknologiske fastgørelseselementer har nået et kritisk punkt. Efter lidt pine kom jeg til behovet for at lave den korrekte port til mit board. For at gøre dette skal vi kopiere og justere et antal filer, så de passer til vores konfiguration.

Nå, cirka, her er en lille tabel

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

    Initial support for Zeowaa A-E115FB board

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 findes i depoter.

Som det viste sig, på dette SiFive-kort har registrene på nogle enheder forskellige adresser. Det viste sig også, at U-Boot er konfigureret ved hjælp af Kconfig-mekanismen, som allerede er kendt fra Linux-kernen - for eksempel kan du kommandere make menuconfig, og en praktisk tekstgrænseflade vises foran dig, der viser beskrivelser af parametrene ved ? etc. Generelt, efter at have samlet en beskrivelse af den tredje fra beskrivelserne af to boards, smidt alle mulige prætentiøse PLL-rekonfigurationer ud derfra (tilsyneladende er dette på en eller anden måde forbundet med kontrol fra værtscomputeren via PCIe, men det er ikke sikkert) , Jeg modtog noget firmware, som i det rigtige vejr på Mars gav mig en besked via UART om hvilken commit-hash den var kompileret fra, og om hvor meget DRAM jeg har (men jeg skrev selv denne information i headeren).

Den eneste skam er, at bestyrelsen efter dette normalt holdt op med at reagere via processor JTAG, og indlæsning fra et SD-kort er desværre ikke hurtig i min konfiguration. På den anden side gav BootROM nogle gange en besked om det ERROR, kunne ikke starte, og U-Boot dukkede straks op. Det var da, det gik op for mig: tilsyneladende, efter genstart af bitstream i FPGA'en, bliver hukommelsen ikke slettet, den har ikke tid til at "aftræne" osv. Kort sagt, du kan simpelthen, når en besked vises LOADING / forbinde med en debugger og kommando set variable $pc=0x80089800, og derved omgå denne lange indlæsning (selvfølgelig ud fra den antagelse, at den sidste gang gik i stykker tidligt nok til, at den ikke havde tid til at indlæse noget oven på den originale kode).

Er det i øvrigt generelt normalt, at processoren fryser fuldstændigt, og JTAG-debuggeren ikke kan oprette forbindelse til den med beskeder?

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

Så vent! Jeg har allerede set det her! Noget lignende sker, når TileLink er deadlocked, og jeg på en eller anden måde ikke stoler på forfatteren af ​​hukommelsescontrolleren - jeg skrev det selv... Pludselig, efter den første vellykkede genopbygning af processoren efter redigering af controlleren, så jeg:

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

Til denne mærkelige linje før In: serial vær ikke opmærksom - jeg prøvede at forstå på en hængende processor, om den fungerer korrekt med miljøet. Hvad mener du, "Det har hængt sådan i ti minutter"? Det lykkedes i det mindste at flytte og gå til opstartsmenuen! En lille digression: Selvom U-Boot indlæses i de første 2^24 bytes fra SD-kortet, kopierer den sig selv til en længere væk adresse, når den starter, enten skrevet i konfigurationshovedet eller blot til de højere adresser i RAM , og udfører ELF relocation -karakterer og overfører kontrol dertil. Så: det ser ud til, at vi passerede dette niveau og modtog en bonus, at processoren ikke hang stramt efter det.

Så hvorfor virker timeren ikke? Det ser ud til, at uret ikke virker af en eller anden grund...

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

Hvad hvis du drejer pilene manuelt?

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

Derefter:

Hit any key to stop autoboot:  0
MMC_SPI: 0 at 0:1 hz 20000000 mode 0

Konklusion: uret tikker ikke. Dette er sandsynligvis grunden til, at tastaturinput ikke virker:

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:
        /* First char of ANSI escape sequence 'e' */
        if (c == 'e') {
            *esc = 1;
            *key = KEY_NONE;
        }
        break;
    case 1:
        /* Second char of ANSI '[' */
        if (c == '[') {
...

Problemet viste sig at være, at jeg var lidt for klog: Jeg tilføjede nøglen til processorkonfigurationen:

  case DTSTimebase => BigInt(0)

... baseret på det faktum, at kommentaren sagde "hvis du ikke ved det, så lad 0." Og trods alt WithNBigCores Jeg har lige sat det til 1MHz (som det i øvrigt blev angivet i U-Boot-konfigurationen). Men for pokker, jeg er pæn og omhyggelig: Jeg ved det ikke, her er det 25MHz! I sidste ende virker intet. Jeg fjernede mine "forbedringer" og...

Hit any key to stop autoboot:  0
MMC_SPI: 0 at 0:1 hz 20000000 mode 0
## Unknown partition table type 0
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
** No partition table - mmc 0 **
## Info: input data size = 34 = 0x22
Running uEnv.txt boot2...
## Error: "boot2" not defined
HiFive-Unleashed #

Du kan endda indtaste kommandoer! For eksempel, efter at have stukket lidt rundt, kan du endelig gætte dig ind mmc_spi 1 10000000 0; mmc part, hvilket reducerer SPI-frekvensen fra 20MHz til 10MHz. Hvorfor? Nå, den maksimale frekvens på 20MHz blev skrevet i konfigurationen, og den er stadig skrevet der. Men så vidt jeg forstår, fungerer grænsefladerne, i det mindste her, sådan her: koden deler frekvensen af ​​hardwareenheden (min er 25MHz overalt) med målet, og indstiller den resulterende værdi som en divisor i den tilsvarende kontrol Tilmeld. Problemet er, at hvis der for en 115200Hz UART er tilnærmelsesvis hvad der skal til, så hvis du dividerer 25000000 med 20000000 får du 1, dvs. det vil virke ved 25MHz. Måske er dette normalt, men hvis der er begrænsninger, betyder det, at nogen har brug for det (men det er ikke sikkert)... Generelt er det nemmere at sætte det ned og komme videre - langt og desværre i lang tid. 25MHz er ikke en Core i9.

Konsoludgang

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

Okay, vi har nået næste niveau, men det fryser stadig. Og nogle gange drysser det også med undtagelser. Du kan se mcause ved at ligge og vente på koden på den angivne adresse $pc og efter si være på trap_entry. U-Boot-handleren selv kan kun udskrive for mcause = 0..4, så gør dig klar til at sidde fast i en forkert boot. Så gik jeg ind i konfigurationen, begyndte at se på, hvad jeg ændrede, og huskede: der inde conf/rvboot-fit.txt skrevet:

fitfile=image.fit
# below much match what's in FIT (ugha)

Nå, lad os bringe alle filerne i overensstemmelse, erstatte kernekommandolinjen med noget som dette, da der er mistanke om, at SIF0 - dette er output et sted via PCIe:

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

Og lad os ændre hashing-algoritmen fra SHA-256 til MD5: Jeg har ikke brug for kryptografisk styrke (især ved debugging), det tager frygtelig lang tid, og til at fange integritetsfejl under indlæsning er MD5 for let. Hvad er slutresultatet? Vi begyndte at fuldføre det forrige niveau mærkbart hurtigere (på grund af enklere hashing), og det næste åbnede:

...
   Verifying Hash Integrity ... md5+ OK
   Loading loadables from 0x90a5a758 to 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
chosen {
        linux,initrd-end = <0x00000000 0x83000000>;
        linux,initrd-start = <0x00000000 0x82000000>;
        riscv,kernel-end = <0x00000000 0x80a00000>;
        riscv,kernel-start = <0x00000000 0x80200000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
chosen {
        linux,initrd-end = <0x00000000 0x83000000>;
        linux,initrd-start = <0x00000000 0x82000000>;
        riscv,kernel-end = <0x00000000 0x80a00000>;
        riscv,kernel-start = <0x00000000 0x80200000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
   Loading Kernel Image ... OK
Booting kernel in
3

Men uret tikker ikke...

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

Ups, det ser ud som om, at korrigering af uret viste sig at være en placebo, selvom det forekom mig på det tidspunkt, at det hjalp. Nej, det skal selvfølgelig rettes, men lad os først dreje pilene manuelt og se, hvad der sker:

0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=1000000
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=2000000
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=3000000
(gdb) c
Continuing.

I mellemtiden…

   Loading Kernel Image ... OK
Booting kernel in
3
2
1
0
## Starting application at 0x80000000 ...

Nej, jeg vil automatisere uret - ellers beslutter han sig måske for at kalibrere timeren der!

I mellemtiden peger adressen på den aktuelle instruktion et sted ind

0000000080001c20 <poweroff>:
    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 <softfloat_countLeadingZeros8+0x558>
    80001c2e:   e406                    sd      ra,8(sp)
    80001c30:   f7fff0ef                jal     ra,80001bae <printm>
    80001c34:   8522                    mv      a0,s0
    80001c36:   267000ef                jal     ra,8000269c <finisher_exit>
    80001c3a:   00010797                auipc   a5,0x10
    80001c3e:   41e78793                addi    a5,a5,1054 # 80012058 <htif>
    80001c42:   639c                    ld      a5,0(a5)
    80001c44:   c399                    beqz    a5,80001c4a <poweroff+0x2a>
    80001c46:   72c000ef                jal     ra,80002372 <htif_poweroff>
    80001c4a:   45a1                    li      a1,8
    80001c4c:   4501                    li      a0,0
    80001c4e:   dc7ff0ef                jal     ra,80001a14 <send_ipi_many>
    80001c52:   10500073                wfi
    80001c56:   bff5                    j       80001c52 <poweroff+0x32>

inde i den indlæste Berkeley Boot Loader. Personligt er det, der forvirrer mig ved dette, omtalen htif — værtsgrænseflade brugt til tethered lancering af kernen (det vil sige i samarbejde med værten ARM), antog jeg selvstændigt. Men hvis du finder denne funktion i kildekoden, kan du se, at ikke alt er så slemt:

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"); }
  }
}

Quest: start uret

Søgning efter registre i CLINT fører os til

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

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

Som forbinder til RTC, eller til den mystiske MockAON, som jeg oprindeligt tænkte om: "Så, hvad har vi her? Uklar? Lad os slå det fra!" Da jeg stadig ikke forstår, hvilken slags urmagi der foregår der, så vil jeg bare genimplementere denne logik i System.scala:

  val rtcDivider = RegInit(0.asUInt(16.W)) // на всякий случай поддержу до 16ГГц, я оптимист :)
  val mhzInt = p(DevKitFPGAFrequencyKey).toInt
  // Преположим, частота равна целому числу мегагерц
  rtcDivider := Mux(rtcDivider === (mhzInt - 1).U, 0.U, rtcDivider + 1.U)
  outer.clintOpt.foreach { clint =>
    clint.module.io.rtcTick := rtcDivider === 0.U
  }

På vej til Linux-kernen

Her har historien allerede trukket ud og er blevet lidt ensformig, så jeg vil beskrive den fra top til bund:

BBL antog tilstedeværelsen af ​​FDT kl 0xF0000000, men jeg har allerede rettet det! Nå, lad os se igen... Fandt det ind HiFive_U-Boot/arch/riscv/lib/boot.c, erstattet af 0x81F00000, angivet i U-Boot boot-konfigurationen.

Så klagede BBL over, at der ikke var nogen hukommelse. Min vej lå i funktionen mem_prop, hvad i riscv-pk/machine/fdt.c: Derfra lærte jeg, at du skal markere fdt ram-noden som device_type = "memory" - så skal processorgeneratoren måske rettes, men indtil videre vil jeg bare skrive den ind manuelt - i hvert fald overførte jeg denne fil manuelt.

Nu fik jeg beskeden (leveret i formateret form, med vognretur):

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.

Det ser ud til, at mulighederne er angivet efter behov riscv,kernel-start и riscv,kernel-end i DTB, men nuller parses. Debugging query_chosen viste, at BBL forsøger at parse en 32-bit adresse, men den støder på et par <0x0 0xADDR>, og den første værdi synes at være de mindst signifikante bits. Tilføjet til sektion chosen

chosen {
      #address-cells = <1>;
      #size-cells = <0>;
      ...
}

og korrigeret genereringen af ​​værdier: Tilføj ikke 0x0 det første element.

Disse 100500 enkle trin gør det nemt at se en pingvin falde:

Skjult tekst

   Verifying Hash Integrity ... md5+ OK
   Loading loadables from 0x90a5a758 to 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
chosen {
        linux,initrd-end = <0x83000000>;
        linux,initrd-start = <0x82000000>;
        riscv,kernel-end = <0x80a00000>;
        riscv,kernel-start = <0x80200000>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
chosen {
        linux,initrd-end = <0x83000000>;
        linux,initrd-start = <0x82000000>;
        riscv,kernel-end = <0x80a00000>;
        riscv,kernel-start = <0x80200000>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
   Loading Kernel Image ... OK
Booting kernel in
3
2
1
0
## Starting application at 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           555555555           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: Ignoring memory range 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 Wed Jul 3 21:29:21 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] Initial ramdisk at: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] On node 0 totalpages: 261632
[    0.000000]   DMA32 zone: 3577 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 261632 pages, LIFO batch:63
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)

(logoet vises af BBL, og det med tidsstempler vises af kernen).

Heldigvis ved jeg ikke, hvordan det er overalt, men på RocketChip, når du tilslutter en debugger via JTAG, kan du fange fælder ud af kassen - debuggeren stopper præcis på dette tidspunkt.

Program received signal SIGTRAP, Trace/breakpoint trap.
0xffffffe0000024ca in ?? ()
(gdb) bt
#0  0xffffffe0000024ca in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) file work/linux/vmlinux
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from work/linux/vmlinux...done.
(gdb) bt
#0  0xffffffe0000024ca in setup_smp () at /hdd/trosinenko/fpga/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:75
#1  0x0000000000000000 in ?? ()
Backtrace stopped: frame did not save the 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); // < ВЫ НАХОДИТЕСЬ ЗДЕСЬ
}

Som den gamle joke sagde, CPU ikke fundet, kører softwareemulering. Nå, eller ikke løbe. Tabt i en enkelt processorkerne.

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

Fin kommentar i linux/arch/riscv/kernel/setup.c - en slags maleri af et hegn efter Tom Sawyer-metoden. Generelt var der af en eller anden grund ingen vindere i dag, præmien overføres til næste lodtrækning...

Her foreslår jeg at afslutte den allerede lange artikel.

Fortsættes. Der vil være en kamp med en snedig fejl, der formår at gemme sig, hvis du langsomt kryber op på den med singlestep.

Tekstdownload screencast (eksternt link):
Del 3: Næsten indlæsning af Linux fra SD-kort til RocketChip

Kilde: www.habr.com

Tilføj en kommentar