Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Beş 3: Hema barkirina Linux ji qerta SD li RocketChip В beşa berê kontrolkerek bîranîna xebitandinê ya kêm-zêde hate bicîh kirin, an bêtir, pêçek li ser IP Core ji Quartus, ku adapterek e ji bo TileLink. Îro, di beşa "Em RocketChip-ê bi Cyclone re li panelek Chineseînî ya hindik-naskirî vediguhezînin" hûn ê konsolek xebatê bibînin. Pêvajo hinekî dirêj dirêj kir: Min jixwe difikirî ku ez ê zû Linux dest pê bikim û bimeşim, lê ne wusa bû. Di vê beşê de, ez pêşniyar dikim ku li pêvajoya destpêkirina U-Boot, BBL, û hewildanên tirsnak ên kernel Linux ji bo destpêkirinê binihêrim. Lê konsolek heye - U-Boot, û pir pêşkeftî, ku pir tiştê ku hûn ji konsolek bêkêmasî hêvî dikin heye.

Zehf dê qerta SD-ya ku bi navgîniya SPI-yê ve girêdayî ye, û her weha UART-ê vehewîne. Di beşa nermalavê de, BootROM-ê dê were guheztin xip li ser sdboot û, bi rastî, qonaxên barkirinê yên jêrîn hatine zêdekirin (li ser qerta SD).

Dawîkirina hardware

Ji ber vê yekê, peywir: hûn hewce ne ku veguhezînin navokek "mezin" û UART (ji Raspberry) û adapterek SD ve girêbidin (me qertek ji Catalex bi şeş pinan bikar anî: GND, VCC, MISO, MOSI, SCK, CS) .

Di prensîbê de, her tişt pir hêsan bû. Lê berî ku ez vê yekê fêhm bikim, ez piçekî ji aliyek ber bi aliyekî ve hatim avêtin: piştî dema berê, min biryar da ku dîsa ez tenê hewce dikim ku têxim nav hev. System tiştekî wek HasPeripheryUART (û li gorî vê yekê pêkanîn), heman ji bo qerta SD - û her tişt dê amade be. Dûv re min biryar da ku bibînim ka ew çawa di sêwiranek "ciddî" de hate bicîh kirin. Ji ber vê yekê, li ser vê yekê çi ciddî ye? Arty, xuya ye, li hev nayê - cinawir dimîne unleahshed.DevKitConfigs. Û ji nişkê ve derket holê ku li her derê hin serpêhatî hene, ku bi pîvanan ji hêla bişkojan ve hatine zêdekirin. Ez texmîn dikim ku ev belkî pir maqûl û mîhengbar e, lê ez dixwazim bi kêmanî pêşî tiştek bimeşînim… Ma we heman tişt tune, tenê hêsan û aciztir?.. Wê demê ez pê re hatim vera.iofpga.FPGAChip ji bo FPGA-yên Microsemi û tavilê ew ji bo binavkirinê ji hev veqetand û hewl da ku bi analojiyê pêkanîna xwe bikim, bextewar di yek pelê de kêm-zêde tevaya "layout motherboard" heye.

Derket holê ku hûn bi rastî hewce ne ku lê zêde bikin System.scala xetên

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

Line di bedena polê de System agahdariya li ser frekansa ku ev beşê SoC-ya me li pelê dts dixebite zêde dike. Bi qasî ku ez fam dikim, DTS/DTB analogek statîk a teknolojiya pêve-û-play-ê ye ji bo cîhazên pêvekirî: dara danasîna dts di pelek dtb-ya binary de tê berhev kirin û ji hêla bootloader ve tê veguheztin kernelê da ku ew bi rengek rast rast mîheng bike. hardware. Balkêş e, bêyî rêza bi tlclock her tişt bêkêmasî hevrêz dike, lê berhevkirina BootROM (bihêle ez ji we re bi bîr bînim, naha ev ê jixwe be sdboot) dê nexebite - di dema pêvajoya berhevkirinê de ew pelê dts par dike û bi makroyek sernavek diafirîne. TL_CLK, bi spasiya ku ew ê bikaribe dabeşkerên frekansê yên ji bo pêwendiyên derveyî rast mîheng bike.

Her weha hûn ê hewce bikin ku "têlkêşanê" hinekî rast bikin:

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
}

Zencîreyên qeydkirinê, bi rastî, bi tenê li gorî hin deverên din ên di koda orjînal de hatine zêdekirin. Bi îhtîmaleke mezin, divê ew li hember biparêzin metastability. Dibe ku di hin blokan jixwe parastina xwe heye, lê pêşî ez dixwazim wê bi kêmanî "di astek kalîteya bilind" de dest pê bikim. Ji bo min pirsek balkêştir ev e ku çima MISO û MOSI ji hev cuda ne dq? Min hîn bersiv nedîtiye, lê wusa dixuye ku koda mayî bi tenê pêwendiyek wusa ve girêdayî ye.

Ji hêla fizîkî ve, min bi tenê pêlên sêwiranê danî ser têkiliyên belaş ên li ser blokê û hilbijarka voltaja berbi 3.3V vekir.

adapterê SD

Dîtina ji jor:

Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Dîtina jêrîn:

Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Debugging Software: Amûrên

Pêşîn, bila em li ser amûrên debugkirinê yên berdest û sînorên wan biaxivin.

Minicom

Pêşîn, em ê hewce bikin ku bi rengek bootloader û kernel çi derdixin bixwînin. Ji bo kirina vê yekê li ser Linux (di vê rewşê de, li ser yeka li ser RaspberryPi), em hewceyê bernameya Minicom in. Bi gelemperî, her bernameyek ku bi porta serial re dixebite dê bike.

Ji kerema xwe not bikin ku dema ku dest pê dike, divê navê cîhaza portê wekî were destnîşan kirin -D /dev/ttyS0 - piştî vebijarkê -D. Welê, agahdariya sereke: derketin, bikar anîn Ctrl-A, X. Bi rastî min bûyerek hebû ku ev tevlihevî nexebitî - wê hingê hûn dikarin bi hêsanî ji danişînek SSH-ya cîran bibêjin killall -KILL minicom.

Taybetmendiyek din jî heye. Bi taybetî, RaspberryPi du UART hene, û her du port jixwe dikarin ji bo tiştek bêne adaptekirin: yek ji bo Bluetooth-ê, ya din ji hêla xwerû ve konsolê kernel derdixe. Xweşbextane, ev tevger dikare were paşguh kirin li gor vê destanê.

Ji nû ve nivîsandina bîranînê

Dema debugging, ji ​​bo ceribandina hîpotezek, ez carinan neçar bûm barkirina bootloader (bibore) rasterast ji mêvandarê nav RAM. Dibe ku ev rasterast ji GDB-ê were kirin, lê di dawiyê de min rêyek hêsan şopand: min pelê pêwîst ji Raspberry re kopî kir, di heman demê de porta 4444 jî bi SSH (telnet ji OpenOCD) re şand û ferman bikar anî. load_image. Dema ku hûn wiya dikin, wusa dixuye ku her tişt cemidî ye, lê di rastiyê de "Xew nake, ew hêdî hêdî dibiriqe": Ew pelê dadixe, tenê bi leza çend kîlobyte di çirkeyê de dike.

Taybetmendiyên sazkirina xalên veqetandinê

Dibe ku gelek kes neçar bûne ku li ser vê yekê bifikirin dema ku bernameyên birêkûpêk jêbirin, lê xalên veqetandinê her gav di hardware de nayên danîn. Carinan danîna xalek veqetandinê bi nivîsandina demkî rêwerzên taybetî li cîhê rast digire rasterast di koda makîneyê de. Mînakî, bi vî rengî fermana min a standard xebitî b li GDB. Li vir çi ye:

  • hûn nekarin xalek li hundurê BootROM-ê bixin ji ber ku ROM
  • Hûn dikarin li ser koda ku di RAM-ê de ji qerta SD-ê hatî barkirin xalek veqetandinê destnîşan bikin, lê hûn hewce ne ku li bendê bimînin heya ku ew were barkirin. Wekî din, em ê perçeyek kodê ji nû ve nenivîsin, lê barker dê xala meya veqetandinê ji nû ve binivîsîne

Ez bawer im ku hûn dikarin bi eşkereyî bixwazin ku xalên veqetandinê yên hardware bikar bînin, lê her weha hejmarek ji wan bi sînor hene.

Veguheztina Quick BootROM

Di qonaxa destpêkê ya xeletkirinê de, pir caran daxwazek heye ku BootROM-ê rast bike û dîsa biceribîne. Lê pirsgirêkek heye: BootROM beşek sêwirana ku di FPGA-yê de hatî barkirin e, û senteza wê çend hûrdeman e (û ev piştî berhevkirina hema hema tavilê ya wêneya BootROM bixwe ji C û Assembler e...). Xweşbextane, di rastiyê de her tişt pir zûtir: rêza çalakiyan wiha ye:

  • nûvekirina bootrom.mif (min li şûna HEX-ê veguherand MIF, ji ber ku min her gav bi HEX re hin pirsgirêk hebûn, û MIF formata xwemalî ya Alter e)
  • li Quartus dibêjin Processing -> Update Memory Initialization File
  • li ser xala Assembler (di stûna çepê ya Tasks) de emrê dîsa dest pê bike

Her tişt li ser her tiştî - çend deh çirkeyan.

Amadekirina karta SD

Li vir her tişt bi hêsanî hêsan e, lê hûn hewce ne ku bîhnfireh bin û bi qasî 14 Gb cîhê dîskê hebe:

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

Piştî vê yekê hûn hewce ne ku paqijek, an bêtir, ya ku tiştek hewce nake, qerta SD-ê têxin û bicîh bikin.

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

… Li ku derê sdX - cîhaza ku ji qertê re hatî veqetandin. HIŞYARÎ: Daneyên li ser qertê dê werin jêbirin, werin nivîsandin û bi gelemperî! Ne hêja ye ku tevahiya meclîsê ji binî were kirin sudoji ber ku wê hingê hemî berhemên çêkirî dê bibin aîdê wan root, û meclîs dê ji binî ve were kirin sudo berdewam.

Encam kartek e ku di GPT-ê de bi çar beşan ve hatî nîşankirin, yek ji wan bi FAT re heye uEnv.txt û wêneyek bootable di formata FIT de (ew çend bin-wêneyan dihewîne, her yek bi navnîşana xweya dakêşanê heye), dabeşa din vala ye, tê xwestin ku ew di Ext4-ê de ji bo Linux-ê were format kirin. Du beşên din - pirdizî: U-Boot li ser yekê dijî (jihevdengiya wê, bi qasî ku ez fêm dikim, di BootROM-ê de hişk e), ji hêla din ve, dixuye ku guhêrbarên hawîrdora wê dijîn, lê ez hîna wan bikar naynim.

Asta yek, BootROM

Hikmeta gelêrî dibêje: "Heke di bernamesaziyê de bi tembûrê danskirin hebe, wê demê di elektronîk de jî danskirina bi vemirandina agir heye." Tewra ne li ser vê yekê ye ku carekê min hema panelê şewitand, biryar da ku "Belê, GND heman asta nizm e." (xuya ye, berxwedêrek dê zirarê nede her tiştî ...) Zêdetir di derbarê vê yekê de ye ku ger dest ji wir mezin nebin, wê hingê elektronîk tu carî dev ji surprîzên xwe bernade: dema ku girêdanê li ser panelê dixin, min hîn jî nikarîbû têkiliyan bi rêkûpêk zevt bikim - vîdyoyê destnîşan dike ka kavil çawa rasterast belav dibe. li ser tevahiya pêwendiyê, tenê hesinek lêdanê bicîh bikin, Ji bo min, wî bi rengekî bêserûber "sîlîk lêxist". Belê, belkî zeliqandî ne li gor germahiya hesinê zeliqandî be, belkî tiştekî din... Bi giştî gava min dît ku berê bi dehan têkiliyên min hene, min dev jê berda û dest bi debugkirinê kir. Û paşê dest pê kir pirdizî: Min RX/TX ji UART ve girêda, ez firmware bar dikim - ew dibêje

INIT
CMD0
ERROR

Welê, her tişt mentiqî ye - min modula qerta SD venekir. Em rewşê rast dikin, firmware bar dikin... Û bêdengî... Çima min fikra xwe neguhert, lê qutiya piçûk tenê vebû: yek ji pîneyên modulê diviyabû ku bi VCC ve were girêdan. Di doza min de, modulê ji bo dabînkirina hêzê 5V piştgirî kir, ji ber vê yekê bêyî ku du caran bifikirim, min têla ku ji modulê tê li aliyê dijberî panelê vekir. Di encamê de, girêdana ku bi xeletî ve hatî zeliqandin qelişî bû, û Têkiliya UART bi tenê winda bû. facepalm.jpg Bi gelemperî, "serê xerab lingan rehet nade" û destên çopê jî bêhna serê xwe nadin...

Di encamê de, min ya dirêj-hêvîdar dît

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

Wekî din, ew dimeşe û nîşana barkirinê dizivire. Ez tavilê rojên xwe yên dibistanê û barkirina bêhêvî ya MinuetOS ji dîskek dîskek tê bîra min. Heya ku ajoker neşewite.

Pirsgirêk ev e ku piştî peyama BOOT tiştek nabe. Ev tê vê wateyê ku ew dem e ku hûn bi rêya OpenOCD-ê bi Raspberry, bi GDB-ê re li ser mêvandar ve girêbidin û bibînin ka ew çi ye.

Pêşîn, girêdana bi karanîna GDB-ê tavilê ev yek destnîşan kir $pc (hejmara bernameyê, navnîşana talîmata heyî) difire 0x0 - ev dibe ku piştî gelek xeletiyan çêdibe. Ji ber vê yekê, tavilê piştî ku peyam tê weşandin BOOT ka em çerxeke bêdawî lê zêde bikin. Ev ê wî ji bo demekê dereng bike ...

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

Kodek wusa ya xapînok "ji bo pêbaweriyê" tê bikar anîn: Min li cîhek bihîst ku lûleyek bêdawî Tevgerek nenas e, lê berhevkar ne mimkûn e ku texmîn bike (Ez bi bîr tînim ku li gorî 0x10000 BootROM heye).

Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Wusa dixuye, wekî din çi li bendê ye - hişk hatî vegirtin, kîjan kodên çavkaniyê hene? Lê di ew gotara nivîskar koda C-yê verast dikir... 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.

Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Hûn tenê hewce ne ku ne pelê MIF an bin, lê guhertoya orîjînal di forma ELF de dakêşin.

Naha hûn dikarin bi hewildana n-ê re navnîşana ku lê darvekirin dê bidome texmîn bikin (ev sedemek din e ku pêdivî ye ku berhevkar texmîn nekiriye ku hêl bêdawî ye). Kom

set variable $pc=0xADDR

destûrê dide te ku hûn nirxa qeydê di firînê de biguhezînin (di vê rewşê de, navnîşana fermana heyî). Bi alîkariya wê, hûn dikarin nirxên ku li ser bîranînê hatine nivîsandin (û tomarên nexşeya bîranînê) biguhezînin.

Di dawiyê de, ez gihîştim wê encamê (ne bawer im ka kîjan rast e) ku me "wêneyek qerta SD ya pergala xelet" heye, û pêdivî ye ku em ne herin destpêka daneyên dakêşandî, lê 0x89800 bytes bêtir:

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

Dibe ku ev jî ji wê yekê bandor bû ku di destê xwe de qerta 4Gb ya nehewce tunebû, min yekî 2Gb girt û bi rasthatinî di Makefile de şûna wê girt. DEMO_END=11718750 li ser DEMO_END=3078900 (di wateyek taybetî de li wateyê negerin - tune ye, tenê ew e ku nuha wêne li ser qertê tê danîn).

Asta duduyan, U-Boot

Naha em hîn jî "dikevin", lê em jixwe li cîhê rast in 0x0000000080089a84. Li vir divê ez bipejirînim: bi rastî, pêşkêşî "bi hemî rawestan" re naçe, lê bi qismî "piştî" tê nivîsandin, ji ber vê yekê li vir min berê xwe da pelê dtb-ya rast ji SoC-ya me, wê di mîhengan de rast bike. HiFive_U-Boot têgûherr CONFIG_SYS_TEXT_BASE=0x80089800 (li şûna 0x08000000) da ku navnîşana dakêşanê bi ya rastîn re têkildar be. Naha em nexşeya asta din, wêneyek din bar dikin:

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

Û em dibînin:

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

Wekî din, em dikevin navbera rêzên 308 û 309. Û ne ecêb e, ji ber ku di $sp wateya derewan dike 0xfffffffe31cdc0a0. Mixabin, ew jî ji ber rêza 307-an bi berdewamî "direve". Ji ber vê yekê, em hewl bidin ku xalek veqetandinê li trap_entry, û paşê vegerin 0x80089800 (Xala têketina U-Boot), û em hêvî bikin ku ew ne hewce ye ku qeydan berî bazdanê rast werin danîn... Wusa dixuye ku ew dixebite:

(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

Nîşana stackê wusa ye, bi eşkereyî dipeyivî: ew destnîşan dike ku RAM-ê bi tevahî derbas dike (heya ku, bê guman, me jixwe wergera navnîşan tune, lê em li hêviya vebijarkek hêsan bin).

Werin em biceribînin ku nîşanderê bi cîh bikin 0x881cf950. Di encamê de, em digihîjin vê encamê handle_trap gazî kir û gazî kir, û di heman demê de em diçin nav _exit_trap bi arguman epc=2148315240 (bi dehanî):

(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

Pîvana veqetandinê li ser strnlen, em berdewam dikin û dibînin:

(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

Xuya ye ku be, _exit_trap Dixwaze di derheqê îstîsna ku qewimî de agahdariya xeletkirinê peyda bike, lê ew nikare. Ji ber vê yekê, bi rengekî çavkaniyên me dîsa nayên xuyang kirin. set directories ../freedom-u-sdk/HiFive_U-Boot/ JI DOR! Niha tê nîşandan!

Were, em wê dîsa bimeşînin û li ser stackê bibînin ku sedema pirsgirêka bingehîn a ku bûye sedema xeletiya yekem (mcause == 5). Ger min rast fêm kir ku çi hatî nivîsandin vir di rûpela 37 de, hingê ev îstîsna tê wateya Load access fault. Sedem xuya dike ku li vir e

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 heman wateya çewt e, û hundir board_init_f_init_reserve xeletiyek çêdibe. Wusa dixuye ku ev sûcdar e: guhêrbarek bi navek nezelal CONFIG_SYS_INIT_SP_ADDR. Di dosyayê de hatiye diyarkirin HiFive_U-Boot/include/configs/HiFive-U540.h. Di deverekê de min tewra fikir kir, belkî, baş e, divê ez ji bo pêvajoyê barkerek boot lê zêde bikim - belkî ew ê hêsantir be ku pêvajoyê piçek rast bike? Lê dûv re min dît ku ew bêtir wekî hunerek e ku bi tevahî nehatiye qedandin#if 0-Mîhengên taybetî ji bo mîhengek bîranînek cihêreng, û hûn dikarin vê yekê biceribînin:

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

Di hin nuqteyan de hejmara kêzikan fasteners teknolojîk gihîştiye asteke krîtîk. Piştî hinek ezabê, min hewce kir ku ez porta rast ji bo panela xwe çêkim. Ji bo vê yekê, pêdivî ye ku em çend pelan kopî bikin û li gorî veavakirina me rast bikin.

Welê, hema hema, li vir tabloyek piçûk heye

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

Agahdariyên di nav de têne dîtin depoyên.

Wekî ku derket holê, li ser vê panelê SiFive qeydên hin cîhazan navnîşanên cûda hene. Di heman demê de derket holê ku U-Boot bi karanîna mekanîzmaya Kconfig-ê, ku berê ji kernel Linux-ê nas e, hatî mîheng kirin - mînakî, hûn dikarin ferman bikin make menuconfig, û pêvekek nivîsê ya hêsan dê li ber we xuya bibe ku ravekirina parametreyan ji hêla we ve nîşan dide ? etc. Bi gelemperî, danasîna ya sêyemîn ji danasînên du tabloyan bi hev re berhev kirin, her cûre veavakirina PLL-ya dilpak ji wir derdixe (xuya ye, ev bi rengekî bi kontrola ji komputera mêvandar bi PCIe ve girêdayî ye, lê ev ne diyar e) , Min hin firmware wergirt, ku, di hewa rast a li Marsê de, bi riya UART-ê peyamek da min ka ew ji kîjan commit hash hatî berhev kirin, û derheqê min de çiqas DRAM heye (lê min bixwe ev agahdarî di serî de nivîsand).

Tenê heyf ev e ku piştî vê panelê bi gelemperî bersivdayîna bi pêvajoya JTAG-ê rawestand, û barkirina ji qerta SD-ê, mixabin, di veavakirina min de ne bilez e. Ji hêla din ve, carinan BootROM peyamek da ERROR, boot bi ser neket, û U-Boot yekser derket holê. Dûv re ew ji min re xuya bû: xuya ye, piştî ku bitstream-ê ji nû ve li FPGA-yê ji nû ve hatî destpêkirin, bîranîn nayê jêbirin, wextê wê tune ku "hilweşandin" û hwd. Bi kurtasî, hûn dikarin bi hêsanî gava ku peyamek xuya dibe LOADING / bi debugger û fermanê ve girêdin set variable $pc=0x80089800, bi vî rengî vê barkirina dirêj derbas dike (bê guman, bi texmîna ku cara paşîn ew zû şikest ku wextê wê tunebû ku tiştek li ser koda orîjînal bar bike).

Bi awayê, gelo bi gelemperî normal e ku pêvajo bi tevahî dicemidîne û debugger JTAG nikare bi peyaman pê ve girêbide?

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

Ji ber vê yekê, bisekinin! Min berê jî ev dît! Tiştek wusa diqewime dema ku TileLink xitimî ye, û ez bi rengekî ji nivîskarê kontrolkerê bîranînê bawer nakim - min bi xwe ew nivîsand ... Ji nişkê ve, piştî yekem nûavakirina serketî ya pêvajoyê piştî sererastkirina kontrolkerê, min dît:

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

Ji bo vê xeta xerîb berê In: serial bala xwe nedin - Min hewl dida ku li ser pêvajoyek daleqandî fam bikim ka ew bi jîngehê re rast dixebite. Mebesta te çi ye, "Ev deh deqe bi vî rengî daliqandî ye"? Bi kêmanî ew karî veguhezîne û here menuya bootê! Xalek piçûk: her çend U-Boot di 2^24 baytên yekem ên qerta SD-ê de tê barkirin, dema ku ew dest pê dike, ew xwe li navnîşanek dûrtir kopî dike, an di sernavê veavakirinê de hatî nivîsandin, an jî bi tenê li navnîşanên bilind ên RAM-ê hatî nivîsandin. , û veguheztina ELF-karakteran pêk tîne, û kontrolê li wir vediguhezîne. Ji ber vê yekê: Wusa dixuye ku me vê astê derbas kir û bonusek wergirt ku pêvajo piştî wê zexm negirt.

Ji ber vê yekê çima demjimêr naxebite? Wusa dixuye ku demjimêr ji ber hin sedeman naxebite...

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

Ger hûn tîrên bi destan bizivirin çi?

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

Paşan:

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

Encam: Saet naqede. Dibe ku ji ber vê yekê têketina klavyeyê nexebite:

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

Pirsgirêk derket holê ku ez piçek pir jîr bûm: Min mifteyê li mîhenga pêvajoyê zêde kir:

  case DTSTimebase => BigInt(0)

... li ser vê yekê ku şîrove got "heke hûn nizanin, 0 bihêlin." Û piştî her tiştî WithNBigCores Min tenê ew danî ser 1MHz (wek ku, bi awayê, ew di veavakirina U-Boot de hate destnîşan kirin). Lê nalet, ez paqij û hûrbîn im: Ez li wir nizanim, li vir ew 25 MHz e! Di dawiyê de, tiştek kar nake. Min "pêşketinên" xwe rakirin û ...

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 #

Tewra hûn dikarin fermanan têkevin! Mînakî, piştî ku hinekî li dora xwe bigerin, hûn dikarin di dawiyê de texmîn bikin ku têkevinê mmc_spi 1 10000000 0; mmc part, kêmkirina frekansa SPI ji 20MHz bo 10MHz. Çima? Welê, frekansa herî zêde ya 20MHz di mîhengê de hate nivîsandin, û ew hîn jî li wir tê nivîsandin. Lê, bi qasî ku ez fêm dikim, navber, bi kêmanî li vir, bi vî rengî dixebitin: kod frekansa yekîneya hardware (ya min li her derê 25 MHz e) li ser armancê dabeş dike, û nirxa encam wekî dabeşker di kontrola têkildar de destnîşan dike. fêhrist. Pirsgirêk ev e ku heke ji bo UARTek 115200Hz hema hema tiştê ku hewce ye hebe, wê hingê heke hûn 25000000 bi 20000000 dabeş bikin hûn ê 1 bistînin, yanî. ew ê li 25 MHz bixebite. Dibe ku ev normal be, lê ger sînorkirin bêne danîn, ev tê vê wateyê ku kesek pê hewce ye (lê ev ne diyar e) ... Bi gelemperî, danîna wê û pêşdebirina wê hêsantir e - dûr û, mixabin, ji bo demek dirêj. 25MHz ne Core i9 e.

Derketina konsolê

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

Baş e, em gihîştine asta din, lê dîsa jî cemidî ye. Û carinan jî îstîsnayan dirijîne. Hûn dikarin mcause li benda kodê li navnîşana diyarkirî bibînin $pc û piştî si li ser be trap_entry. Rêvebirê U-Boot bixwe dikare tenê ji bo mcause = 0..4 derxe, ji ber vê yekê xwe amade bikin ku di bootek nerast de asê bibin. Dûv re ez ketim nav mîhengê, min dest pê kir ku li tiştê ku ez diguhezim mêze bikim û hat bîra min: li wir conf/rvboot-fit.txt hatiye nivîsandin:

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

Were, bila em hemî pelan li hev bînin, rêzika fermanê ya kernel bi tiştek wusa biguhezînin, ji ber ku guman hene ku SIF0 - ev der derek bi rêya PCIe ve ye:

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

We bila em algorîtmaya haşkirinê ji SHA-256 berbi MD5-ê biguhezînin: Ez hewcedarê hêza krîptografî nakim (nemaze dema xeletkirinê), ew demek pir dirêj digire, û ji bo girtina xeletiyên yekitiyê di dema barkirinê de, MD5 pir hêsan e. Encama dawî çi ye? Me dest pê kir ku asta berê bi baldarî zûtir biqedînin (ji ber haşkirina hêsantir), û ya din vebû:

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

Lê saet naqede...

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

Oops, wusa dixuye ku rastkirina demjimêrê wekî cîhêbo derketiye holê, her çend di wê demê de ji min re xuya bû ku ew alîkarî kir. Na, bê guman ew pêdivî ye ku were rast kirin, lê em pêşî tîrên bi destan bizivirînin û bibînin ka çi diqewime:

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.

Di vê navberê de…

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

Na, ez ê herim demjimêrê otomatîk bikim - wekî din belkî ew ê biryar bide ku demjimêrê li wir kalibr bike!

Di vê navberê de, navnîşana rêwerziya heyî li cîhek din destnîşan dike

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>

di hundurê Berkeley Boot Loader de barkirî. Bi kesane, tiştê ku min di vê yekê de tevlihev dike, behs e htif - Navbera mêvandar ku ji bo destpêkirina girêdana kernelê tê bikar anîn (ango, bi hevkariya mêvandarê ARM-ê re), min serbixwe texmîn kir. Lêbelê, heke hûn vê fonksiyonê di koda çavkaniyê de bibînin, hûn dikarin bibînin ku ne her tişt ew qas xirab e:

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: saetê dest pê bike

Lêgerîna tomarên di CLINT de me rê dide

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

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

Kîjan bi RTC, an bi MockAON-a razdar ve girêdide, ku ez di destpêkê de li ser wê fikirîm: "Ji ber vê yekê, me li vir çi heye? Nezelal? Ka em wê vemirînin!" Ji ber ku ez hîn jî fam nakim ka çi celeb sêrbaziya demjimêrê li wir diqewime, ji ber vê yekê ez ê tenê vê mantiqê ji nû ve pêk bînim 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
  }

Riya me berbi kernel Linux-ê vedike

Li vir çîrok jixwe dirêj bûye û hinekî monoton bûye, loma ez ê ji serî heta binî vebêjim:

BBL hebûna FDT li wê texmîn kir 0xF0000000, lê min berê rast kir! Baş e, em dîsa lê binerin... Di nav de hat dîtin HiFive_U-Boot/arch/riscv/lib/boot.c, li şûna 0x81F00000, di veavakirina bootê ya U-Boot de hatî destnîşan kirin.

Dûre BBL gilî kir ku bîranîn tune. Riya min di fonksiyonê de bû mem_prop, çi di riscv-pk/makîne/fdt.c: ji wir ez fêr bûm ku hûn hewce ne ku girêka fdt ram wekî nîşan bikin device_type = "memory" - wê hingê, dibe ku, jeneratorê pêvajoyê hewce bike ku were rast kirin, lê heya nuha ez ê tenê bi destan binivîsim - her weha, min bi destan ev pel veguhezand.

Naha min peyam wergirt (bi forma formatkirî, bi vegerên bargiraniyê ve hatî peyda kirin):

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.

Wusa dixuye ku vebijark li gorî hewcedariyê têne destnîşan kirin riscv,kernel-start и riscv,kernel-end di DTB de, lê sifir têne pars kirin. Debugging query_chosen nîşan da ku BBL hewl dide ku navnîşek 32-bit parsek bike, lê ew li cotek tê <0x0 0xADDR>, û nirxa yekem xuya dike ku bitikên herî kêm girîng in. Li beşê hat zêdekirin chosen

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

û nifşê nirxan rast kir: zêde neke 0x0 hêmana yekem.

Van 100500 gavên hêsan dê temaşekirina ketina pinguinek hêsan bike:

Nivîsa veşartî

   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)

(Logo ji hêla BBL-ê ve tê xuyang kirin, û ya ku bi îşaretên demê re ji hêla kernelê ve tê xuyang kirin).

Xweşbextane, ez nizanim ew li her derê çawa ye, lê li ser RocketChip, gava ku hûn debuggerek bi navgîniya JTAG ve girêdidin, hûn dikarin xefikên ji qutiyê bigirin - debugger tam di vê nuqteyê de raweste.

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

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

Wek henekê berê got, CPU nehat dîtin, emûlasyona nermalavê dimeşîne. Baş e, an naherikin. Di bingehek pêvajoyek yekane de winda kirin.

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

Şîroveya xweş di nav de linux/arch/riscv/kernel/setup.c - cureyekî boyaxkirina têlekî bi rêbaza Tom Sawyer. Bi gelemperî, ji ber hin sedeman îro tu serketî tune bûn, xelat tê veguheztin bo pêşandana din ...

Li vir ez pêşniyar dikim ku gotara jixwe dirêj biqedînim.

Ez bêtir ji te hez dikim. Ger hûn hêdî-hêdî bi yek gavê li ser wê bizivirin dê şerek bi xeletiyek hîlekar re hebe ku karibe veşêre.

Dîmena daxistina nivîsê (girêdana derve):
Beş 3: Hema barkirina Linux ji qerta SD li RocketChip

Source: www.habr.com

Add a comment