Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile Uues eelmises osas olid töötav mälu kontroller, täpsemalt — IP Core'i ümbertöötamine Quartusest, mis toimib üleminekuna TileLinkile. Täna rubriigis "Kandke RocketChip üle vähemtuntud Hiina plaadile Cycloniga" näete töötavat konsooli. Protsess venis veidi: ma juba arvasin, et saan kiiresti Linuxi üles ja edasi liikuda, kuid mitte seekord. Selles osas pakun vaadata U-Booti, BBL-i ja algama üritusi Linuxi tuuma initsialiseerimiseks. Kuid konsool on — U-Booti konsool ja üsna arenenud, sisaldades palju sellest, mida ootate korralikult töötavalt konsoolilt.

Riistvaras lisandub SD-kaart, mis on ühendatud SPI liidese kaudu, samuti UART. Tarkvaras BootROM asendatakse xip . Tundub, et sdboot ja tegelikult lisatakse järgmised laadimisetapid (SD-kaardil).

Riistvara meetodite täiustamine

Nii, ülesanne: tuleb minna "suurema" tuuma ja ühendada UART (Raspberry'lt) ning SD-adapter (kasutati mingit Catalexi plaati kuue piniga: GND, VCC, MISO, MOSI, SCK, CS).

Tegelikult oli kõik üsna lihtne. Kuid enne, kui seda mõistsin, viskas mind veidi pooleldi: pärast eelmist korda otsustasin, et pean taas lihtsalt segama sisse Süsteem midagi sarnast HasPeripheryUART (ja vastavas seadistuses), sama SD-kaardiga — ja kõik on valmis. Siis otsustasin vaadata, kuidas see on realiseeritud "tõsises" disainis. Nii, mis meil siin tõsise kohta on? Arty, ilmselt, ei sobi — jääb hirv kõigele unleahshed.DevKitConfigs. Ja ootamatult avastasin, et seal on igal pool mingid overlayd, mis lisatakse võtmeargumentide kaudu. Ma aiman, et see on tõenäoliselt väga paindlik ja konfigureeritav, kuid mul oleks vaja vähemalt midagi, et alustada... Kuid teil ei ole midagi sarnast, vaid pisut lihtsamat ja konarlikumat? Siin ma komistasin vera.iofpga.FPGAChip Microsemi FPGA ja kohe kopeerisin tsitaate, proovisin teha oma rakendust sarnaselt, õnneks oli siin enam-vähem kogu "emaplaatide tasakaalustus" ühes failis.

Selgus, et tegelikult peab lihtsalt lisama System.scala read

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

Rea klassi kehake Süsteem lisab teavet selle sageduse kohta, millega see meie SoC osa töötab, dts-faili. Mida ma aru saan, on DTS/DTB staatiline analoog plug-and-play tehnoloogiale siseseadmetes: dts- kirjelduste puu kompileeritakse binaarseks dtb-failiks ja edastatakse laadijale, et tuum saaks korralikult riistvara seadistada. Mis on huvitav, ilma reaväli tlclock kõik sünteesitakse suurepäraselt, kuid BootROM-i kompileerida ei saa (tuletan meelde, et nüüd on see juba sdboot) — kompileerimise käigus analüüsib ta dts-faili ja loob päise makro TL_CLK, mille abil saab ta õigesti seadistada sageduse jagureid välistes liidetes.

Samuti tuleb veidi muuta "juhendit":

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

Registriketid on ausalt öeldes lisatud lihtsalt sarnastest kohtadest algses koodis. Tõenäoliselt peavad nad kaitsma metastabiilsuse. Võib-olla on mõnedes plokkides juba oma kaitse, kuid soovin esmalt käivitada vähemalt "kvaliteetsel tasemel". Minu jaoks huvitavam küsimus on, miks MISO ja MOSI on erinevates dq? Ответа я пока так и не нашёл, но, похоже, остальной код рассчитывает именно на такое подключение.

Füüsiliselt määrasin ma lihtsalt disaini väljundid vabade kontaktide peale ja viisin pingeteguri valimise jumperi 3.3V peale.

SD-adapter

Ülevaade ülalt:

Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Ülevaade alt:

Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Tarkvara osa tõrgete tõrkeotsing: tööriistad

Alustame olemasolevate tõrkeotsingute tööriistade ja nende piirangute arutamist.

Minicom

Esiteks peame me kuidagi lugema, mida laadija ja tuum väljastavad. Selleks vajame Linuxis (antud juhul RaspberryPi peal) programmi Minicom. Üldiselt sobib iga programm, mis töötab sarjaliidese portidega.

Pange tähele, et seadme porti nime tuleb käivitamisel määrata kui -D /dev/ttyS0 — pärast valikut -D. Peamine teave: väljumiseks kasutage Ctrl-A, X. Mul oli tõesti juhtum, kui see kombinatsioon ei töötanud — sel juhul saab naaber SSH seansist lihtsalt öelda killall -KILL minicom.

On Raspberry Pi, there is another feature. Specifically, there are two UARTs, and both ports can be used for something: one for Bluetooth, while the other outputs the kernel console by default. Fortunately, this behavior can be reconfigured. according to this manual..

Memory rewriting.

During debugging, to test the hypothesis, I sometimes had to load the bootloader (sorry) into RAM directly from the host. Maybe it can be done directly from GDB, but I ultimately took the simpler route: I copied the required file to the Raspberry and forwarded port 4444 (telnet from OpenOCD) via SSH, using the command load_image.When you execute it, it seems like everything is frozen, but actually it's not asleep, it's just blinking slowly.: it loads the file, just doing it at a speed of a few kilobytes per second.

Features of setting breakpoints.

Probably, many have not thought about this when debugging ordinary programs, but breakpoints are not always set in hardware. Sometimes setting a breakpoint involves temporarily writing a special instruction at the desired location directly in machine code.For example, that's how the standard command b in GDB worked for me. Here’s what follows from this:

  • you cannot set a breakpoint inside BootROM because ROM
  • you can set a breakpoint on code loaded into RAM from the SD card, but you need to wait until it is loaded. Otherwise, we won't overwrite a piece of code, but the bootloader will overwrite our breakpoint.

I am sure you can explicitly request to use hardware breakpoints, but they are limited in number in any case.

Quickly replacing BootROM.

At the beginning of debugging, there is often a desire to modify BootROM and try again. But there’s a problem: BootROM is part of the design loaded into the FPGA, and its synthesis takes a few minutes (and this is after almost instantaneous compilation of the BootROM image itself from C and Assembler...). Fortunately, everything is actually much faster:the sequence of actions is as follows:

  • regenerate bootrom.mif (I switched to MIF instead of HEX because I always had some issues with HEX, and MIF is the native Altera format).
  • in Quartus, say Processing -> Update Memory Initialization File
  • under Assembler (in the left column of Tasks), command Start again.

The whole process takes just a couple of dozen seconds.

Preparing the SD card.

Siin on kõik suhteliselt lihtne, kuid tuleb varuda kannatust ja umbes 14 Gb kettaruumi:

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

Pärast seda tuleb sisestada puhas, täpsemalt öeldes, mitte midagi vajalikku sisaldav SD-kaart ja teha

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

… kus sdX — seadme nimi kaardile. KUIDAS: kaardilt andmed kustutatakse, kirjutatakse üle ja muul moel! Tõenäoliselt ei tasuks kogu ülesehitust teha sudo, sest siis kuuluvad kõik ülesehituse artefaktid root, ja ülesehitust tuleb teha sudo korralikult.

Lõpuks on meil kaart, mis on jaotatud GPT-sse neljaks osaks, millest ühes on FAT-ga uEnv.txt ja laadimisvõime FIT formaadis (see sisaldab mitmeid allpildi, igaühel oma laadimisadressiga), teine osa on puhas, mis tuleb vormindada Ext4 Linuxile. Veel kaks osa on müstilised: ühes asub U-Boot (tema nihke, kui ma õigesti aru saan, on BootROM-is sisse kirjutatud), teises tundub, et on tema keskkonnamuutujid, kuid ma neid praegu ei kasuta.

Tase esimene, BootROM

Rahva tarkus ütleb: "Kui programmeerimises on trall, siis elektroonikas on see veel koos tulekustutiga." Asi pole isegi selles, et korra olin ma peaaegu plaati põletanud, mõeldes, et "Noh, GND on ju sama madal tase" (näib, et takisti ei oleks kahjuks ära teinud...) Asi on pigem selles, et kui käed ei kasva sealt, siis elektroonika ei lõpeta üllatusi: kui ma panin pistikut plaadile, ei suutnud ma korralikult kontaktide kohale joota — videos näidatakse, kuidas jootetükk laiali valgub kogu ühenduses, ainult et pintsett viibuta, minule aga see „kleepus“ kuidas juhtub. Noh, võib-olla ei olnud jootetükk sobiv jootmistemperatuurile, võib-olla veel midagi... Ühesõnaga, nähes, et mul on juba tosin kontakti, viskasin ma kõik kõrvale ja hakkasin siluda. Ja siis algas müstiline: ühendasin RX/TX UART-ilt, laadisin pühendatud tarkvara — see ütleb

INIT
CMD0
ERROR

Noh, kõik on loogiline — ma ei ühendanud SD-kaardi moodulit. Parandasin olukorra, laadisin firma… Ja vaikus… Mida ma ainult ei mõelnud, aga probleem oli lihtne: mooduli üks väljund tuli ühendada VCC-le. Minu puhul toetas moodul 5V toite, seega palun, ühendasin kaabli, mis tuli moodulist, plaadi vastaspoolele. Lõpuks, halvasti joodetud pistik nihkus, ja Lihtsalt kaotasin UART-kontakti. facepalm.jpg Lühidalt öeldes, "halb pea ei anna jalgadele rahu", aga kõverad käed — peaga…

Lõpuks nägin Minicomis kauaoodatud

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LAADIMINE /

Veelgi enam, laadimisnäitaja liikuda. See toob meelde kooliaastad ja aeglane MinuetOS laadimine disketilt. Ainult, et ketas ei kriuksi.

Probleem on selles, et pärast BOOT sõnumit ei juhtu midagi. Seega, on kõige õigem aeg ühendada OpenOCD Raspberryga, GDB-ga hostis ja vaadata, mis see on.

Esiteks, ühendus GDB-ga näitas kohe, et $pc (programmi loendur, jooksva käsu aadress) lendab 0x0 — ilmselt toimub see pärast mitut viga. Seetõttu, kohe pärast sõnumi edastamist BOOT lisame lõputu tsükli. See pidurdab teda natuke…

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

Selline kaval kood on kasutusel "usaldusväärsuse" nimel: olen kuulnud, et lõputu tsükkel on Undefined Behavior, ja siin kompilaator tõenäoliselt ei arva (tuletan meelde, et 0x10000 asub BootROM).

Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Tundub, et mida veel oodata — karm embedded, mis siin mingid lähtekoodid. Aga siiski, räägiti põgusalt RFID-siltide tööteooriast, samuti avati ja analüüsiti mitmeid tollal kõige levinumaid ja kergesti kätte saadavaid silte. autor silus C-koodi... Kreks-feks-meks:

(gdb) file builds/zeowaa-e115/sdboot.elf
Programmi debugeeritakse juba.
Kas olete kindel, et soovite faili muuta? (y või n) y
Symbolite lugemine builds/zeowaa-e115/sdboot.elf...tehtud.

Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Kuid tuleb laadida mitte MIF-faili ega bin'i, vaid originaalversiooni ELF-formaadis.

Nüüd saab järjekordse katsega aimata aadressi, kus täitmine jätkub (see on veel üks põhjus, miks kompilaator ei pidanud arvama, et tsükkel on lõputu). Käsk

set variable $pc=0xADDR

lubab teha registri väärtuse muutmise jooksvalt (antud juhul — jooksva käsu aadress). Sellega saab muuta ka mälu (ja mälu-kaardistatud registreid) väärtusi.

Lõpuks jõudsin järeldusele (ei ole kindel, et õige), et meil on "sd-kaardi pilt vale süsteemi jaoks", ja liikuda tuleks mitte andmete algusesse, vaid 0x89800 baiti edasi:

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

Võib-olla mõjutas seda ka see, et mul ei olnud käepärast liigset 4Gb kaarti, seega võtsin 2Gb ja asendasin juhuslikult Makefile'is. DEMO_END=11718750 . Tundub, et DEMO_END=3078900 (ärge otsige tähendust konkreetses tähenduses – seda pole, lihtsalt nüüd sobib pilt kaardile).

Teine tase, U-Boot

Nüüd me ikka veel „kukume”, kuid juba õigele aadressile. 0x0000000080089a84. Siin pean tunnistama: tegelikult esitus ei käi „kõikide peatumistega”, vaid on osaliselt kirjutatud juba „hiljem”, seega olen ma siin juba suutnud lisada õige dtb-faili meie SoC-lt, seadistustesse muudatusi teha. HiFive_U-Boot muutuja CONFIG_SYS_TEXT_BASE=0x80089800 (asemel 0x08000000), et laadimisadresse vastaks tegelikule. Laadime nüüd järgmise taseme jaoks teise pildi:

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

Ja näeme:

   │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)                      │

Me hüppame ridade vahel 308 ja 309. Ja ei ole üllatav, arvestades, et $sp sisaldab väärtust 0xfffffffe31cdc0a0. Kahjuks see „põgeneb” pidevalt read 307 tõttu. Seetõttu proovime panna peatuse trap_entry, ja siis minna tagasi 0x80089800 (U-Booti sisenemispunkt), lootes, et see ei nõua registrite õiget seadmist enne üleminekut… Tundub, et see töötab:

(gdb) b trap_entry
Peatus 1 aadressil 0x80089a80: failis \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S, rida 308.
(gdb) set variable $pc=0x80089800
(gdb) c
Jätkamine.

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

Mitte just parim stack pointer, otse öeldes: osutab üldse mööda RAM-i (kui meil pole veel aadresside tõlget, kuid looda lihtsale variandile).

Proovime asendada pointeri 0x881cf950. Lõpuks jõuame tõdemuseni, et handle_trap kutsutakse ja kutsutakse, samal ajal jõudes _exit_trap argumentidega epc=2148315240 (pärisnumbris):

(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

Seame breakpoint 'ilma strnlen, then we continue and see:

(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/interr 92
#7 handle_trap (mcause=, epc=, regs=) at arch/riscv/lib/interr 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

Tundub nagu _exit_trap proovib anda teavet, mis puudutab toimunud erandit, aga tal ei õnnestu. Näib, et meie allikad ei kuvata taas. seadistame kaustad .. /freedom-u-sdk/HiFive_U-Boot/ O! Nüüd kuvatakse!

Noh, käivitame uuesti ja näeme, et virnastuse jälg näitab algse probleemi põhjuse, mis põhjustas esimese vea (mcause == 5). Kui ma õigesti aru sain, mis seal öeldakse siin lehelt 37, siis see erand tähistab Laadi juurdepääsu viga. Tundub, et põhjus on siin,

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 omab see vale ja sees board_init_f_init_reserve tekib vea. Tundub, et siin on süüdlane: muutuja, millel on selge nimi CONFIG_SYS_INIT_SP_ADDR. See on määratletud failis HiFive_U-Boot/include/configs/HiFive-U540.hMõnes mõttes mõtlesin isegi, et võib-olla ei tasu enam laadijat protsessori jaoks edasi arendada — äkki on lihtsam protsessorit veidi kohandada? Kuid siis märkasin, et see näeb rohkem välja nagu artefakt, mis on tingitud valedest seadistustest teise mälukonfiguratsiooni jaoks, ja on võimalik proovida teha nii:#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 */

Mõnes mõttes jõudis tugede arv kriitilisse punkti. tehnilist kinnitust oli jõudnud kriitilisse punkti. Pärast väikest vaeva jõudsin järeldusele, et on hädavajalik teha korrektne port oma plaadile. Selleks on vaja kopeerida ja kohandada meie konfiguratsiooni mõningaid faile.

Noh, umbes niimoodi

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

    Esmane tugi Zeowaa A-E115FB plaadi jaoks

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

Üksikasju saab vaadata hoidlad.

Nagu selgus, on sellel SiFive plaadil mõnede seadmete registrid teistel aadressidel. Samuti selgus, et U-Boot konfigureeritakse juba tuntud Linuxi südamikule sarnase Kconfig mehhanismiga — näiteks on võimalik käskida make menuconfig, ja teie ette kerkib mugav tekstipõhine liides koos parameetrite kirjelduste näitamisega. ? ja jne. Ühesõnaga, kombineerides kahe plaadi kirjelduse, onnistus mul luua kolmanda plaadi kirjeldus, jättes välja kõik uhked PLL ümberkorraldused (ilmselt on see seotud hostarvuti juhtimisega PCIe kaudu, aga ma ei ole selles kindel), sain mingisuguse püsivara, mis õigete tingimuste korral Marsil edastas mulle UARTi kaudu teadet, millise commit'i hash'ist see oli ehitatud, ja kui palju mul DRAM'i on (aga selle info panin ma ise ju pealkirja sisse).

Kahjuks tavaliselt pärast seda plaat enam ei reageeri protsessori JTAG'i kaudu, ja SD-kaardilt bootimine – noh, kahjuks on see minu konfiguratsioonis aeglane. Teisest küljest, mõnikord andis BootROM teada, et VIGA, ei suutnud käivitada, ja kohe hüppas välja U-Boot. Siis taipasin: ilmselt pärast restart'i bitstream'i PLD mälu ei kustutata, ei jõua see "dekonfigureerida" jne. Lühidalt, kui kuulen teadet LAADIMINE \/ , saan debuggeriga ühendada ja käskin set variable $pc=0x80089800, mööndes seega selle pika laadimise (loomulikult eeldusel, et see eelmine kord katkestas piisavalt vara ja ei jõudnud originaalkoodi peale midagi laadida).

Üleüldiselt, kas on normaalne, et protsessor hangub täielikult ja JTAG-debugger ei suuda sellega ühendada, andes teadet

Viga: ei suuda peatada hart 0
Viga:   dmcontrol=0x80000001
Viga:   dmstatus =0x00030c82

Oota! Olen seda juba näinud! Midagi sellist juhtub TileLink'i deadlock'i korral, ja ma ei usalda mälu kontrolleri autorit – kirjutasin selle ju ise... Üks hetk, pärast esimest edukat protsessori ümberkokkuvebemist pärast kontrolleri redigeerimist, märkasin:

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LAADIMINE
BOOT

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

DRAM:  1 GiB
MMC:
ENNE KESKKONNA LAADIMISTENNE FDTKONTROLLAADRESSENNE LAADIMISEAADRESSSis:    seeria
Välja:   seeria
Viga:   seeria
Vajuta mis tahes klahvi autobooti peatamiseks:  3

Selle kummalise rea peale Sis: seeria Ärge pöörake tähelepanu — see olin mina, kes püüdis külmunud protsessoriga aru saada, kas see töötab keskkonnaga korrektselt. Mis tähendab „Juba kümme minutit on niimoodi kinni”? Kas see suutis vähemalt relokatsiooniga edasi liikuda ja pääseda laadimismenüüsse! Väike kõrvalepõige: kuigi U-Boot laaditakse esimesse 2^24 baiti SD-kaardilt, kopeerib see pärast käivitamist end kaugele aadressile, kas siis konfigureerimispealdise järgi, või lihtsalt operatiivmälu kõrgematesse aadressidesse, teostab ELF-sümbolite relokatsiooni ja edastab juhtimise sinna. Seega: tundub, et see tase on ületatud ja boonuseks saime protsessor, mis ei külmu täielikult pärast seda.

Nii et, miks kell ei tööta? Tundub, et kellad ei liigu üldse…

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

Aga mis siis, kui näppude abil kella käike keerata?

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

Siis:

Rohkem kui üks klahv peatab autobooti:  0
MMC_SPI: 0 aadressil 0:1 hz 20000000 režiim 0

Kokkuvõte: kellad ei tööta. Tõenäoliselt on see põhjus, miks klaviatuurilt sisend ei tööta:

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:
        /* Esimene sümbol ANSI escape'i jada 'e' */
        if (c == 'e') {
            *esc = 1;
            *key = KEY_NONE;
        }
        break;
    case 1:
        /* Teine sümbol ANSI '[' */
        if (c == '[') {
...

Probleem oli selles, et ma natuke liialdaselt muutsin: ma lisasin protsessori konfiguratsioonifaili võtme:

  case DTSTimebase => BigInt(0)

… lähtudes sellest, et kommentaarides oli öeldud „kui te ei tea — jätke 0“. Ja tõepoolest WithNBigCores asetati see täpselt 1 MHz'iks (nagu muide, oli ka U-Booti konfiguratsioonis näidatud). Kuid ma olin, pagana, hoolikas ja põhjalik: seal ma ei tea, siin 25 MHz! Lõppkokkuvõttes ei toiminud miski. Eemaldasin oma „parandused“ ja...

Rohkem kui üks klahv peatab autobooti:  0
MMC_SPI: 0 aadressil 0:1 hz 20000000 režiim 0
## Tundmatu partitsioonitabeli tüüp 0
libfdt fdt_path_offset() tagastas FDT_ERR_NOTFOUND
** Ei ole partitsioonitabelit - mmc 0 **
## Teave: sisendi andmete suurus = 34 = 0x22
Käivitan uEnv.txt boot2...
## Viga: "boot2" ei ole määratletud
HiFive-Unleashed #

Saame isegi käske sisestada! Näiteks, natuke nokitsedes, saame lõpuks aru, et peame sisestama mmc_spi 1 10000000 0; mmc part, vähendades SPI sagedust 20 MHz-lt 10 MHz-le. Miks? Noh, konfiguratsioonis oli kirjutatud maksimaalne sagedus 20 MHz, see on seal ikka veel kirjas. Aga kuidas ma aru saan, et liidesed, vähemalt siin, töötavad nii: kood jagab riistvarakompleksi sageduse (minu puhul — kõikjal 25 MHz) sihtsagedusega ja seadeb saadud väärtuse vastavasse juhtregistrisse jaguriks. Probleem on selles, et kui 115200 Hz UART-ile sobib umbkaudu see, mida on vaja, siis kui jagada 25000000 otse 20000000-ga, saadakse 1, st see töötab 25 MHz-l. Võib-olla on see ka normaalne, aga kui piirangud on seatud, siis peavad need kedagi huvitama (aga see ei pruugi olla kindel)… Ühesõnaga, lihtsam on need näitajad kirja panna ja edasi liikuda — kaugele ja, kahjuks, pikaks ajaks. 25 MHz — see ei ole Core i9.

Konsoli väljund

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

Okei, me oleme uuele tasemele üle läinud, kuid see hangub endiselt. Ja vahel viskab ka erandeid. mcause'i näha on võimalik, püüdes koodi antud aadressilt $pc ja pärast si jõuda trap_entry. U-Boot-ile on töötleja, mis suudab välja anda ainult mcause = 0..4, seega valmistuge tsüklisse jääma vale laadimise tõttu. Siin vaatasin konfiguratsioonifaili ja mõtlesin, mida ma muutsin ja meenutasin: seal on ju conf/rvboot-fit.txt kirjutatud:

fitfile=image.fit
# allpool peab vastama sellele, mis on FIT-is (ugha)

Mis siis, viime kõik failid kooskõlla, muutame kerneli käsurea umbes nii, kuna on kahtlus, et SIF0 — see on väljund kuhugi PCIe kaudu:

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

Ja lisaks muudame krüpteerimise algoritmi SHA-256 pealt MD5-ks: krüptograafilist tugevust mul ei ole vaja (veelgi enam, silumise ajal), see tundub äärmiselt aeglane, ja vigade tuvastamiseks laadimise ajal piisab MD5-st. Mis siis lõpuks? Eelmise taseme läbimine muutus märgatavalt kiiremaks (lihtsama krüptimise tõttu) ja järgnev avanes:

...
   Verifying Hash Integrity ... md5+ OK
   Laadimine 0x90a5a758-st 0x82000000-sse
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";
};
   Laadimine Kernel Image ... OK
Kernel käivitamine
3

Aga kellad ei käi...

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

Ups, näib, et kella käigu parandamine osutus platseeboks, kuigi mul siis tundus, et see aitas. Ei, muidugi tuleb korda teha, aga alustame sellest, et keerame käepidemed käsitsi ja vaatame, mis juhtub:

0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=1000000
(gdb) c
Jätkab.
^C
Programm sai signaali SIGINT, katkestus.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=2000000
(gdb) c
Jätkab.
^C
Programm sai signaali SIGINT, katkestus.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=3000000
(gdb) c
Jätkab.

Sel ajal...

   Laadimine Kernel Image ... OK
Kernel käivitamine
3
2
1
0
## Rakenduse käivitamine 0x80000000-st ...

Ei, lähen automatiseerima kellade käiku — võibolla üritab ta seal mingit kalibreerimist teha!

Ja praegune käsu aadress osutab samal ajal kuhugi

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

laaditud Berkeley Boot Loaderi sees. Isiklikult mind häirib see mainimine htif — host interface, mida kasutatakse tuuma tihendatud käivitamiseks (st koostöös host ARM-iga), ma arvasin, et see on standalone. Siiski, kui leida see funktsioon lähtekoodist, siis ei ole kõik nii hull:

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

Ülesanne: käivita kellad

Registrite otsimine CLINT-is viib meid

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

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

Mis on ühendatud RTC-sse või salapärasesse MockAON-i, mille kohta ma algselt mõtlesin: "Nii, mis see siin on? Ebaselge? Lülitan välja!" Kuna ma ei saa endiselt aru, mis see takti maagia seal toimub, teen lihtsalt selle loogika uuesti rakenduse System.scala:

  val rtcDivider = RegInit(0.asUInt(16.W)) // igaks juhuks toetan kuni 16GHz, olen optimist :)
  val mhzInt = p(DevKitFPGAFrequencyKey).toInt
  // Oletame, et sagedus on täisarv megaherzhides
  rtcDivider := Mux(rtcDivider === (mhzInt - 1).U, 0.U, rtcDivider + 1.U)
  outer.clintOpt.foreach { clint =>
    clint.module.io.rtcTick := rtcDivider === 0.U
  }

Liikudes Linux kernel'i suunas

Siin on jutustus juba veninud ja muutunud veidi monotoonseks, seetõttu kirjeldan seda ülevalt alla:

BBL eeldas olemasolu FDT aadressil 0xF0000000, ja ma olen seda juba korrigeerinud! Noh, uurime veel… Leidsin HiFive_U-Boot/arch/riscv/lib/boot.c, asendasin 0x81F00000, mida on näidatud U-Booti laadimisconfiguratsioonis.

Siis BBL kurtis, et mälu pole. Minu tee viis funktsiooni mem_prop, mis riscv-pk/machine/fdt.c: seal sain teada, et fdt ram sõlme tuleb märkida kui device_type = "memory" — siis võibolla tuleb protsessorigeneraatorit hiljem korrigeerida, aga praegu lihtsalt kirjutan käsitsi — olen niikuinii selle faili käsitsi üle kantud.

Nüüd sain sõnumi (esitatud vormindatud kujul, rikka reavahetustega):

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.

Tundub, et kõik vajalikud valikud on määratud. riscv,kernel-start ja riscv,kernel-end DTB-s, aga nullid tõlgendatakse valesti. Silumine query_chosen näitas, et BBL proovib tõlgendada 32-bitist aadressi, kuid sellele sattub paar <0x0 0xADDR>, ja esimene väärtus tundub olevat madalamad bitid. Kirjutasin sektsiooni chosen

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

ja parandasin väärtuste genereerimist: mitte lisada 0x0 esimese elemendiga.

Need 100500 lihtsat sammu aitavad sul lihtsalt ja kergelt näha, kuidas pingviin kukub:

Peidetud tekst

   Kontrollimine Hash Integrity ... md5+ OK
   Laadimine loadables vahemälust 0x90a5a758 kuni 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
valitud {
        linux,initrd-lõpp = ;
        linux,initrd-alguses = ;
        riscv,kerne-lõpp = ;
        riscv,kerne-alguses = ;
        #aadress-cellerid = ;
        #suurus-cellerid = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=\/dev\/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() tagastas FDT_ERR_NOTFOUND
valitud {
        linux,initrd-lõpp = ;
        linux,initrd-alguses = ;
        riscv,kerne-lõpp = ;
        riscv,kerne-alguses = ;
        #aadress-cellerid = ;
        #suurus-cellerid = ;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=\/dev\/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
   Laadimine Kernel Image ... OK
Käivitamine kernelis
3
2
1
0
## Rakenduse käivitamine aadressil 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: Ignores mäluruum 0x80000000 - 0x80200000
[    0.000000] Linuxi versioon 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versioon 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Kolm Juuli 3 21:29:21 MSK 2019
[    0.000000] bootconsole [early0] lubatud
[    0.000000] Algne ramdisk aadressil: 0x(____ptrval____) (16777216 baiti)
[    0.000000] Tsooni vahemikud:
[    0.000000]   DMA32    [mäluaadress 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normaalsed [mäluaadress 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Liikuv tsoon algab iga sõlme jaoks
[    0.000000] Varajased mälu sõlmed
[    0.000000]   sõlm   0: [mäluaadress 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem seadistamine sõlmes 0 [mäluaadress 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Sõlmes 0 on kokku lehekülgi: 261632
[    0.000000]   DMA32 tsoonis: 3577 lehte kasutatud memmap
[    0.000000]   DMA32 tsoonis: 0 lehte reserveeritud
[    0.000000]   DMA32 tsoonis: 261632 lehte, LIFO partii:63
[    0.000000] tarkvara IO TLB: kaardistatud [mäluaadress 0xbb1fc000-0xbf1fc000] (64MB)

(BBL kuvab embleemi, ja see, mis on ajatempleid sisaldav, on kernel).

Õnneks, ma ei tea, kuidas mujal, kuid RocketChip'is saab JTAG-i kaudu debugeerijat ühendades karistusi otse kinni püüda — debugeerija peatub just selles kohas.

Programm sai signaali SIGTRAP, jälgimise/puruste karistus.
0xffffffe0000024ca in ?? ()
(gdb) bt
#0  0xffffffe0000024ca in ?? ()
Tagasiviide peatub: eelmine raam on sama, mis see raam (rikutud virn?)
(gdb) fail work\/linux\/vmlinux
Programm on juba debugeerimise all.
Kas olete kindel, et soovite faili muuta? (y või n) y
Sümbolite lugemine failist work\/linux\/vmlinux...valmis.
(gdb) bt
#0  0xffffffe0000024ca in setup_smp () at \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/linux\/arch\/riscv\/kernel\/smpboot.c:75
#1  0x0000000000000000 in ?? ()
Tagasiviide peatub: raam ei salvestanud PC-d

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); // < TE OLETE SIIN
}

Nagu öeldakse vanas anekdoodis, CPU ei leitud, käivitamine tarkvaraga emulatsiooniga. Või nagu, ei running. Eksisime protsessori ühes tuumas.

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

Hea kommentaaris linux/arch/riscv/kernel/setup.c — selline Tom Sawyer'i meetodiga aiaga värvimine. Ühesõnaga, täna pole mingil põhjusel võitjaid leidunud, auhind edasilükkub järgmisse loosimisse…

Sellega lõpetan juba niigi veninud artikli.

Jätkub. Selles on lahing kavalate vigadega, mis suudavad peituda, kui sellele ettevaatlikult singlestep-iga läheneda.

Tekstiline skrinnikastimine laadimisest (väline link):
Osa 3: Peaaegu laadime Linuxi SD-kaardilt RocketChipile

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster