Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin В edellinen osa toteutettiin enemmän tai vähemmän toimiva muistiohjain, tai pikemminkin Quartuksen IP Core -kääre, joka on sovitin TileLinkille. Tänään osiossa "Siirrämme RocketChipin vähän tunnetulle kiinalaiselle levylle, jossa on Cyclone" näet toimivan konsolin. Prosessi kesti hieman kauemmin: Ajattelin jo käynnistää Linuxin nopeasti ja jatkaa eteenpäin, mutta niin ei käynyt. Tässä osassa ehdotan, että tarkastellaan U-Bootin, BBL:n käynnistysprosessia ja Linux-ytimen arkoja alustusyrityksiä. Mutta on konsoli - U-Boot, ja melko edistynyt, jossa on paljon sitä, mitä voit odottaa täysivaltaiselta konsolilta.

Laitteistoon tulee SPI-liitännän kautta kytketty SD-kortti sekä UART. Ohjelmistoosassa BootROM korvataan xip päälle sdboot ja itse asiassa seuraavat latausvaiheet on lisätty (SD-kortille).

Laitteiston viimeistely

Joten, tehtävä: sinun on vaihdettava "isoon" ytimeen ja kytkettävä UART (Vadelmalta) ja SD-sovitin (käytimme Catalexin korttia, jossa on kuusi nastaa: GND, VCC, MISO, MOSI, SCK, CS) .

Periaatteessa kaikki oli melko yksinkertaista. Mutta ennen kuin tajusin tämän, minua heitettiin hieman puolelta toiselle: edellisen kerran päätin, että minun on vain sekoitettava System vähän niin kuin HasPeripheryUART (ja toteutus vastaavasti), sama SD-kortille - ja kaikki on valmis. Sitten päätin nähdä, kuinka se toteutettiin "vakavassa" suunnittelussa. Joten mitä vakavaa tässä on? Arty ei ilmeisesti sovi - hirviö jää unleahshed.DevKitConfigs. Ja yhtäkkiä kävi ilmi, että kaikkialla oli peittokuvia, jotka lisättiin parametreilla avaimilla. Luulen, että tämä on luultavasti erittäin joustava ja konfiguroitavissa, mutta haluaisin ainakin ajaa jotain ensin... Eikö sinulla ole sama asia, vain yksinkertaisempi ja ärsyttävämpi? .. Silloin törmäsin vera.iofpga.FPGAChip Microsemi FPGA:lle ja purin sen heti lainauksia varten ja yritin tehdä omaa toteutusta analogisesti, onneksi on enemmän tai vähemmän koko "emolevyn asettelu" yhdessä tiedostossa.

Kävi ilmi, että sinun tarvitsee vain lisätä System.scala linja

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

Viiva luokan rungossa System lisää tietoa taajuudesta, jolla tämä SoC:n osa toimii dts-tiedostoon. Ymmärtääkseni DTS/DTB on sulautettujen laitteiden plug-and-play-tekniikan staattinen analogi: dts-kuvauspuu käännetään binääriseksi dtb-tiedostoksi ja käynnistyslatain siirtää sen ytimeen, jotta se voi määrittää laitteisto. Mielenkiintoista, ilman linjaa tlclock kaikki syntetisoituu täydellisesti, mutta BootROMin kääntäminen (muistutan, nyt tämä on jo sdboot) ei toimi - käännösprosessin aikana se jäsentää dts-tiedoston ja luo otsikon makrolla TL_CLK, jonka ansiosta hän pystyy konfiguroimaan ulkoisten liitäntöjen taajuusjakajat oikein.

Sinun on myös korjattava hieman "johdotusta":

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
}

Rekisteriketjut on rehellisesti sanottuna lisätty yksinkertaisesti analogisesti joidenkin muiden alkuperäisen koodin paikkojen kanssa. Todennäköisesti niiltä pitäisi suojautua metastabiilisuus. Ehkä sisään jotkut lohkoilla on jo oma suojansa, mutta ensin haluan käynnistää sen ainakin "laadukkaalla tasolla". Minulle kiinnostavampi kysymys on, miksi MISO ja MOSI roikkuvat eri tavalla dq? En ole vielä löytänyt vastausta, mutta näyttää siltä, ​​että muu koodi perustuu juuri tällaiseen yhteyteen.

Fyysisesti annoin yksinkertaisesti suunnittelunastat lohkon vapaisiin koskettimiin ja siirsin jännitteen valinnan hyppyjohtimen 3.3 V:iin.

SD-sovitin

Näkymä ylhäältä:

Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Alhaalta katsottuna:

Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Ohjelmiston virheenkorjaus: Työkalut

Puhutaanpa ensin käytettävissä olevista virheenkorjaustyökaluista ja niiden rajoituksista.

Minicom

Ensin meidän on jotenkin luettava, mitä käynnistyslatain ja ydin tuottavat. Tämän tekemiseksi Linuxissa (tässä tapauksessa RaspberryPi:ssä) tarvitsemme Minicom-ohjelman. Yleisesti ottaen mikä tahansa sarjaportin kanssa toimiva ohjelma käy.

Huomaa, että käynnistyksen yhteydessä portin laitteen nimi on määritettävä muodossa -D /dev/ttyS0 - vaihtoehdon jälkeen -D. No, tärkein tieto: poistu, käytä Ctrl-A, X. Minulla oli itse asiassa tapaus, jossa tämä yhdistelmä ei toiminut - sitten voit sanoa yksinkertaisesti viereisestä SSH-istunnosta killall -KILL minicom.

On vielä yksi ominaisuus. Tarkemmin sanottuna RaspberryPissä on kaksi UART-porttia, ja molemmat portit voidaan jo mukauttaa johonkin: toinen Bluetoothille, toinen oletuksena tuottaa ytimen konsolin. Onneksi tämä käyttäytyminen voidaan ohittaa tämän ohjekirjan mukaan.

Muistin uudelleenkirjoitus

Vianjäljityksessä minun oli joskus pakko testata hypoteesia lataa käynnistyslatain (anteeksi) RAM-muistiin suoraan isännältä. Ehkä tämän voi tehdä suoraan GDB:stä, mutta loppujen lopuksi seurasin yksinkertaista polkua: kopioin tarvittavan tiedoston Raspberrylle, välitin myös portin 4444 SSH:n kautta (telnet OpenOCD:stä) ja käytin komentoa load_image. Kun teet sen, näyttää siltä, ​​​​että kaikki on jäässä, mutta itse asiassa "se ei nuku, se vain vilkkuu hitaasti": Se lataa tiedoston, se vain tekee sen nopeudella pari kilotavua sekunnissa.

Katkaisupisteiden asennuksen ominaisuudet

Monien ei luultavasti ole tarvinnut ajatella tätä tavallisten ohjelmien virheenkorjauksen yhteydessä, mutta keskeytyskohtia ei aina aseteta laitteistossa. Joskus keskeytyskohdan asettaminen edellyttää erityisohjeiden kirjaamista tilapäisesti oikeaan paikkaan suoraan konekoodiin. Esimerkiksi standardikomentoni toimi näin b GDB:ssä. Seuraavassa on seuraavat asiat:

  • BootROMin sisään ei voi laittaa pistettä, koska ROM
  • Voit asettaa keskeytyskohdan SD-kortilta RAM-muistiin ladatulle koodille, mutta sinun on odotettava, kunnes se ladataan. Muuten emme kirjoita koodinpätkää uudelleen, mutta latausohjelma kirjoittaa uudelleen keskeytyspisteemme

Olen varma, että voit nimenomaisesti pyytää käyttämään laitteiston keskeytyskohtia, mutta niitä on kuitenkin rajoitettu määrä.

Nopea BootROM-vaihto

Virheenkorjauksen alkuvaiheessa halutaan usein korjata BootROM ja yrittää uudelleen. Mutta on ongelma: BootROM on osa FPGA:lle ladattua suunnittelua, ja sen synteesi on muutaman minuutin kysymys (ja tämä tapahtuu sen jälkeen, kun itse BootROM-kuva on käännetty melkein välittömästi C:stä ja Assembleristä...). Onneksi todellisuudessa kaikki paljon nopeampi: toimintojen järjestys on seuraava:

  • regeneroi bootrom.mif (vaihdin MIF:ään HEX:n sijaan, koska minulla on aina ollut ongelmia HEX:n kanssa, ja MIF on Alterin alkuperäinen muoto)
  • Quartusissa sanotaan Processing -> Update Memory Initialization File
  • Assembler-kohdassa (Tasks-kohdan vasemmassa sarakkeessa) -komento Aloita uudelleen

Kaikesta kaikesta - parikymmentä sekuntia.

SD-kortin valmistelu

Kaikki täällä on suhteellisen yksinkertaista, mutta sinun on oltava kärsivällinen ja sinulla on oltava noin 14 Gt levytilaa:

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

Sen jälkeen sinun on asetettava puhdas, tai pikemminkin sellainen, joka ei sisällä mitään tarpeellista, SD-kortti ja suoritettava

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

… Missä sdX — kortille määritetty laite. HUOMIO: kortin tiedot poistetaan, ylikirjoitetaan ja yleensä! Koko kokoonpanoa tuskin kannattaa tehdä alhaalta sudokoska silloin kaikki rakennetut esineet kuuluvat root, ja kokoonpano on tehtävä alhaalta sudo jatkuvasti.

Tuloksena on GPT:ssä merkitty kortti, jossa on neljä osiota, joista yhdessä on FAT uEnv.txt ja käynnistyskuva FIT-muodossa (sisältää useita alikuvia, jokaisella on oma latausosoite), toinen osio on tyhjä, sen oletetaan olevan alustettu Ext4 Linuxille. Vielä kaksi jaksoa - salaperäinen: Yhdessä U-Boot elää (sen offset on ymmärtääkseni kovakoodattu BootROMiin), toisella sen ympäristömuuttujat näyttävät elävän, mutta en käytä niitä vielä.

Taso yksi, BootROM

Suosittu viisaus sanoo: "Jos ohjelmoinnissa tanssitaan tamburiinilla, niin elektroniikassa tanssitaan myös sammuttimella." Kyse ei ole edes siitä, että kerran melkein poltin laudan ja päätin, että "No, GND on sama matala taso." (ilmeisesti vastus ei haittaisikaan...) Kyse on enemmänkin siitä, että jos kädet eivät kasva sieltä, niin elektroniikka ei lakkaa tuomasta yllätyksiä: liitintä levylle juotettaessa en silti pystynyt juottamaan kontakteja kunnolla - videolta näkyy kuinka juote leviää suoraan koko liitännän yli, käytä vain juotoskolvia, Minulle hän "löi" satunnaisesti. No, ehkä juotos ei ollut sopiva juotosraudan lämpötilaan, ehkä jotain muuta... Yleisesti ottaen, kun näin, että minulla on jo kymmenkunta kontaktia, luovutin ja aloin virheenkorjauksen. Ja sitten se alkoi salaperäinen: Yhdistin RX/TX:n UART:sta, lataan laiteohjelmiston - se sanoo

INIT
CMD0
ERROR

No, kaikki on loogista - en yhdistänyt SD-korttimoduulia. Korjaamme tilanteen, lataamme laiteohjelmiston... Ja hiljaisuus... Miksi en muuttanut mieltäni, mutta pieni laatikko avautui juuri: yksi moduulin nasta piti kytkeä VCC:hen. Minun tapauksessani moduuli tuki 5V virransyöttöä, joten kahdesti ajattelematta liitin moduulista tulevan johdon levyn vastakkaiselle puolelle. Tämän seurauksena vinoon juotettu liitin meni vinoon ja UART-yhteys yksinkertaisesti katosi. facepalm.jpg Yleensä "huono pää ei anna lepoa jaloille", ja vinot kädet eivät anna lepoa päälle...

Tuloksena näin kauan odotetun

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

Lisäksi se liikkuu ja latausilmaisin pyörii. Muistan heti kouluaikani ja MinuetOS:n rauhassa lataamisen levykkeeltä. Ellei taajuusmuuttaja hiero.

Ongelmana on, että BOOT-viestin jälkeen mitään ei tapahdu. Tämä tarkoittaa, että on aika muodostaa yhteys OpenOCD:n kautta Raspberryen, isäntäkoneen GDB:hen ja nähdä, mikä se on.

Ensinnäkin yhteyden muodostaminen GDB:llä osoitti sen välittömästi $pc (ohjelmalaskuri, nykyisen käskyn osoite) lentää 0x0 - Tämä tapahtuu todennäköisesti useiden virheiden jälkeen. Siksi heti viestin lähettämisen jälkeen BOOT Lisätään loputon silmukka. Tämä viivyttää häntä jonkin aikaa...

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

Tällaista hankalaa koodia käytetään "luotettavuuden vuoksi": kuulin jostain, että loputon silmukka on määrittelemätön käyttäytyminen, mutta kääntäjä tuskin arvaa (muistutan, että 0x10000 sijaitsee BootROM).

Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Vaikuttaa siltä, ​​mitä muuta odottaa - ankaria upotettuja, millaisia ​​lähdekoodeja on olemassa? Mutta sisään tuo artikkeli kirjoittaja teki virheenkorjauksen C-koodista... 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.

Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Sinun tarvitsee vain ladata ei MIF-tiedostoa tai bin, vaan alkuperäinen versio ELF-muodossa.

Nyt voit arvata n:nnellä yrityksellä osoitteen, jossa suoritus jatkuu (tämä on toinen syy, miksi kääntäjän ei olisi pitänyt arvata silmukan olevan ääretön). Tiimi

set variable $pc=0xADDR

mahdollistaa rekisteriarvon muuttamisen lennossa (tässä tapauksessa nykyisen käskyn osoitteen). Sen avulla voit muuttaa muistiin (ja muistikartoitettuihin rekistereihin) kirjoitettuja arvoja.

Lopulta tulin siihen tulokseen (en ole varma, mikä on oikein), että meillä on "SD-korttikuva väärästä järjestelmästä", ja meidän ei tarvitse mennä ladattujen tietojen alkuun, vaan 0x89800 tavua lisää:

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

Ehkä tähän vaikutti myös se, että kun ei ollut turhaa 4Gb korttia käsilläni, otin 2Gb kortin ja vaihdoin sen Makefileen satunnaisesti. DEMO_END=11718750 päälle DEMO_END=3078900 (älä etsi merkitystä tietystä merkityksestä - sellaista ei ole, se on vain, että nyt kuva on asetettu kortille).

Taso kaksi, U-boot

Nyt ollaan vielä "putoamassa", mutta olemme jo oikeassa paikassa 0x0000000080089a84. Tässä minun on myönnettävä: itse asiassa esitys ei mene "kaikilla pysähdyksillä", vaan on osittain kirjoitettu "jälkeen", joten täällä olen jo onnistunut syöttämään oikean dtb-tiedoston SoC:stämme, korjaa se asetuksissa HiFive_U-Boot muuttuja CONFIG_SYS_TEXT_BASE=0x80089800 (eikä 0x08000000), jotta latausosoite vastaa todellista osoitetta. Nyt lataamme seuraavan tason kartan, toisen kuvan:

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

Ja näemme:

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

Lisäksi hyppäämme rivien 308 ja 309 välillä. Eikä se ole yllättävää, kun otetaan huomioon, että sisään $sp on tarkoitus 0xfffffffe31cdc0a0. Valitettavasti se myös "juoksee karkuun" jatkuvasti linjan 307 takia. Yritetään siis asettaa keskeytyskohta trap_entryja palaa sitten kohtaan 0x80089800 (U-Bootin sisääntulopiste), ja toivotaan, ettei se vaadi rekistereiden asettelua oikein ennen hyppäämistä... Näyttää toimivan:

(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

Pinoosoitin on rehellisesti sanottuna niin ja näin: se osoittaa ohittaen RAM-muistin kokonaan (ellei meillä tietenkään ole vielä osoitekäännöstä, mutta toivotaan yksinkertaista vaihtoehtoa).

Yritetään korvata osoitin sanalla 0x881cf950. Tämän seurauksena tulemme siihen tulokseen handle_trap soitti ja soitti, ja samaan aikaan menemme sisään _exit_trap argumentin kanssa epc=2148315240 (desimaalilukuina):

(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

Aseta keskeytyskohta strnlen, jatkamme ja katsomme:

(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

Näyttää olevan, _exit_trap haluaa antaa virheenkorjaustietoja tapahtuneesta poikkeuksesta, mutta hän ei voi. Joten jotenkin lähteitämme ei näytetä uudelleen. set directories ../freedom-u-sdk/HiFive_U-Boot/ NOIN! Nyt esillä!

Suoritetaan se uudelleen ja katsotaan pinon jäljityksestä alkuperäisen ongelman syy, joka aiheutti ensimmäisen virheen (mcause == 5). Jos ymmärsin oikein mitä kirjoitettiin täällä sivulla 37, tämä poikkeus tarkoittaa Load access fault. Syy näyttää olevan tässä

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 on sama väärä merkitys ja sisällä board_init_f_init_reserve tapahtuu virhe. Tämä näyttää olevan syyllinen: muuttuja, jolla on yksiselitteinen nimi CONFIG_SYS_INIT_SP_ADDR. Se on määritelty tiedostossa HiFive_U-Boot/include/configs/HiFive-U540.h. Jossain vaiheessa jopa ajattelin, että ehkä, no, pitäisikö minun lisätä prosessorille käynnistyslatain - ehkä olisi helpompi korjata prosessoria vähän? Mutta sitten huomasin, että se oli enemmän kuin artefakti, joka ei ollut täysin valmis#if 0-erityiset asetukset toiselle muistikokoonpanolle, ja voit yrittää tehdä tämän:

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

Jossain vaiheessa kainalosauvojen määrä tekniset kiinnikkeet on saavuttanut kriittisen pisteen. Pienen kamppailun jälkeen tulin tarpeeseen tehdä oikea portti levylleni. Tätä varten meidän on kopioitava ja säädettävä useita tiedostoja kokoonpanoomme sopivaksi.

No, suunnilleen, tässä on pieni pöytä

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

Yksityiskohdat löytyvät osoitteesta arkistot.

Kuten kävi ilmi, tällä SiFive-kortilla joidenkin laitteiden rekistereillä on eri osoitteet. Kävi myös ilmi, että U-Boot on määritetty Kconfig-mekanismilla, joka on jo tuttu Linux-ytimestä - voit esim. make menuconfig, ja edessäsi tulee kätevä tekstikäyttöliittymä, joka näyttää parametrien kuvaukset by ? jne. Yleisesti ottaen, kun on mukulannut yhteen kuvauksen kolmannesta kahden levyn kuvauksista, heittäen sieltä kaikenlaisia ​​​​tekeellisiä PLL-uudelleenkonfigurointeja (ilmeisesti tämä liittyy jotenkin ohjaukseen isäntätietokoneesta PCIe: n kautta, mutta tämä ei ole varmaa) , Sain jonkinlaisen laiteohjelmiston, joka oikean sään Marsissa antoi minulle UART:n kautta viestin mistä commit hashista se on koottu ja kuinka paljon DRAMia minulla on (mutta kirjoitin tämän tiedon otsikkoon).

Harmi vain, että tämän jälkeen kortti yleensä lakkasi vastaamasta prosessorin JTAGin kautta, ja lataaminen SD-kortilta ei valitettavasti ole nopeaa minun asetuksissani. Toisaalta joskus BootROM antoi viestin, että ERROR, ei käynnistynyt, ja U-Boot ilmestyi välittömästi. Silloin se valkeni minulle: ilmeisesti, kun bittivirta on käynnistetty uudelleen FPGA:han, muistia ei tyhjennetä, sillä ei ole aikaa "harjoitella" jne. Lyhyesti sanottuna voit yksinkertaisesti, kun viesti tulee näkyviin LOADING / muodosta yhteys debuggeriin ja komentoon set variable $pc=0x80089800, ohittaen näin tämän pitkän latauksen (tietenkin olettaen, että viime kerralla se meni rikki niin aikaisin, ettei se ehtinyt ladata mitään alkuperäisen koodin päälle).

Onko muuten normaalia, että prosessori jähmettyy kokonaan eikä JTAG-debuggeri voi muodostaa yhteyttä siihen viesteillä?

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

Joten, odota! Olen jo nähnyt tämän! Jotain vastaavaa tapahtuu, kun TileLink on umpikujassa, enkä jotenkin luota muistiohjaimen kirjoittajaan - kirjoitin sen itse... Yhtäkkiä ensimmäisen onnistuneen prosessorin uudelleenrakentamisen jälkeen ohjaimen muokkaamisen jälkeen näin:

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

Tähän outoon linjaan ennen In: serial älä kiinnitä huomiota - yritin ymmärtää riippuvalla prosessorilla, toimiiko se oikein ympäristön kanssa. Mitä tarkoitat "Se on roikkunut näin kymmenen minuuttia"? Ainakin se onnistui muuttamaan ja siirtymään käynnistysvalikkoon! Pieni poikkeama: vaikka U-Boot ladataan ensimmäiset 2^24 tavua SD-kortilta, se käynnistyessään kopioi itsensä kauempana olevaan osoitteeseen, joka on joko kirjoitettu asetusten otsikkoon tai yksinkertaisesti korkeampiin osoitteisiin. RAM, ja suorittaa ELF relocation -hahmot ja siirtää ohjauksen sinne. Joten: näyttää siltä, ​​että läpäisimme tämän tason ja saimme bonuksen, että prosessori ei roikkunut tiukasti sen jälkeen.

Joten miksi ajastin ei toimi? Näyttää siltä, ​​​​että kello ei jostain syystä toimi...

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

Mitä jos käännät nuolia käsin?

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

sitten:

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

Johtopäätös: kello ei tiki. Tästä syystä näppäimistön syöttö ei todennäköisesti toimi:

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 == '[') {
...

Ongelmaksi tuli se, että olin vähän liian fiksu: lisäsin avaimen prosessorin konfiguraatioon:

  case DTSTimebase => BigInt(0)

... perustuu siihen, että kommentissa sanottiin "jos et tiedä, jätä 0". Ja loppujen lopuksi WithNBigCores Asetin sen vain 1 MHz:iin (kuten se muuten mainittiin U-Boot-kokoonpanossa). Mutta hitto, olen siisti ja tarkka: en tiedä, täällä se on 25 MHz! Loppujen lopuksi mikään ei toimi. Poistin "parannukset" ja...

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 #

Voit jopa kirjoittaa komentoja! Voit esimerkiksi vihdoin arvailla pääseväsi sisään pienen tuijotuksen jälkeen mmc_spi 1 10000000 0; mmc part, vähentää SPI-taajuutta 20 MHz:stä 10 MHz:iin. Miksi? No, 20MHz:n maksimitaajuus oli kirjoitettu konfiguraatioon, ja se on edelleen siellä. Mutta ymmärtääkseni rajapinnat ainakin täällä toimivat näin: koodi jakaa laitteistoyksikön taajuuden (minun on 25MHz kaikkialla) tavoitteella ja asettaa tuloksena olevan arvon jakajaksi vastaavassa ohjauksessa. rekisteröidy. Ongelmana on, että jos 115200Hz UART:lle on suunnilleen mitä tarvitaan, niin jos jaat 25000000 luvulla 20000000, saat 1, ts. se toimii 25 MHz:llä. Ehkä tämä on normaalia, mutta jos rajoituksia asetetaan, se tarkoittaa, että joku tarvitsee sitä (mutta tämä ei ole varmaa)... Yleensä on helpompi laittaa se alas ja jatkaa eteenpäin - pitkälle ja valitettavasti pitkään. 25 MHz ei ole Core i9.

Konsolin lähtö

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, olemme saavuttaneet seuraavalle tasolle, mutta se on edelleen jäätävää. Ja joskus se ripottelee myös poikkeuksia. Voit nähdä syyn odottamalla koodia määritetyssä osoitteessa $pc ja jälkeen si olla päällä trap_entry. Itse U-Boot-käsittelijä voi tulostaa vain mcause = 0..4, joten valmistaudu juuttumaan väärään käynnistykseen. Sitten menin asetuksiin, aloin katsoa, ​​mitä olin muuttamassa, ja muistin: siellä conf/rvboot-fit.txt kirjoitettu:

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

No, saatetaan kaikki tiedostot yhteen, korvataan ytimen komentorivi jollain tämmöisellä, koska epäillään, että SIF0 - tämä on lähtö jossain PCIe:n kautta:

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

Ja vaihdetaan tiivistysalgoritmi SHA-256:sta MD5:een: En tarvitse salausvoimakkuutta (etenkään vianetsinnässä), se vie hirveän kauan ja eheysvirheiden havaitsemiseen latauksen aikana MD5 on liian helppoa. Mikä on lopputulos? Aloimme suorittaa edellistä tasoa huomattavasti nopeammin (yksinkertaisemman tiivistyksen ansiosta), ja seuraava avautui:

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

Mutta kello ei käy...

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

Hups, näyttää siltä, ​​että kellon korjaaminen osoittautui plaseboksi, vaikka minusta silloin tuntui, että se auttoi. Ei, se on tietysti korjattava, mutta käännetään ensin nuolia manuaalisesti ja katsotaan mitä tapahtuu:

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.

Sillä välin…

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

Ei, aion automatisoida kellon - muuten ehkä hän päättää kalibroida ajastimen siellä!

Sillä välin nykyisen ohjeen osoite osoittaa jonnekin

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>

ladatun Berkeley Boot Loaderin sisällä. Henkilökohtaisesti minua hämmentää tässä maininta htif — isäntärajapinta, jota käytetään ytimen kytkettyyn käynnistämiseen (eli yhteistyössä isäntä-ARM:n kanssa), oletin, että se on erillinen. Jos kuitenkin löydät tämän toiminnon lähdekoodista, voit nähdä, että kaikki ei ole niin huonoa:

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

Tehtävä: käynnistä kello

Rekistereiden etsiminen CLINTistä johtaa meidät

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

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

Joka liittyy RTC:hen tai salaperäiseen MockAONiin, josta aluksi ajattelin: ”Mitä meillä on täällä? Epäselvä? Sammuta se!" Koska en vieläkään ymmärrä, millaista kellotaikuutta siellä tapahtuu, niin otan tämän logiikan käyttöön uudelleen 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
  }

Matkalla kohti Linux-ytimiä

Tässä tarina on jo venynyt ja muuttunut hieman yksitoikkoiseksi, joten kuvailen sitä ylhäältä alas:

BBL oletti FDT:n läsnäolon klo 0xF0000000, mutta korjasin sen jo! No, katsotaan uudestaan... Löysin sen HiFive_U-Boot/arch/riscv/lib/boot.c, korvattu 0x81F00000, määritetty U-Boot-käynnistyskokoonpanossa.

Sitten BBL valitti, ettei muistia ollut. Minun polkuni oli funktiossa mem_prop, mitä sisällä riscv-pk/machine/fdt.c: Sieltä opin, että sinun täytyy merkitä fdt ram-solmu nimellä device_type = "memory" - Sitten ehkä prosessorin generaattori on korjattava, mutta toistaiseksi kirjoitan sen vain manuaalisesti - joka tapauksessa siirsin tämän tiedoston manuaalisesti.

Nyt sain viestin (toimitettu muotoillussa muodossa, vaunujen palautuksilla):

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.

Näyttää siltä, ​​että vaihtoehdot on ilmoitettu tarpeen mukaan riscv,kernel-start и riscv,kernel-end DTB:ssä, mutta nollia jäsennetään. Virheenkorjaus query_chosen osoitti, että BBL yrittää jäsentää 32-bittistä osoitetta, mutta se löytää parin <0x0 0xADDR>, ja ensimmäinen arvo näyttää olevan vähiten merkitseviä bittejä. Lisätty osioon chosen

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

ja korjasi arvojen luomisen: älä lisää 0x0 ensimmäinen elementti.

Näiden 100500 XNUMX yksinkertaisen vaiheen avulla on helppo seurata pingviinin putoamista:

Piilotettu teksti

   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)

(BBL näyttää logon ja ydin näyttää logon, jossa on aikaleima).

Onneksi en tiedä miten se on kaikkialla, mutta RocketChipissä, kun yhdistät debuggerin JTAGin kautta, voit saada ansoja pois laatikosta - debuggeri pysähtyy täsmälleen tässä vaiheessa.

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); // < ВЫ НАХОДИТЕСЬ ЗДЕСЬ
}

Kuten vanha vitsi sanoi, Prosessoria ei löydy, käynnissä ohjelmistoemulointi. Tai sitten ei juokse. Kadonnut yhteen prosessoriytimeen.

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

Kiva kommentti mukana linux/arch/riscv/kernel/setup.c - eräänlainen aidan maalaus Tom Sawyer -menetelmällä. Yleensä jostain syystä tänään ei ollut voittajia, palkinto siirtyy seuraavaan arvontaan...

Ehdotan tähän lopettaa jo ennestään pitkä artikkeli.

Jatkuu. Tulee taistelu ovelan bugin kanssa, joka onnistuu piiloutumaan, jos hiipii sen päälle hitaasti yhdellä askeleella.

Tekstin lataus screencast (ulkoinen linkki):
Osa 3: Lähes Linuxin lataaminen SD-kortilta RocketChipiin

Lähde: will.com

Lisää kommentti