3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

3. daļa: GandrÄ«z Linux ielāde no SD kartes uz RocketChip Š’ iepriekŔējā daļa tika ieviests vairāk vai mazāk strādājoÅ”s atmiņas kontrolieris, pareizāk sakot, Quartus IP Core iesaiņojums, kas ir TileLink adapteris. Å odien sadaļā ā€œMēs pārnēsājam RocketChip uz mazpazÄ«stamu Ä·Ä«nieÅ”u plati ar Cycloneā€ jÅ«s redzēsiet strādājoÅ”u konsoli. Process aizņēma nedaudz ilgāku laiku: jau domāju, ka ātri palaisÄ«Å”u Linux un doÅ”os tālāk, bet tā nebija. Å ajā daļā es ierosinu aplÅ«kot U-Boot, BBL palaiÅ”anas procesu un Linux kodola kautrÄ«gos inicializÄ“Å”anas mēģinājumus. Bet ir konsole - U-Boot, un tā ir diezgan uzlabota, un tai ir daudz no tā, ko jÅ«s varētu sagaidÄ«t no pilnvērtÄ«gas konsoles.

AparatÅ«rā bÅ«s SD karte, kas savienota, izmantojot SPI interfeisu, kā arÄ« UART. ProgrammatÅ«ras daļā BootROM tiks aizstāts ar xip par sdboot un faktiski ir pievienoti Ŕādi ielādes posmi (SD kartē).

Aparatūras pabeigŔana

Tātad, uzdevums: jums ir jāpārslēdzas uz ā€œlieluā€ kodolu un jāpievieno UART (no Raspberry) un SD adapteris (mēs izmantojām Catalex karti ar seŔām tapām: GND, VCC, MISO, MOSI, SCK, CS) .

Principā viss bija pavisam vienkārÅ”i. Bet, pirms es to sapratu, es biju nedaudz iemests no vienas puses uz otru: pēc iepriekŔējās reizes es nolēmu, ka atkal man vienkārÅ”i jāiejaucas System kaut kas kā HasPeripheryUART (un attiecÄ«gi realizācija), tas pats SD kartei - un viss bÅ«s gatavs. Tad es nolēmu redzēt, kā tas tika Ä«stenots "nopietnā" dizainā. Tātad, kas tur ir nopietns? Artijs acÄ«mredzot neiederas - briesmonis paliek unleahshed.DevKitConfigs. Un pēkŔņi izrādÄ«jās, ka visur bija daži pārklājumi, kas tika pievienoti caur parametriem ar taustiņiem. Es domāju, ka tas, iespējams, ir ļoti elastÄ«gs un konfigurējams, bet es gribētu vispirms kaut ko palaist... Vai jums nav tas pats, tikai vienkārŔāk un kaitinoŔāk? .. Toreiz es saskāros vera.iofpga.FPGAChip priekÅ” Microsemi FPGA un uzreiz izjaucu to citātiem un mēģināju pēc analoÄ£ijas izveidot savu implementāciju, par laimi ir vairāk vai mazāk viss ā€œmātesplates izkārtojumsā€ vienā failā.

Izrādījās, ka tieŔām vajag tikai pievienot System.scala līnijas

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

LÄ«nija klases pamattekstā System dts failam pievieno informāciju par frekvenci, kādā Ŕī mÅ«su SoC daļa darbojas. Cik es saprotu, DTS/DTB ir statisks plug-and-play tehnoloÄ£ijas analogs iegultajām ierÄ«cēm: dts aprakstu koks tiek apkopots binārā dtb failā un bootloader to pārsÅ«ta uz kodolu, lai tas varētu pareizi konfigurēt aparatÅ«ra. Interesanti, ka bez lÄ«nijas ar tlclock viss sintezējas perfekti, bet kompilējot BootROM (atgādināŔu, tagad Å”is jau bÅ«s sdboot) nedarbosies - kompilācijas procesa laikā tas parsē dts failu un izveido galveni ar makro TL_CLK, pateicoties kuriem viņŔ varēs pareizi konfigurēt frekvenču dalÄ«tājus ārējām saskarnēm.

Jums būs arī nedaudz jālabo "vadu instalācija":

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
}

GodÄ«gi sakot, reÄ£istru ķēdes tika pievienotas vienkārÅ”i pēc analoÄ£ijas ar dažām citām vietām sākotnējā kodā. Visticamāk, viņiem vajadzētu aizsargāties pret metastabilitāte. VarbÅ«t iekŔā daži blokiem jau ir sava aizsardzÄ«ba, bet vispirms es vēlos to palaist vismaz "augstas kvalitātes lÄ«menÄ«". Man interesantāks jautājums ir, kāpēc MISO un MOSI karājas atŔķirÄ«gi dq? Es vēl neesmu atradis atbildi, bet Ŕķiet, ka pārējais kods ir balstÄ«ts tikai uz Ŕādu savienojumu.

Fiziski es vienkārÅ”i pieŔķīru konstrukcijas tapas brÄ«vajiem kontaktiem uz bloka un pārvietoju sprieguma izvēles džemperi uz 3.3 V.

SD adapteris

Skats no augŔas:

3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

Skats no apakŔas:

3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

Programmatūras atkļūdoŔana: rīki

Vispirms parunāsim par pieejamajiem atkļūdoŔanas rīkiem un to ierobežojumiem.

Minicom

Pirmkārt, mums bÅ«s kaut kā jāizlasa bootloader un kodola izvade. Lai to izdarÄ«tu operētājsistēmā Linux (Å”ajā gadÄ«jumā ar RaspberryPi), mums ir nepiecieÅ”ama programma Minicom. VispārÄ«gi runājot, derēs jebkura programma, kas darbojas ar seriālo portu.

LÅ«dzu, ņemiet vērā, ka startÄ“Å”anas laikā porta ierÄ«ces nosaukums ir jānorāda kā -D /dev/ttyS0 - pēc opcijas -D. Nu, galvenā informācija: lai izietu, izmantojiet Ctrl-A, X. Man tieŔām bija gadÄ«jums, kad Ŕī kombinācija nedarbojās - tad jÅ«s varat vienkārÅ”i teikt no blakus esoŔās SSH sesijas killall -KILL minicom.

Ir vēl viena funkcija. Konkrēti, RaspberryPi ir divi UART, un abus portus jau var kaut kam pielāgot: viens Bluetooth, otrs pēc noklusējuma izvada kodola konsoli. Par laimi, Å”o uzvedÄ«bu var ignorēt saskaņā ar Å”o rokasgrāmatu.

Atmiņas pārrakstÄ«Å”ana

Atkļūdojot, lai pārbaudÄ«tu hipotēzi, man dažreiz tas bija jādara ielādējiet sāknÄ“Å”anas programmu (atvainojiet) RAM tieÅ”i no resursdatora. VarbÅ«t to var izdarÄ«t tieÅ”i no GDB, bet beigās gāju pa vienkārÅ”u ceļu: nokopēju vajadzÄ«go failu uz Raspberry, pārsÅ«tÄ«ju arÄ« portu 4444 caur SSH (telnet no OpenOCD) un izmantoju komandu load_image. Kad to dari, Ŕķiet, ka viss ir sasalis, bet patiesÄ«bā "tas neguļ, tas tikai lēni mirgo": Tas lejupielādē failu, tas tikai dara to ar ātrumu pāris kilobaiti sekundē.

Pārtraukuma punktu uzstādīŔanas iezīmes

Daudziem cilvēkiem, iespējams, par to nav jādomā, atkļūdojot parastās programmas, taču pārtraukuma punkti ne vienmēr ir iestatÄ«ti aparatÅ«rā. Dažreiz pārtraukuma punkta iestatÄ«Å”ana ietver Ä«paÅ”u instrukciju Ä«slaicÄ«gu pierakstÄ«Å”anu pareizajā vietā tieÅ”i maŔīnas kodā. Piemēram, Ŕādi darbojās mana standarta komanda b GDB. Tālāk ir norādÄ«ts tālāk.

  • BootROM iekŔā nevar likt punktu, jo ROM
  • Varat iestatÄ«t pārtraukuma punktu kodam, kas tiek ielādēts RAM no SD kartes, taču jums jāgaida, lÄ«dz tas tiek ielādēts. Pretējā gadÄ«jumā mēs nepārrakstÄ«sim koda daļu, bet ielādētājs pārrakstÄ«s mÅ«su pārtraukuma punktu

Esmu pārliecināts, ka varat tieŔi lūgt izmantot aparatūras pārtraukumpunktus, taču to skaits tik un tā ir ierobežots.

Ātra BootROM nomaiņa

Sākotnējā atkļūdoÅ”anas stadijā bieži vien ir vēlme salabot BootROM un mēģināt vēlreiz. Bet pastāv problēma: BootROM ir daļa no FPGA ielādētā dizaina, un tā sintēze ir dažu minÅ«Å”u jautājums (un tas notiek pēc gandrÄ«z tÅ«lÄ«tējas paÅ”a BootROM attēla kompilācijas no C un Assembler...). Par laimi, patiesÄ«bā viss daudz ātrāk: darbÄ«bu secÄ«ba ir Ŕāda:

  • atjaunot bootrom.mif (es pārgāju uz MIF, nevis HEX, jo man vienmēr bija dažas problēmas ar HEX, un MIF ir Alter vietējais formāts)
  • in Quartus teikt Processing -> Update Memory Initialization File
  • uz vienuma Assembler (uzdevumu kreisajā kolonnā) komandu Sākt no jauna

Viss par visu ā€“ pāris desmiti sekunžu.

SD kartes sagatavoŔana

Viss Å”eit ir salÄ«dzinoÅ”i vienkārÅ”s, taču jums ir jābÅ«t pacietÄ«gam un jābÅ«t apmēram 14 Gb diska vietas:

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

Pēc tam jums jāievieto tÄ«ra vai drÄ«zāk tāda, kurā nav nekā nepiecieÅ”amā, SD karte un jāizpilda

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

ā€¦ Kur sdX ā€” kartei pieŔķirtā ierÄ«ce. UZMANÄŖBU: dati kartē tiks dzēsti, pārrakstÄ«ti un vispār! Diez vai ir vērts veikt visu montāžu no apakÅ”as sudojo tad visi celtnes artefakti piederēs root, un montāža bÅ«s jāveic no apakÅ”as sudo pastāvÄ«gi.

Rezultāts ir karte, kas atzÄ«mēta GPT ar četriem nodalÄ«jumiem, no kuriem vienā ir FAT ar uEnv.txt un bootable attēlu FIT formātā (tajā ir vairāki apakÅ”attēli, katrs ar savu lejupielādes adresi), otrs nodalÄ«jums ir tukÅ”s, tas ir paredzēts formatēt Ext4 for Linux. Vēl divas sadaļas - noslēpumains: U-Boot dzÄ«vo vienā (tā nobÄ«de, cik saprotu, ir iekodēta BootROM), otrā, Ŕķiet, tā vides mainÄ«gie dzÄ«vo, bet es tos vēl neizmantoju.

Pirmais līmenis, BootROM

Tautas gudrÄ«ba vēsta: "Ja programmÄ“Å”anā ir dejoÅ”ana ar tamburÄ«nu, tad elektronikā ir arÄ« dejoÅ”ana ar ugunsdzÄ“Å”amo aparātu." Runa nav pat par to, ka reiz es gandrÄ«z sadedzināju dēli, nolemjot, ka "Nu, GND ir tikpat zems lÄ«menis." (acÄ«mredzot, rezistors galu galā nesāpēs...) Tas vairāk ir par to, ka, ja rokas no turienes neaug, tad elektronika nebeidz sagādāt pārsteigumus: pielodējot savienotāju uz plates, joprojām nevarēju pareizi pielodēt kontaktus - video redzams, kā lodējums tieÅ”i izplatās. pa visu savienojumu, vienkārÅ”i uzklājiet lodāmuru, Man viņŔ nejauÅ”i "iesita". Nu, varbÅ«t lodāmurs nebija piemērots lodāmura temperatÅ«rai, varbÅ«t vēl kaut kas... Vispār, kad ieraudzÄ«ju, ka man jau ir ducis kontaktu, padevos un sāku atkļūdot. Un tad tas sākās noslēpumaini: Es pievienoju RX/TX no UART, ielādēju programmaparatÅ«ru - tā saka

INIT
CMD0
ERROR

Nu viss ir loÄ£iski - es nepievienoju SD kartes moduli. Izlabojam situāciju, ielādējam programmaparatÅ«ru... Un klusums... Kāpēc es nepārdomāju, bet tikko atvērās mazā kastÄ«te: viena no moduļa tapām bija jāpievieno VCC. Manā gadÄ«jumā modulis atbalstÄ«ja 5V strāvas padevei, tāpēc, divreiz nedomājot, es pievienoju vadu, kas nāk no moduļa, pretējā dēļa pusē. Rezultātā greizi pielodētais savienotājs kļuva Ŕķībs, un UART kontakts vienkārÅ”i tika zaudēts. facepalm.jpg Kopumā "slikta galva nedod atpÅ«tu kājām", un lÄ«kas rokas nedod atpÅ«tu galvai ...

Rezultātā es redzēju ilgi gaidīto

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

Turklāt tas kustas un iekrauÅ”anas indikators griežas. Uzreiz atceros skolas laikus un nesteidzÄ«go MinuetOS ielādi no disketes. Ja vien piedziņa nesasmalcina.

Problēma ir tāda, ka pēc BOOT ziņojuma nekas nenotiek. Tas nozīmē, ka ir pienācis laiks izveidot savienojumu, izmantojot OpenOCD ar Raspberry, ar resursdatora GDB, un redzēt, kas tas ir.

Pirmkārt, savienoÅ”ana, izmantojot GDB, to uzreiz parādÄ«ja $pc (programmu skaitÄ«tājs, paÅ”reizējās instrukcijas adrese) lido uz 0x0 - tas, iespējams, notiek pēc vairākām kļūdām. Tāpēc uzreiz pēc ziņojuma izsniegÅ”anas BOOT Pievienosim bezgalÄ«gu cilpu. Tas viņu uz kādu laiku aizkavēs...

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

Šāds viltÄ«gs kods tiek izmantots ā€œuzticamÄ«bas labadā€: kaut kur dzirdēju, ka bezgalÄ«ga cilpa ir nenoteikta uzvedÄ«ba, taču kompilators diez vai uzminēs (atgādinu, ka saskaņā ar 0x10000 atrodas BootROM).

3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

Šķiet, ko gan citu gaidīt - skarbi iegulti, kādi tur pirmkodi? Bet iekŔā tas raksts autors atkļūdoja C kodu... 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.

3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

Jums vienkārÅ”i jālejupielādē nevis MIF fails vai tvertne, bet gan sākotnējā versija ELF formātā.

Tagad, ar n-to mēģinājumu, jūs varat uzminēt adresi, kurā izpilde turpināsies (tas ir vēl viens iemesls, kāpēc kompilatoram nevajadzētu uzminēt, ka cilpa ir bezgalīga). Komanda

set variable $pc=0xADDR

ļauj lidojuma laikā mainÄ«t reÄ£istra vērtÄ«bu (Å”ajā gadÄ«jumā paÅ”reizējās instrukcijas adresi). Ar tās palÄ«dzÄ«bu jÅ«s varat mainÄ«t atmiņā ierakstÄ«tās vērtÄ«bas (un atmiņas kartētos reÄ£istrus).

Galu galā es nonācu pie secinājuma (neesmu pārliecināts, kurÅ” ir pareizs), ka mums ir "nepareizas sistēmas SD kartes attēls", un mums ir jāiet nevis uz paÅ”u lejupielādēto datu sākumu, bet gan uz 0x89800 baiti tālāk:

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

Iespējams, to ietekmēja arÄ« tas, ka, tā kā pa rokai nebija liekas 4Gb kartes, paņēmu 2Gb un pēc nejauŔības principa nomainÄ«ju to Makefile. DEMO_END=11718750 par DEMO_END=3078900 (nemeklējiet jēgu konkrētā nozÄ«mē - tādas nav, vienkārÅ”i tagad attēls ir ievietots kartē).

Otrais līmenis, U-Boot

Tagad vēl ā€œkrÄ«tamā€, bet jau esam Ä«stajā vietā 0x0000000080089a84. Te gan jāatzÄ«st: patiesÄ«bā prezentācija neiet ā€œar visām pieturāmā€, bet gan ir daļēji uzrakstÄ«ta ā€œpēcā€, tāpēc Å”eit jau paspēju ievietot pareizo dtb failu no mÅ«su SoC, izlabot to iestatÄ«jumos HiFive_U-Boot mainÄ«gs CONFIG_SYS_TEXT_BASE=0x80089800 (nevis 0x08000000), lai lejupielādes adrese atbilstu faktiskajai adresei. Tagad mēs ielādējam nākamā lÄ«meņa karti, citu attēlu:

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

Un mēs redzam:

   ā”‚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)                      ā”‚

Turklāt mēs pārejam starp 308. un 309. rindiņām. Un tas nav pārsteidzoÅ”i, ņemot vērā to $sp slēpjas jēga 0xfffffffe31cdc0a0. Diemžēl tas arÄ« pastāvÄ«gi ā€œaizbēgā€ 307. rindas dēļ. Tāpēc mēģināsim iestatÄ«t pārtraukuma punktu plkst. trap_entry, un pēc tam atgriezieties pie 0x80089800 (U-Boot ieejas punkts), un cerēsim, ka pirms pārlēkÅ”anas nav nepiecieÅ”ams pareizi iestatÄ«t reÄ£istrus... Izskatās, ka tas darbojas:

(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

Steka rādÄ«tājs ir tik, atklāti sakot: tas norāda, apejot RAM vispār (ja vien mums, protams, vēl nav adreÅ”u tulkoÅ”anas, bet cerēsim uz vienkārÅ”u iespēju).

Mēģināsim aizstāt rādÄ«tāju ar 0x881cf950. Rezultātā mēs nonākam pie secinājuma, ka handle_trap zvanÄ«ja un zvanÄ«ja, un tajā paŔā laikā mēs ieejam _exit_trap ar argumentu epc=2148315240 (decimāldaļās):

(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

Iestatīt pārtraukuma punktu uz strnlen, mēs turpinām un redzam:

(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

Å Ä·iet, _exit_trap vēlas sniegt atkļūdoÅ”anas informāciju par notikuÅ”o izņēmumu, bet viņŔ nevar. Tātad, kaut kā mÅ«su avoti atkal netiek parādÄ«ti. set directories ../freedom-u-sdk/HiFive_U-Boot/ PAR! Tagad parādÄ«ts!

PalaidÄ«sim to vēlreiz un no steka izsekojam sākotnējās problēmas cēloni, kas izraisÄ«ja pirmo kļūdu (mcause == 5). Ja pareizi sapratu rakstÄ«to Å”eit 37. lappusē, tad Å”is izņēmums nozÄ«mē Load access fault. Å Ä·iet, ka iemesls ir Å”eit

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 ir tāda pati nepareiza nozÄ«me, un iekŔā board_init_f_init_reserve rodas kļūda. Å Ä·iet, ka tas ir vaininieks: mainÄ«gais ar nepārprotamu nosaukumu CONFIG_SYS_INIT_SP_ADDR. Tas ir definēts failā HiFive_U-Boot/include/configs/HiFive-U540.h. Kādā brÄ«dÄ« pat iedomājos, varbÅ«t, nu, vajadzētu pielikt klāt procesoram boot loader - varbÅ«t bÅ«tu vieglāk procesoru nedaudz salabot? Bet tad es redzēju, ka tas vairāk atgādina artefakts no lÄ«dz galam nepabeigtam#if 0-specifiskus iestatÄ«jumus citai atmiņas konfigurācijai, un varat mēģināt to izdarÄ«t:

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

Kādā brÄ«dÄ« kruÄ·u skaits tehnoloÄ£iskie stiprinājumi ir sasniedzis kritisko punktu. Pēc nelielas pÅ«lÄ“Å”anās es nonācu pie nepiecieÅ”amÄ«bas izveidot pareizo portu savam dēlim. Lai to izdarÄ«tu, mums ir jākopē un jāpielāgo vairāki faili, lai tie atbilstu mÅ«su konfigurācijai.

Nu, apmēram, Å”eit ir maza tabula

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

Sīkāku informāciju var atrast krātuves.

Kā izrādÄ«jās, Å”ajā SiFive platē dažu ierīču reÄ£istriem ir dažādas adreses. IzrādÄ«jās arÄ«, ka U-Boot ir konfigurēts, izmantojot Kconfig mehānismu, kas jau pazÄ«stams no Linux kodola - piemēram, jÅ«s varat komandēt make menuconfig, un jÅ«su priekŔā parādÄ«sies ērts teksta interfeiss, kurā bÅ«s redzami parametru apraksti ? utt. Vispār sakopot treŔā aprakstu no divu dēļu aprakstiem, izmetot no turienes visādas pretenciozas PLL pārkonfigurācijas (acÄ«mredzot, tas kaut kā ir saistÄ«ts ar vadÄ«bu no saimniekdatora caur PCIe, bet tas nav droÅ”i) , es saņēmu kādu programmaparatÅ«ru, kas piemērotos laikapstākļos uz Marsa man caur UART sniedza ziņojumu par to, no kura commit hash tas tika kompilēts, un par to, cik daudz man ir DRAM (bet es pats ierakstÄ«ju Å”o informāciju galvenē).

VienÄ«gi žēl, ka pēc tam plate parasti pārstāja reaģēt caur procesoru JTAG, un ielāde no SD kartes manā konfigurācijā diemžēl nav ātra. No otras puses, dažreiz BootROM deva ziņojumu, ka ERROR, neizdevās palaist, un uzreiz parādÄ«jās U-Boot. Toreiz man atklājās: acÄ«mredzot pēc bitu plÅ«smas pārstartÄ“Å”anas FPGA atmiņa netiek izdzēsta, tai nav laika ā€œattrenētā€ utt. ÄŖsāk sakot, jÅ«s varat vienkārÅ”i, kad parādās ziņojums LOADING / izveidojiet savienojumu ar atkļūdotāju un komandu set variable $pc=0x80089800, tādējādi apejot Å”o ilgo ielādi (protams, pieņemot, ka pagājuÅ”ajā reizē tas salÅ«za pietiekami agri, ka tam nebija laika ielādēt neko virs sākotnējā koda).

Starp citu, vai tas vispār ir normāli, ka procesors pilnībā sasalst un JTAG atkļūdotājs nevar pieslēgties tam ar ziņojumiem?

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

Tātad, pagaidiet! Å o jau esmu redzējis! Kaut kas lÄ«dzÄ«gs notiek, kad TileLink ir strupceļā, un es kaut kā neuzticos atmiņas kontroliera autoram - pats to rakstÄ«ju... PēkŔņi pēc pirmās veiksmÄ«gās procesora pārbÅ«ves pēc kontrollera rediģēŔanas es redzēju:

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

Uz Å”o dÄ«vaino lÄ«niju iepriekÅ” In: serial nepievērsiet uzmanÄ«bu - es mēģināju saprast uz piekārtā procesora, vai tas pareizi darbojas ar vidi. Ko jÅ«s domājat: "Tas ir karājies Ŕādi desmit minÅ«tes"? Vismaz izdevās pārvietot un doties uz sāknÄ“Å”anas izvēlni! Neliela atkāpe: lai gan U-Boot tiek ielādēts pirmajos 2^24 baitos no SD kartes, startējot, tas kopē sevi uz tālāku adresi, kas ierakstÄ«ta konfigurācijas galvenē, vai vienkārÅ”i uz augstākajām RAM adresēm. , un veic ELF pārvietoÅ”anu -rakstzÄ«mes, un nodod tur kontroli. Tātad: izskatās, ka izgājām Å”o lÄ«meni un saņēmām bonusu, ka procesors pēc tam nav cieÅ”i nokarājies.

Tātad, kāpēc taimeris nedarbojas? Izskatās, ka pulkstenis nez kāpēc nestrādā...

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

Ko darīt, ja pagriežat bultiņas manuāli?

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

Pēc tam:

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

Secinājums: pulkstenis netikŔķ. Iespējams, tāpēc tastatÅ«ras ievade nedarbojas:

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

Problēma izrādījās tā, ka es biju nedaudz pārāk gudrs: procesora konfigurācijai pievienoju atslēgu:

  case DTSTimebase => BigInt(0)

... pamatojoties uz to, ka komentārā bija teikts "ja nezināt, atstājiet 0." Un galu galā WithNBigCores Es tikko iestatÄ«ju to uz 1MHz (kā, starp citu, tas bija norādÄ«ts U-Boot konfigurācijā). Bet sasodÄ«ts, es esmu veikls un rÅ«pÄ«gs: es nezinu, Å”eit tas ir 25 MHz! Galu galā nekas nedarbojas. Es noņēmu savus "uzlabojumus" un...

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 #

JÅ«s pat varat ievadÄ«t komandas! Piemēram, pēc nelielas pabakstÄ«Å”anās, jÅ«s beidzot varat uzminēt, lai ieietu mmc_spi 1 10000000 0; mmc part, samazinot SPI frekvenci no 20MHz lÄ«dz 10MHz. Kāpēc? Nu konfigurācijā bija ierakstÄ«ta maksimālā frekvence 20MHz, un tur joprojām ir rakstÄ«ts. Bet, cik es saprotu, saskarnes, vismaz Å”eit, darbojas Ŕādi: kods sadala aparatÅ«ras vienÄ«bas frekvenci (manējais visur ir 25 MHz) ar mērÄ·i un iegÅ«st iegÅ«to vērtÄ«bu kā dalÄ«tāju attiecÄ«gajā vadÄ«klā. reÄ£istrēties. Problēma ir tāda, ka ja priekÅ” 115200Hz UART ir aptuveni tas, kas vajadzÄ«gs, tad, izdalot 25000000 ar 20000000, sanāk 1, t.i. tas darbosies ar 25MHz. VarbÅ«t tas ir normāli, bet, ja tiek noteikti ierobežojumi, tas nozÄ«mē, ka kādam tas ir vajadzÄ«gs (bet tas nav droÅ”i)... Kopumā ir vieglāk to nolikt un virzÄ«ties tālāk - tālu un, diemžēl, uz ilgu laiku. 25MHz nav Core i9.

Konsoles izvade

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

Labi, mēs esam sasnieguÅ”i nākamo lÄ«meni, bet tas joprojām ir salst. Un dažreiz tas arÄ« apkaisa izņēmumus. JÅ«s varat redzēt mcause, gaidot kodu norādÄ«tajā adresē $pc un tad si bÅ«t ieslēgtam trap_entry. Pats U-Boot apstrādātājs var izvadÄ«t tikai mcause = 0..4, tāpēc esiet gatavs iestrēgt nepareizā sāknÄ“Å”anas gadÄ«jumā. Tad es iegāju konfigurācijā, sāku skatÄ«ties, ko mainu, un atcerējos: tur iekŔā conf/rvboot-fit.txt rakstÄ«ts:

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

Labi, sakārtosim visus failus, nomainiet kodola komandrindu ar kaut ko līdzīgu, jo pastāv aizdomas, ka SIF0 - Ŕī ir izvade kaut kur caur PCIe:

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

MainÄ«sim jaukÅ”anas algoritmu no SHA-256 uz MD5: man nav vajadzÄ«ga kriptogrāfijas stiprums (it Ä«paÅ”i atkļūdoÅ”anas laikā), tas aizņem Å”ausmÄ«gi ilgu laiku, un, lai ielādes laikā uztvertu integritātes kļūdas, MD5 ir pārāk viegli. Kāds ir gala rezultāts? IepriekŔējo lÄ«meni sākām pabeigt ievērojami ātrāk (vienkārŔākas jaukÅ”anas dēļ), un tika atvērts nākamais:

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

Bet pulkstenis negriežas...

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

Ups, izskatās, ka pulksteņa laboÅ”ana izrādÄ«jās placebo, lai gan man toreiz Ŕķita, ka tas palÄ«dz. Nē, tas, protams, ir jālabo, taču vispirms pagriezÄ«sim bultiņas manuāli un paskatÄ«simies, kas notiek:

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.

Tikmērā€¦

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

Nē, es ieÅ”u automatizēt pulksteni - pretējā gadÄ«jumā viņŔ varbÅ«t nolems kalibrēt taimeri tur!

Tikmēr paÅ”reizējās instrukcijas adrese norāda kaut kur

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>

ielādētā Berkeley sāknÄ“Å”anas ielādētājā. Mani personÄ«gi mulsina pieminÄ“Å”ana htif ā€” resursdatora saskarne, ko izmanto kodola piesietai palaiÅ”anai (tas ir, sadarbÄ«bā ar resursdatora ARM), es pieņēmu, ka tas ir savrups. Tomēr, ja atrodat Å”o funkciju avota kodā, varat redzēt, ka ne viss ir tik slikti:

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

Uzdevums: sāciet pulksteni

Reģistru meklēŔana CLINT mūs noved pie

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

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

Kas savienojas ar RTC vai noslēpumaino MockAON, par kuru es sākumā domāju: ā€œKas mums Å”eit ir? Vai nav skaidrs? Izslēgsim to!" Tā kā es joprojām nesaprotu, kāda pulksteņa maÄ£ija tur notiek, es vienkārÅ”i ieviesÄ«Å”u Å”o loÄ£iku 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
  }

Dodamies uz Linux kodolu

Å eit stāsts jau ir ievilcies un kļuvis nedaudz vienmuļŔ, tāpēc aprakstÄ«Å”u to no augÅ”as uz leju:

BBL pieņēma FDT klātbÅ«tni plkst 0xF0000000, bet es jau izlaboju! Nu, paskatÄ«simies vēlreiz... Atradu iekŔā HiFive_U-Boot/arch/riscv/lib/boot.c, aizvietots ar 0x81F00000, kas norādÄ«ta U-Boot sāknÄ“Å”anas konfigurācijā.

Tad BBL sÅ«dzējās, ka nav atmiņas. Mans ceļŔ bija funkcijā mem_prop, kas iekŔā riscv-pk/machine/fdt.c: no turienes es uzzināju, ka jums ir jāatzÄ«mē fdt ram mezgls kā device_type = "memory" - tad, iespējams, procesora Ä£enerators bÅ«s jālabo, bet pagaidām es to ierakstÄ«Å”u tikai manuāli - jebkurā gadÄ«jumā es manuāli pārsÅ«tÄ«ju Å”o failu.

Tagad es saņēmu ziņojumu (nodroÅ”ināts formatētā veidā ar vagona atgrieÅ”anu):

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.

Å Ä·iet, ka iespējas ir norādÄ«tas pēc vajadzÄ«bas riscv,kernel-start Šø riscv,kernel-end DTB, bet nulles tiek parsētas. AtkļūdoÅ”ana query_chosen parādÄ«ja, ka BBL mēģina parsēt 32 bitu adresi, bet tas saskaras ar pāri <0x0 0xADDR>, un Ŕķiet, ka pirmā vērtÄ«ba ir vismazāk nozÄ«mÄ«gie biti. Pievienots sadaļai chosen

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

un laboja vērtÄ«bu Ä£enerÄ“Å”anu: nepievieno 0x0 pirmais elements.

Å Ä«s 100500 XNUMX vienkārŔās darbÄ«bas atvieglos pingvÄ«na kriÅ”anas vēroÅ”anu:

Slēpts teksts

   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)

(logotipu parāda BBL, bet logotipu ar laikspiedoliem parāda kodols).

Par laimi, es nezinu, kā tas ir visur, bet RocketChip, pievienojot atkļūdotāju, izmantojot JTAG, jūs varat noķert slazdus no kastes - atkļūdotājs apstāsies tieŔi Ŕajā brīdī.

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); // < Š’Š« ŠŠŠ„ŠžŠ”Š˜Š¢Š•Š”Š¬ Š—Š”Š•Š”Š¬
}

Kā teica vecais joks, CPU nav atrasts, darbojas programmatūras emulācija. Nu vai neskrien. Pazudis vienā procesora kodolā.

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

Labs komentārs iekŔā linux/arch/riscv/kernel/setup.c - sava veida žoga krāsoÅ”ana, izmantojot Toma Sojera metodi. Vispār nez kāpēc Å”odien nebija uzvarētāju, balva tiek pārcelta uz nākamo izlozi...

Šeit es ierosinu beigt jau tā garo rakstu.

Turpinājums sekos. Būs cīņa ar viltīgu blakti, kas izdodas paslēpties, ja lēnām piezagsies tai ar vienu soli.

Teksta lejupielādes ekrānuzņēmums (ārēja saite):
3. daļa: Gandrīz Linux ielāde no SD kartes uz RocketChip

Avots: www.habr.com

Pievieno komentāru