В un controller di memoria più o menu di travagliu hè statu implementatu, o megliu, un wrapper over IP Core da Quartus, chì hè un adattatore per TileLink. Oghje, in a rùbbrica "Avemu porting RocketChip à un bordu cinese pocu cunnisciutu cù Cyclone" vi vede una cunsola di travagliu. U prucessu pigliò un pocu di più: aghju digià pensatu chì lanciassi rapidamente Linux è andaraghju, ma ùn era micca u casu. In questa parte, pruponu di vede u prucessu di lanciari U-Boot, BBL, è i timidi tentativi di u kernel Linux per inizializà. Ma ci hè una cunsola - U-Boot, è abbastanza avanzata, avè assai di ciò chì aspittàvate da una cunsola piena.
U hardware includerà una carta SD cunnessa via l'interfaccia SPI, è ancu un UART. In a parte di u software, BootROM serà rimpiazzatu cù xip nantu sdboot è, in fattu, i seguenti tappe di carica sò state aghjunte (nantu à a carta SD).
Finitura di u hardware
Allora, u compitu: avete bisognu di cambià à un core "grande" è cunnette un UART (da Raspberry) è un adattatore SD (avemu utilizatu una carta da Catalex cù sei pin: GND, VCC, MISO, MOSI, SCK, CS) .
In principiu, tuttu era abbastanza sèmplice. Ma prima di rializà questu, sò statu ghjittatu un pocu da un latu à l'altru: dopu à l'ora precedente, aghju decisu chì di novu avia bisognu di mischjà. System qualcosa cum'è HasPeripheryUART (è implementazione in cunseguenza), u listessu per a carta SD - è tuttu serà prontu. Allora decisu di vede cumu hè stata implementata in un disignu "seriu". Allora, chì hè seriu in questu? Arty, apparentemente, ùn hè micca adattatu - u mostru resta unleahshed.DevKitConfigs. È di colpu si hè risultatu chì ci sò parechje superposizioni in ogni locu, chì sò stati aghjuntu à traversu paràmetri da chjave. Pensu chì questu hè probabilmente assai flessibile è configurabile, ma mi piacerebbe almenu eseguisce qualcosa prima ... Ùn avete micca a stessa cosa, solu più simplice è più fastidiosa ?... Hè quandu aghju scontratu vera.iofpga.FPGAChip per i Microsemi FPGAs è subitu subitu spartitu per quote è pruvatu à fà a mo propria implementazione per analogia, per furtuna ci hè più o menu tuttu u "disposizione di a scheda madre" in un schedariu.
Hè risultatu chì avete veramente bisognu di aghjunghje System.scala linii
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
...Linea in u corpu di a classa System aghjunghje infurmazione nantu à a frequenza à quale sta parte di u nostru SoC opera à u schedariu dts. Per quantu capiscu, DTS / DTB hè un analogu staticu di a tecnulugia plug-and-play per i dispositi incorporati: l'arburu di descrizzione di dts hè compilatu in un schedariu dtb binariu è trasferitu da u bootloader à u kernel per pudè cunfigurà currettamente u hardware. Curiosamente, senza a linea cù tlclock tuttu sintetizza perfettamente, ma cumpilà BootROM (lasciami ricurdà, avà questu serà digià sdboot) ùn funziona micca - durante u prucessu di compilazione analizza u schedariu dts è crea un capu cù una macro TL_CLK, grazia à quale ellu puderà cunfigurà currettamente divisori di frequenza per interfacce esterni.
Averete ancu bisognu di correggere ligeramente u "cablamentu":
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
}I catene di registru, per esse onestu, sò stati aghjuntu solu per analogia cù certi altri posti in u codice originale. Probabilmente, anu da prutege . Forse in некоторых i blocchi anu digià a so propria prutezzione, ma prima vogliu lancià almenu "à un livellu d'alta qualità". Una quistione più interessante per mè hè perchè MISO è MOSI appiccicate in diverse dq? Ùn aghju micca trovu a risposta ancu, ma pare chì u restu di u codice s'appoghja solu in una tale cunnessione.
Fisicamente, aghju semplicemente attribuitu i pins di disignu à i cuntatti gratuiti nantu à u bloccu è trasfirìu u jumper di selezzione di tensione à 3.3V.
adattatore SD
Vista da sopra:

Vista di fondu:

Debugging Software: Strumenti
Prima, parlemu di i strumenti di debugging dispunibili è di e so limitazioni.
Minicom
Prima, avemu bisognu di qualchì manera di leghje ciò chì u bootloader è u kernel output. Per fà questu in Linux (in questu casu, nantu à quellu di u RaspberryPi), avemu bisognu di u prugramma Minicom. In generale, ogni prugramma chì travaglia cù un portu seriale farà.
Per piacè nutate chì quandu partendu, u nome di u dispositivu portu deve esse specificatu cum'è -D /dev/ttyS0 - dopu l'opzione -D. Ebbè, l'infurmazioni principali: per esce, aduprà Ctrl-A, X. Aghju avutu un casu quandu sta cumminazione ùn hà micca travagliatu - allora pudete solu dì da una sessione SSH vicina killall -KILL minicom.
Ci hè una altra funzione. In particulare, u RaspberryPi hà dui UART, è i dui porti ponu esse adattati per qualcosa: unu per Bluetooth, l'altru per difettu produce a cunsola di kernel. Fortunatamente, stu cumpurtamentu pò esse annullatu .
Riscrittura di memoria
Quandu u debugging, per pruvà una ipotesi, aghju avutu qualchì volta carica bootloader (scusate) in RAM direttamente da l'ospite. Forsi questu pò esse fattu direttamente da GDB, ma à a fine aghju seguitu un percorsu simplice: aghju copiatu u schedariu necessariu à Raspberry, hà ancu trasmessu u portu 4444 via SSH (telnet da OpenOCD) è hà utilizatu u cumandimu. load_image. Quandu fate, pare chì tuttu hè congelatu, ma in fattu "ùn dorme, lampeghja solu lentamente": Scaricate u schedariu, u faci solu à una vitezza di un paru di kilobyte per seconda.
Funzioni di stallà breakpoints
Parechje persone prubabilmente ùn anu micca avutu à pensà à questu quandu debugging programmi regularmente, ma i punti di rottura ùn sò micca sempre stabiliti in hardware. Calchì volta stabilisce un puntu di rottura implica scrive temporaneamente struzzioni speciali in u locu ghjustu direttamente in codice machine. Per esempiu, questu hè cumu u mo cumandamentu standard hà travagliatu b in GDB. Eccu ciò chì seguita:
- ùn pudete micca mette un puntu in BootROM perchè ROM
- Pudete stabilisce un puntu di breakpoint nantu à u codice caricatu in RAM da a carta SD, ma avete bisognu à aspittà finu à ch'ella hè caricata. Altrimenti, ùn scriveremu micca un pezzu di codice, ma u caricatore riscriverà u nostru puntu di rottura.
Sò sicuru chì pudete dumandà esplicitamente à utilizà punti di rottura hardware, ma ci sò un numeru limitatu di elli in ogni modu.
Sustituzione rapida di BootROM
In u stadiu iniziale di debugging, ci hè spessu un desideriu di riparà u BootROM è pruvate di novu. Ma ci hè un prublema: BootROM hè parti di u disignu caricatu in u FPGA, è a so sintesi hè una materia di uni pochi di minuti (è questu hè dopu a compilazione quasi immediata di l'imagine BootROM stessu da C è Assembler...). Fortunatamente, in realità tuttu assai più veloce: a sequenza di l'azzioni hè a siguenti:
- regenerate bootrom.mif (aghju cambiatu à MIF invece di HEX, perchè aghju sempre avutu qualchì problema cù HEX, è MIF hè u formatu nativu di Alter)
- in Quartus dì
Processing -> Update Memory Initialization File - nantu à l'elementu Assembler (in a colonna di manca di Tasks) cumandimu Start again
Tuttu di tuttu - un paru di decine di seconde.
Preparazione di a carta SD
Tuttu quì hè relativamente simplice, ma avete bisognu à esse pazienti è avè circa 14 Gb di spaziu di discu:
git clone https://github.com/sifive/freedom-u-sdk
git submodule update --recursive --init
makeDopu à quale vi tocca à inserisce una pulita, o piuttostu, unu chì ùn cuntene nunda necessariu, carta SD, è eseguisce
sudo make DISK=/dev/sdX format-boot-loader… Induve sdX - dispusitivu assignatu à a carta. ATTENZIONE : i dati nantu à a carta seranu sguassati, soprascritti è in generale ! Ùn vale a pena di fà tutta l'assemblea da sottu sudoperchè allora tutti i manufatti di custruzzione apparteneranu root, è l'assemblea duverà esse fatta da sottu sudo sempre.
U risultatu hè una carta marcata in GPT cù quattru partizioni, una di quale hà FAT cù uEnv.txt è una maghjina bootable in u formatu FIT (cuntene parechje sub-imaghjini, ognunu cù u so propiu indirizzu di scaricamentu), l'altra partizione hè in biancu, deve esse furmatu in Ext4 per Linux. Dui sezzioni più - misteriu: U-Boot vive nantu à una (u so offset, quant'è l'aghju capitu, hè hardcoded in BootROM), à l'altru, pare chì e so variabili di l'ambienti vivenu, ma ùn l'utilizanu ancu.
Livellu unu, BootROM
A saviezza populari dice: "Se in a prugrammazione ci hè ballu cù un tamburinu, allora in l'elettronica ci hè ancu ballu cù un extinguisher". Ùn si tratta ancu di u fattu chì una volta aghju quasi brusgiatu u bordu, decisu chì "Bè, GND hè u listessu livellu bassu". (apparentemente, una resistenza ùn saria micca male dopu tuttu ...) Hè più nantu à u fattu chì, se e mani ùn cresce micca da quì, allora l'elettronica ùn cesseghja mai di purtà sorprese: quandu si salda u connettore à u bordu, ùn pudia micca saldà i cuntatti bè - u video mostra cumu si sparghje direttamente a saldatura. nantu à tutta a cunnessione, appricà solu un ferru di saldatura, Per mè, hà "slapped" à l'aleatoriu. Eppo, forsi a saldatura ùn era micca adattatu per a temperatura di u ferru di saldatura, forsi qualcosa altru... In generale, quandu aghju vistu chì aghju avutu una decina di cuntatti, aghju rinunziatu è cuminciatu à debugging. E poi cuminciò misteriu: Aghju cunnessu RX / TX da UART, cargu u firmware - dice
INIT
CMD0
ERROREbbè, tuttu hè logicu - ùn aghju micca cunnessu u modulu di a carta SD. Corregemu a situazione, caricate u firmware ... È u silenziu ... Perchè ùn aghju micca cambiatu d'idea, ma a piccula scatula appena aperta: unu di i pins di u modulu duvia esse cunnessu à VCC. In u mo casu, u modulu supporta 5V per l'alimentazione, cusì senza pensà duie volte, aghju aghjustatu u filu chì vene da u modulu à u latu oppostu di u bordu. Cum'è un risultatu, u connector crookedly soldedly addivintò skewed, è U cuntattu UART hè statu simplicemente persu. facepalm.jpg In generale, "un capu cattivu ùn dà micca riposu à i gammi", è e mani storte ùn dà micca riposu à a testa...
In u risultatu, aghju vistu u longu aspittatu
INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /Inoltre, si move è l'indicatore di carica gira. Mi ricordu subitu i mo ghjorni di scola è a carica tranquilla di MinuetOS da un dischettu. A menu chì l'unità ùn macina micca.
U prublema hè chì dopu à u messagiu BOOT ùn succede nunda. Questu significa chì hè ora di cunnette via OpenOCD à Raspberry, à GDB nantu à l'ospite, è vede ciò chì hè.
Prima, a cunnessione cù GDB hà dimustratu immediatamente questu $pc (contatore di prugramma, indirizzu di l'istruzzione attuale) vola à 0x0 - questu prubabilmente succede dopu à parechji errori. Dunque, subitu dopu chì u missaghju hè publicatu BOOT Aghjunghjite un ciclu infinitu. Questu u ritarderà per un pezzu ...
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;
}Un tali codice complicatu hè utilizatu "per affidabilità": aghju intesu in qualchì locu chì un loop infinitu hè un Comportamentu Undefined, ma u compilatore hè improbabile di indovinà (vi ricordu chì secondu 0x10000 situatu BootROM).

Sembra, chì altru aspittà - duru embedded, chì tipu di codici fonte ci sò? Ma in l'autore stava debugging u codice C... 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.
Basta à scaricà micca u schedariu MIF o u bin, ma a versione originale in formatu ELF.
Avà pudete indovinà cù l'ennesimu tentativu l'indirizzu induve l'esekzione cuntinueghja (questu hè un altru mutivu per quessa chì u compilatore ùn deve micca indovinatu chì u ciclu hè infinitu). squadra
set variable $pc=0xADDRpermette di cambià u valore di u registru nantu à a mosca (in questu casu, l'indirizzu di l'istruzzioni attuale). Cù u so aiutu, pudete cambià i valori scritti in memoria (è i registri mappati in memoria).
In ultimamente, sò ghjuntu à a cunclusione (micca sicura di quale hè currettu) chì avemu "una maghjina di carta SD di u sistema sbagliatu", è avemu bisognu di andà micca à u principiu di i dati scaricati, ma per 0x89800 bytes in più:
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 .rodataForsi questu hè statu ancu affettatu da u fattu chì ùn avè micca una carta 4Gb innecessaria in manu, aghju pigliatu una 2Gb è l'aghju rimpiazzata in u Makefile in casu. DEMO_END=11718750 nantu DEMO_END=3078900 (ùn circate micca u significatu in un significatu specificu - ùn ci hè nimu, hè solu chì avà l'imaghjini hè pusatu nantu à a carta).
Livellu dui, U-Boot
Avà simu sempre "caduta", ma simu digià in u locu ghjustu 0x0000000080089a84. Quì aghju da ammette: in fattu, a presentazione ùn và micca "cù tutte e tappe", ma hè parzialmente scritta "dopu", cusì quì aghju digià sappiutu inserisce u schedariu dtb currettu da u nostru SoC, currettu in i paràmetri. HiFive_U-Boot variabile CONFIG_SYS_TEXT_BASE=0x80089800 (invece di 0x08000000) in modu chì l'indirizzu di scaricamentu currisponde à quellu attuale. Avà caricamu a mappa di u prossimu livellu, un'altra maghjina:
(gdb) file ../freedom-u-sdk/work/HiFive_U-Boot/u-boot
(gdb) tui enÈ vedemu:
│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) │Inoltre, saltemu trà e linee 308 è 309. È ùn hè micca surprisante, postu chì in $sp si trova u significatu 0xfffffffe31cdc0a0. Alas, hè ancu constantemente "fughje" per via di a linea 307. Dunque, pruvemu à stabilisce un puntu di ruptura à trap_entry, è poi vultà à 0x80089800 (U puntu di entrata di U-Boot), è speremu chì ùn hà micca bisognu chì i registri per esse stallati currettamente prima di saltà... Sembra chì funziona:
(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 = 0x81cf950U puntatore di stack hè cusì cusì, francamente parlante: indica l'annullamentu di a RAM in tuttu (salvo chì, sicuru, ùn avemu micca digià traduzzione di l'indirizzu, ma speremu una opzione simplice).
Pruvemu di rimpiazzà u puntatore cù 0x881cf950. In u risultatu, ghjunghjemu à a cunclusione chì handle_trap chjamatu è chjamatu, è à u stessu tempu andemu in _exit_trap cun argumentu epc=2148315240 (in decimali):
(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,0Set breakpoint à strnlen, cuntinuemu è vede:
(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 PCParenu esse, _exit_trap vole furnisce infurmazioni di debugging nantu à l'eccezzioni chì hè accaduta, ma ùn pò. Dunque, in qualchì manera e nostre fonti ùn sò micca visualizate di novu. set directories ../freedom-u-sdk/HiFive_U-Boot/ À propositu! Avà affissatu!
Ebbè, corremu di novu, è vede da a pila traccia a causa di u prublema originale chì hà causatu u primu errore (mcause == 5). Se aghju capitu bè ciò chì hè scrittu in a pagina 37, allora sta eccezzioni significa Load access fault. U mutivu pare esse quì
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 hà u listessu significatu incorrectu, è in l'internu board_init_f_init_reserve un errore accade. Sembra chì questu hè u culprit: una variabile cù un nome senza ambiguità CONFIG_SYS_INIT_SP_ADDR. Hè definitu in u schedariu HiFive_U-Boot/include/configs/HiFive-U540.h. In un certu puntu aghju ancu pensatu, forsi, bè, aghju da aghjunghje un boot loader per u processatore - forse saria più faciule per riparà u processatore un pocu? Ma dopu aghju vistu chì era più cum'è un artefattu da micca cumplettamente cumpletu#if 0- paràmetri specifichi per una cunfigurazione di memoria diversa, è pudete pruvà à fà questu:
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 */À un certu puntu u numeru di crutches hà righjuntu un puntu criticu. Dopu avè luttatu un pocu, aghju ghjuntu à a necessità di fà u portu currettu per u mo bordu. Per fà questu, avemu bisognu di cupià è aghjustà una quantità di schedari per adattà à a nostra cunfigurazione.
Ebbè, circa, eccu una piccula tavola
trosinenko@trosinenko-pc:/hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot$ git show --name-status
commit 39cd67d59c16ac87b46b51ac1fb58f16f1eb1048 (HEAD -> zeowaa-1gb)
Author: Anatoly Trosinenko <anatoly.trosinenko@gmail.com>
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.hI dettagli ponu esse truvati in .
Cum'è s'hè risultatu, nantu à questu bordu SiFive, i registri di certi dispositi anu indirizzi diffirenti. Hè ancu risultatu chì U-Boot hè cunfiguratu cù u mecanismu Kconfig, digià familiarizatu da u kernel Linux - per esempiu, pudete cumanda. make menuconfig, è una interfaccia di testu còmuda apparirà davanti à voi chì mostra descrizzione di i paràmetri da ? ecc. In generale, dopu avè cobbled inseme una descrizzione di u terzu da e descrizzioni di dui schede, scacciò ogni tipu di ricunfigurazioni PLL pretenziose da quì (apparentemente, questu hè in qualchì manera cunnessu cù u cuntrollu da l'urdinatore host via PCIe, ma questu ùn hè micca sicuru) , Aghju ricivutu qualchì firmware, chì, in u tempu ghjustu in Mars, m'hà datu un messagiu via UART nantu à quale commit hash hè statu compilatu, è quantu DRAM aghju (ma aghju scrittu sta infurmazione in l'intestazione).
L'unica pietà hè chì, dopu à questu, u bordu di solitu cessava di risponde via u processatore JTAG, è a carica da una carta SD hè, sfortunatamente, micca veloce in a mo cunfigurazione. Per d 'altra banda, qualchì volta BootROM hà datu un missaghju chì ERROR, ùn hà micca riesciutu à boot, è U-Boot apparsu immediatamente. Hè tandu ch'ellu mi s'avvicinava: apparentemente, dopu avè riavviatu u bitstream in u FPGA, a memoria ùn hè micca sguassata, ùn hà micca tempu di "untrain", etc. In corta, pudete simpricimenti quandu un missaghju appare LOADING / cunnette cù un debugger è cumanda set variable $pc=0x80089800, bypassing thereby this long loading (di sicuru, in l'assunzione chì l'ultima volta si rumpiu abbastanza prima ch'ellu ùn hà micca avutu u tempu di carica nunda in cima à u codice originale).
Per via, hè in generale normale chì u processatore si congela completamente è u debugger JTAG ùn pò micca cunnette cù i missaghji?
Error: unable to halt hart 0
Error: dmcontrol=0x80000001
Error: dmstatus =0x00030c82Allora, aspetta ! Aghju digià vistu questu! Qualcosa di sìmulu succede quandu TileLink hè in bloccu, è in qualchì manera ùn aghju micca fiducia in l'autore di u controller di memoria - l'aghju scrittu stessu ... Di colpu, dopu a prima ricustruzzione di successu di u processatore dopu à edità u controller, aghju vistu:
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À sta strana linea prima In: serial ùn fate micca attenzione - aghju pruvatu à capisce nantu à un processore appiccicatu s'ellu funziona bè cù l'ambiente. Chì vulete dì, "Hè appesu cusì per deci minuti"? Almenu hà sappiutu di traslocà è andate à u menu di boot ! Una piccula digressione: ancu se U-Boot hè caricatu in i primi 2 ^ 24 bytes da a carta SD, quandu principia, si copia à un indirizzu più luntanu, sia scrittu in l'intestazione di cunfigurazione, sia solu à l'indirizzi più alti di RAM. , è esegue ELF relocation -caratteri, è trasferimentu cuntrollu ci. Allora: pare chì avemu passatu stu livellu è avemu ricevutu un bonus chì u processatore ùn hè micca appiccicatu strettu dopu.
Allora perchè u timer ùn funziona micca? Sembra chì l'orologio ùn funziona micca per una certa ragione...
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000E se girassi e frecce manualmente?
(gdb) set variable *0x0200bff8=310000000
(gdb) cAllora:
Hit any key to stop autoboot: 0
MMC_SPI: 0 at 0:1 hz 20000000 mode 0Conclusioni: u clock ùn hè micca tick. Questu hè probabilmente perchè l'input di u teclatu ùn funziona micca:
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 == '[') {
...U prublema hè diventatu chì eru un pocu troppu intelligente: aghju aghjustatu a chjave à a cunfigurazione di u processatore:
case DTSTimebase => BigInt(0)... basatu annantu à u fattu chì u cummentariu hà dettu "se ùn sapete micca, lasciate 0". È dopu tuttu WithNBigCores Aghju stabilitu solu à 1MHz (cum'è, per via, era indicatu in a cunfigurazione U-Boot). Ma maledetta, sò pulito è meticulosu : ùn sò micca cunnoscu quì, quì hè 25MHz ! In fine, nunda ùn funziona. Aghju eliminatu i mo "miglioramenti" è ...
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 #Pudete ancu inserisce cumandamenti! Per esempiu, dopu à sbuccà un pocu, pudete infine invintà per entre mmc_spi 1 10000000 0; mmc part, riducendu a frequenza SPI da 20MHz à 10MHz. Perchè? Ebbè, a frequenza massima di 20MHz hè stata scritta in a cunfigurazione, è hè sempre scrittu quì. Ma, quantu aghju capitu, l'interfacce, almenu quì, funzionanu cusì: u codice divide a freccia di l'unità hardware (a meia hè 25MHz in ogni locu) da u mira, è stabilisce u valore resultanti cum'è divisore in u cuntrollu currispundente. iscrizzione. U prublema hè chì se per un UART 115200Hz ci hè apprussimatamente ciò chì hè necessariu, allora se dividite 25000000 da 20000000 uttene 1, i.e. hà da travaglià à 25MHz. Forsi questu hè normale, ma se e restrizioni sò stabilite, significa chì qualcunu hà bisognu (ma questu ùn hè micca sicuru) ... In generale, hè più faciule per stabilisce è andate avanti - luntanu è, alas, per un bellu pezzu. 25MHz ùn hè micca un Core i9.
Output di cunsola
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 0x82000000Va bè, avemu ghjuntu à u prossimu livellu, ma hè sempre congelatu. È qualchì volta sprinkles ancu eccezzioni. Pudete vede mcause stendu in attesa di u codice à l'indirizzu specificatu $pc è dopu si esse on trap_entry. U gestore U-Boot stessu pò esse solu per mcause = 0..4, cusì preparate per esse bloccatu in un boot incorrectu. Allora aghju andatu in a cunfigurazione, cuminciò à vede ciò chì cambiava, è ricurdatu: quì in conf/rvboot-fit.txt scrittu:
fitfile=image.fit
# below much match what's in FIT (ugha)Ebbè, mettemu tutti i fugliali in cunfurmità, rimpiazzà a linea di cummanda di u kernel cù qualcosa cusì, postu chì ci sò suspetti chì SIF0 - questu hè l'output in qualchì locu via PCIe:
-bootargs=console=ttySIF0,921600 debug
+bootargs=console=ttyS0,125200 debugE cambiemu l'algoritmu di l'hashing da SHA-256 à MD5: Ùn aghju micca bisognu di forza criptografica (in particulare quandu u debugging), ci vole un tempu terribilmente longu, è per catturà errori di integrità durante a carica, MD5 hè troppu faciule. Chì ghjè u risultatu finale ? Avemu cuminciatu à compie u livellu precedente notevolmente più veloce (per via di un hashing più simplice), è u prossimu si apre:
...
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
3Ma u clock ùn hè micca ticc...
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000Oops, pare chì a currezzione di u clock hè statu un placebo, ancu s'ellu mi pareva à l'epica chì aiutava. Innò, di sicuru, deve esse riparatu, ma prima turnemu e frecce manualmente è vede ciò chì succede:
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.Intantu…
Loading Kernel Image ... OK
Booting kernel in
3
2
1
0
## Starting application at 0x80000000 ...Innò, andaraghju à automatizà u clock - altrimenti forse deciderà di calibre u timer quì!
Intantu, l'indirizzu di l'istruzzioni attuale punta in qualchì locu
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>Dentru u Berkeley Boot Loader caricatu. In modu persunale, ciò chì mi cunfonde nantu à questu hè a menzione htif - Interfaccia d'ospiti utilizata per u lanciu tethered di u kernel (vale à dì, in cuuperazione cù l'ARM di l'ospite), aghju assuciatu standalone. Tuttavia, se truvate sta funzione in u codice fonte, pudete vede chì micca tuttu hè cusì male:
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: principià u clock
A ricerca di registri in CLINT ci porta à
val io = IO(new Bundle {
val rtcTick = Bool(INPUT)
})
val time = RegInit(UInt(0, width = timeWidth))
when (io.rtcTick) { time := time + UInt(1) }Chì cunnetta à RTC, o à u misteriu MockAON, di quale aghju pensatu inizialmente: "Allora, chì avemu quì? Un chjaru? Spegnemu!" Siccomu ùn aghju micca capitu chì tipu di magia di u clock si passa quì, per quessa, aghju solu riimplementà sta logica in 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
}Facendu u nostru modu versu u kernel Linux
Quì a storia hè digià trascinata è hè diventata un pocu monotona, cusì l'aghju da descriverà da cima à fondu:
BBL assume a prisenza di FDT at 0xF0000000, ma l'aghju digià currettu ! Ebbè, guardemu di novu... Truvatu in HiFive_U-Boot/arch/riscv/lib/boot.c, rimpiazzatu da 0x81F00000, specificata in a cunfigurazione di u boot U-Boot.
Allora BBL si lagnava chì ùn ci era micca memoria. A mo strada hè stata in a funzione mem_prop, chì in riscv-pk/machine/fdt.c: da quì aghju amparatu chì avete bisognu di marcà u node ram fdt cum'è device_type = "memory" - allora, forse, u generatore di u processatore deve esse currettu, ma per avà l'aghju da scrive solu manualmente - in ogni modu, aghju trasfirutu manualmente stu schedariu.
Avà aghju ricevutu u missaghju (furnitu in forma furmatu, cù ritorni di carru):
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.Sembra chì l'opzioni sò indicati cum'è necessariu riscv,kernel-start и riscv,kernel-end in DTB, ma i zeri sò analizati. Debugging query_chosen hà dimustratu chì BBL prova di analizà un indirizzu 32-bit, ma vene à traversu un paru <0x0 0xADDR>, è u primu valore pare esse i bits menu significativu. Aggiuntu à a sezione chosen
chosen {
#address-cells = <1>;
#size-cells = <0>;
...
}è currettu a generazione di valori: ùn aghjunghje micca 0x0 u primu elementu.
Questi 100500 passi simplici renderanu più faciule fighjà un pinguinu caduta:
Testu oculatu
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)(u logu hè visualizatu da BBL, è quellu cù timestamps hè visualizatu da u kernel).
Fortunatamente, ùn sò micca sapè cumu hè in ogni locu, ma in RocketChip, quandu cunnette un debugger via JTAG, pudete catturà trappule fora di a scatula - u debugger si ferma esattamente à questu puntu.
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 PCfreedom-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); // < ВЫ НАХОДИТЕСЬ ЗДЕСЬ
}Cum'è u vechju scherzu dicia, CPU ùn hè micca truvatu, emulazione di software in esecuzione. Ebbè, o micca corre. Persu in un core unicu di processore.
/* The lucky hart to first increment this variable will boot the other cores */
atomic_t hart_lottery;
unsigned long boot_cpu_hartid;Bellu cumentu in linux/arch/riscv/kernel/setup.c - un tipu di pittura di una fence cù u metudu Tom Sawyer. In generale, per qualchì mutivu ùn ci era micca vincitori oghje, u premiu hè trasferitu à u prossimu sorteggio ...
Quì prupongu di finisce l'articulu digià longu.
À seguità. Ci sarà una lotta cun un bug astutu chì riesce à ammuccià se ti arrampicate lentamente nantu à ellu cun un passu.
Screencast di scaricamentu di testu (ligame esternu):
Source: www.habr.com
