NĂ« u implementua njĂ« kontrollues memorie mĂ« shumĂ« pak funksional, mĂ« saktĂ«sisht â njĂ« mbĂ«shtjellĂ«s mbi IP Core nga Quartus, i cili shĂ«rben si njĂ« ndĂ«rfaqs pĂ«r TileLink. Sot nĂ« rubrikĂ«n "Ne po portojmĂ« RocketChip nĂ« njĂ« bord tĂ« panjohur kinez me Cyclone" do tĂ« shihni njĂ« konsolĂ« funksionale. Procesi zgjati pak mĂ« shumĂ«: mendova se do tĂ« ngarkoja me shpejtĂ«si Linux dhe do tĂ« shkonim pĂ«rpara, por jo. NĂ« kĂ«tĂ« pjesĂ« propozoj tĂ« shohim procesin e ngarkimit tĂ« U-Boot, BBL, dhe pĂ«rpjekjet e ngathta tĂ« kernel-it tĂ« Linux pĂ«r t'u inicializuar. Por ka njĂ« konsolĂ« â ajo e U-Boot-it, dhe Ă«shtĂ« mjaft e avancuar, duke pasur shumĂ« nga ato qĂ« prisni nga njĂ« konsolĂ« tĂ« plotĂ«.
Në pjesën harduerike do të shtohet karta SD, e lidhur përmes interfesës SPI, si dhe UART. Në pjesën software BootROM do të zëvendësohet me xip në sdboot dhe, në fakt, do të shtohen fazat e ngarkimit të mëposhtme (në kartelën SD).
Përmirësimi i pjesës harduerike
Pra, detyra: duhet të kalojmë në një bërthamë "të madhe" dhe të lidhim UART (nga Raspberry) dhe adaptern e SD (u përdor një bord nga Catalex me gjashtë pinë: GND, VCC, MISO, MOSI, SCK, CS).
NĂ« parim, gjithçka ishte mjaft e thjeshtĂ«. Por para se ta kuptoja kĂ«tĂ«, u ndjeva pak e lĂ«kundur: pas herĂ«s sĂ« mĂ«parshme, vendosa se ishte e nevojshme tĂ« pĂ«rzihej pĂ«rsĂ«ri nĂ« Sistemi diçka si HasPeripheryUART (dhe nĂ« realizimin pĂ«rkatĂ«s), po ashtu pĂ«r kartelĂ«n SD â dhe gjithçka do tĂ« ishte gati. MĂ« pas vendosa tĂ« shoh se si ishte realizuar nĂ« njĂ« dizajn "tĂ« rĂ«ndĂ«sishĂ«m". Pra, çfarĂ« kemi kĂ«tu nga tĂ« rĂ«ndĂ«sishmet? Arty, duket, nuk i pĂ«rgjigjet â mbetet monstĂ«r unleahshed.DevKitConfigs. Dhe papritmas doli se kishim disa overlay tĂ« ndryshĂ«m, qĂ« shtohen pĂ«rmes parametrave tĂ« çelĂ«save. Mendoj se ndoshta Ă«shtĂ« shumĂ« fleksibĂ«l dhe konfigurueshĂ«m, por mĂ« duhet tĂ« paktĂ«n diçka pĂ«r tĂ« nisur... Por a keni diçka tĂ« ngjashme, vetĂ«m mĂ« tĂ« thjeshtĂ« dhe me defekte?.. Aty u ndesha me vera.iofpga.FPGAChip pĂ«r FPGA tĂ« Microsemi dhe menjĂ«herĂ« e kam pĂ«rdorur pĂ«r citate duke provuar tĂ« bĂ«j realizimin tim duke u bazuar nĂ« tĂ«, pĂ«r fat tĂ« mirĂ« kĂ«tu Ă«shtĂ« disi e gjitha "konstrukti i bordit tĂ« sistemit" nĂ« njĂ« skedar.
Doli, në fakt, se thjesht duhet të shtoj në System.scala rreshtat
class System(implicit p: Parameters) extends RocketSubsystem
...
me HasPeripherySPI
me HasPeripheryUART
...
{
val tlclock = new FixedClockResource("tlclk", p(DevKitFPGAFrequencyKey))
...
}
class SystemModule[+L <: System](_outer: L)
extends RocketSubsystemModuleImp(_outer)
...
me HasPeripheryUARTModuleImp
me HasPeripheryGPIOModuleImp
...Rreshti nĂ« trupin e klasĂ«s Sistemi shton informacionin mbi frekuencĂ«n me tĂ« cilĂ«n funksionon ky pjesĂ« e SoC tonĂ« nĂ« skedarin dts. Sa kuptoj, DTS/DTB Ă«shtĂ« njĂ« ekuivalent statik i teknologjisĂ« plug-and-play pĂ«r pajisjet e integruara: struktura e pĂ«rshkrimit dts kompilohet nĂ« njĂ« skedar binar dtb dhe i dĂ«rgohet ngarkuesit pĂ«r t'i lejuar atij tĂ« konfigurojĂ« saktĂ«sisht pajisjet. Ajo qĂ« Ă«shtĂ« interesante, pa rreshtin me tlclock gjithçka sintetohet mirĂ«, por nuk do tĂ« jetĂ« e mundur tĂ« kompilojmĂ« BootROM (mĂ« kujtohet, tani do tĂ« jetĂ« tashmĂ« sdboot) â gjatĂ« procesit tĂ« kompilimit, ai analizon skedarin dts dhe krijon njĂ« header me makro TL_CLK, duke e lejuar qĂ« ai tĂ« konfigurojĂ« saktĂ«sisht ndarĂ«sit e frekuencĂ«s pĂ«r ndĂ«rfaqet e jashtme.
Po ashtu, do të nevojitet të bëjmë disa rregullime në "shtrirjen":
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
}ZinxhirĂ«t e regjistrave, sinqerisht, janĂ« shtuar thjesht pĂ«r analogji me disa vende tĂ« tjera nĂ« kodin origjinal. Me sa duket, ata duhet tĂ« mbrojnĂ« nga . Ndoshta, nĂ« disa bloke, tashmĂ« ka mbrojtje tĂ« vet, por sĂ« pari do tĂ« doja tĂ« niste tĂ« paktĂ«n "nĂ« njĂ« nivel tĂ« kualitetit tĂ« lartĂ«". Pyetja mĂ« interesante pĂ«r mua Ă«shtĂ« â pse MISO dhe MOSI janĂ« tĂ« lidhura nĂ« tĂ« ndryshme dq? ĐŃĐČĐ”Ńа Ń ĐżĐŸĐșа ŃаĐș Đž ĐœĐ” ĐœĐ°ŃŃĐ», ĐœĐŸ, ĐżĐŸŃ
ĐŸĐ¶Đ”, ĐŸŃŃалŃĐœĐŸĐč ĐșĐŸĐŽ ŃаŃŃŃĐžŃŃĐČĐ°Đ”Ń ĐžĐŒĐ”ĐœĐœĐŸ ĐœĐ° ŃаĐșĐŸĐ” ĐżĐŸĐŽĐșĐ»ŃŃĐ”ĐœĐžĐ”.
Fizikisht, thjesht kam caktuar dalje të dizajnit në kontaktet e lira në bllok dhe kam zhvendosur jumperin e zgjedhjes së tensionit në 3.3V.
SD-adapteri
Pamja nga lart:

Pamja nga poshtë:

Debugimi i pjesës së softuerit: mjetet
Fillimisht do të flasim për mjetet e disponueshme të debugimit dhe kufizimet e tyre.
Minicom
SĂ« pari, do tĂ« na nevojitet ndonjĂ« mĂ«nyrĂ« pĂ«r tĂ« lexuar atĂ« qĂ« shkruan ngarkuesi dhe bĂ«rthama. PĂ«r kĂ«tĂ«, nĂ« Linux (nĂ« kĂ«tĂ« rast â nĂ« atĂ« qĂ« Ă«shtĂ« nĂ« RaspberryPi) do tĂ« na nevojitet programi Minicom. NĂ« pĂ«rgjithĂ«si, çdo program pĂ«r pĂ«rdorim me port serial Ă«shtĂ« i pĂ«rshtatshĂ«m.
Kujdes, qĂ« kur nisi, emri i pajisjes sĂ« portit duhet tĂ« jepet si -D /dev/ttyS0 â pas opsionit -D. E, informacioni kryesor: pĂ«r daljen pĂ«rdorni Ctrl-A, X. NĂ« tĂ« vĂ«rtetĂ«, kam pasur njĂ« rast kur kjo kombinim nuk punoi â atĂ«herĂ« mund tĂ« thoni nga seanca e fqinjit SSH thjesht killall -KILL minicom.
Ka një tipar tjetër. Konkretisht në RaspberryPi ka dy UART, dhe të dy portet mund të jenë tashmë të përshtatur për diçka: njëri për Bluetooth, ndërsa tjetri për defaut shfaq konsolën e bërthamës. Fatmirësisht, ky sjellje mund të rikonfigurohet. .
Rikodimi i memories.
Gjatë depurimit, për të verifikuar hipotezën ndonjëherë më ka ndodhur që duhet ta ngarkoja ngarkuesin (më vjen keq) në memorien e përkohshme direkt nga hosti. Ndoshta, mundet që ta bëni këtë direkt nga GDB, por në fund të fundit ndoqa rrugën e thjeshtë: kopjova dosjen e nevojshme në Raspberry, kalova gjithashtu portin 4444 përmes SSH (telnet nga OpenOCD) dhe përdora komandën load_image. Kur e ekzekutoni, duket sikur gjithçka është ngrirë, por në të vërtetë «nuk fle, thjesht pala e diçka të ngadaltë»: po ngarkon dosjen, thjesht e bën këtë me një shpejtësi disa kilobajt në sekondë.
Tiparet e vendosjes së breakpoint-ëve.
Mund të mos ketë ndodhur që shumë njerëz ta mendojnë këtë gjatë depurimit të programeve normale, por pikat e ndalimit nuk vendosen gjithmonë në mënyrë harduerike. Ndonjëherë vendosja e një breakpoint-i përfshin shkrimin përkohësisht të një instruksioni të veçantë në vendin e duhur drejt në kodin e makinerisë.Për shembull, kështu vepronte komanda standarde b në GDB. Ja se çfarë rezulton nga kjo:
- nuk mund të vendosni një pikë brenda BootROM, sepse ROM
- një pikë ndalimi mbi kodin e ngarkuar në memore me SD kartë mund të vendoset, por duhet të presim që të ngarkohet. Në rast të kundërt, nuk do të rishkruajmë një copë kod, por ngarkuesi do të rishkruajë breakpoint-in tonë.
Jam i sigurt se mund të kërkoni qartë të përdoren pikat e ndalimit harduerike, por ato në çdo rast janë të numëruara.
Zëvendësimi i shpejtë i BootROM.
Në fazën fillestare të depurimit shpesh lind dëshira për të rregulluar BootROM dhe të provoni përsëri. Por ka një problem: BootROM është pjesë e dizajnit, i ngarkuar në FPGA, dhe sintetizimi i tij është një punë disa minutash (dhe kjo pas kompilimit pothuajse të menjëhershëm të vetë imazhit BootROM nga C dhe Assembler...). Fatmirësisht, në të vërtetë gjithçka është shumë më e shpejtë:sekuenca e veprimeve është kjo:
- rigenëro bootrom.mif (kam kaluar në MIF në vend të HEX, sepse me HEX gjithmonë kam pasur disa probleme, dhe MIF është formati i natyrshëm i Altera)
- në Quartus tha
Processing -> Update Memory Initialization File - në pikën Assembler (në kolonën e majtë Tasks) urdhëro Start again.
PĂ«r tĂ« gjitha kĂ«to â disa dhjetĂ«ra sekonda.
Përgatitja e kartës SD.
Këtu gjithçka është mjaft e thjeshtë, por duhet të jeni të duruar dhe të keni rreth 14Gb hapësirë në disk:
git clone https://github.com/sifive/freedom-u-sdk
git submodule update --recursive --init
makePas kësaj, duhet të futni një kartë SD të pastër, për më saktë, që nuk përmban asgjë të nevojshme, dhe të kryeni
sudo make DISK=/dev/sdX format-boot-loader⊠ku sdX â pajisja e caktuar pĂ«r kartĂ«n. KĂSHILLĂ: tĂ« dhĂ«nat nĂ« kartĂ« do tĂ« fshihen, do tĂ« tejkalohen dhe pĂ«rgjithĂ«sisht! Nuk ka shumĂ« kuptim tĂ« bĂ«ni tĂ« gjithĂ« ndĂ«rtimin nga â informasiya tÉhlĂŒkÉsizliyi, sepse atĂ«herĂ« tĂ« gjithĂ« artefaktet e ndĂ«rtimit do t'i pĂ«rkasin root, dhe ndĂ«rtimi do tĂ« duhet tĂ« bĂ«het nga â informasiya tÉhlĂŒkÉsizliyi pĂ«rsĂ«ri.
NĂ« fund, rezulton njĂ« kartĂ«, e ndarĂ« nĂ« GPT me katĂ«r pjesĂ«, ku njĂ«ra prej tyre Ă«shtĂ« FAT me uEnv.txt dhe njĂ« imazh ngarkues nĂ« formatin FIT (ai pĂ«rmban disa nĂ«nimazhe, secila me adresĂ«n e saj tĂ« ngarkimit), pjesa tjetĂ«r â e pastĂ«r, Ă«shtĂ« e supozuar tĂ« formatohet nĂ« Ext4 pĂ«r Linux. Dy pjesĂ«t tjera â misterioze: nĂ« njĂ«rin ndodhet U-Boot (sipas sa kam kuptuar, offseti i tij Ă«shtĂ« i koduar nĂ« BootROM), nĂ« tjetrĂ«n, duket se ndodhin variablat e tij tĂ« ambientit, por unĂ« pĂ«r momentin nuk i pĂ«rdor.
Niveli i parë, BootROM
Shpirti popullor thotĂ«: «NĂ«se nĂ« programim ka kĂ«rcime me bumbulla, nĂ« elektronikĂ« ka edhe me zjarĂ«fikĂ«s». Nuk Ă«shtĂ« çështja qĂ« njĂ« herĂ« isha shumĂ« afĂ«r pĂ«r tĂ« djegur bordin, duke menduar se «Epo GND Ă«shtĂ« e njĂ«jta gjĂ« si niveli i ulĂ«t» (duket, resistori do kishte ndihmuarâŠ) ĂĂ«shtja Ă«shtĂ« mĂ« shumĂ« se nĂ«se duar nuk rriten nga aty, elektronika nuk ndalon sĂ« sjelluri surpriza: duke pĂ«rshkruar konektorin nĂ« bordin, nuk arrita tĂ« pĂ«rfundoj kontaktet siç duhet â nĂ« video tregojnĂ« si llak shtrihesha vetĂ« nĂ« tĂ« gjithĂ« lidhjen, vetĂ«m vendosni hekurin, por unĂ« e bĂ«ra gjithçka siç ndodhi. Ndoshta, llaku nuk ishte i pĂ«rshtatshĂ«m pĂ«r temperaturĂ«n e hekurit, ndoshta diçka tjetĂ«r⊠NĂ« pĂ«rgjithĂ«si, duke parĂ« se kam mĂ« shumĂ« se njĂ« duzinĂ« kontakte, u dorĂ«zova dhe fillova tĂ« debug. Dhe kĂ«tu filloi misteri: lidh RX/TX nga UART, ngarkoj firmware â dhe atij i shkruhet
INIT
CMD0
ERROREpo, gjithçka Ă«shtĂ« logjike â moduli i kartĂ«s SD nuk e kam lidhur. KorrigjojmĂ« situatĂ«n, ngarkojmĂ« firmware⊠Dhe heshtje⊠ĂfarĂ« nuk mendoja, por kutia e vogĂ«l u hap lehtĂ«: njĂ« nga daljet e modulit duhej tĂ« ishte lidhur nĂ« VCC. NĂ« rastin tim, moduli pĂ«rkrahte 5V pĂ«r energji, kĂ«shtu qĂ«, pa menduar pĂ«r shumĂ«, vendosa telin qĂ« vinte nga moduli nĂ« anĂ«n e kundĂ«rt tĂ« bordit. Si rezultat, konektori i paqartĂ«suar doli jashtĂ« ekuilibri, dhe thjesht humbi kontakti UART. facepalm.jpg NĂ« pĂ«rgjithĂ«si, "koka e keqe nuk i jep qetĂ«si kĂ«mbĂ«ve", dhe duar tĂ« prera - kokĂ«s...
Në fund e pashë në Minicom të priturin
INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
PO loading /Për më tepër, ndëndizësi i ngarkimit po lëviz. Menjëherë më vijnë ndërmend vitet e shkollës dhe ngarkimi i ngadaltë i MinuetOS nga disku. Të paktën disku nuk schrëqet.
Problemi është se pas mesazhit BOOT nuk ndodh asgjë. Pra, është koha për t'u lidhur përmes OpenOCD në Raspberry, të lidhim GDB në host dhe të shohim se çfarë është.
Së pari, lidhja me GDB menjëherë tregoi se $pc (program counter, adresa e instrukcionit aktual) shkon në 0x0 - ndoshta kjo ndodh pas një gabimi të shumëfishtë. Pra, menjëherë pas dënimit të mesazhit BOOT do të shtojmë një cikël të pafund. Kjo do e ndalojë për pak...
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;
}Ky kod i zgjuar përdoret "për qëndrueshmëri": kam dëgjuar diku se, duket, cikli i pafund është një Comportament i Padrëjtë, dhe këtu kompajleri me siguri nuk do ta kuptojë (Kujtoj se sipas 0x10000 ndodhet BootROM).

Duket se, çfarë tjetër të pritet - një embedded i ashpër, çfarë të bëjmë me këtu burimet. Por në autori po e debugonte kodin në C... Kreks-feks-pex:
(gdb) file builds/zeowaa-e115/sdboot.elf
Një program po debugohet tashmë.
A jeni të sigurt që dëshironi ta ndryshoni skedarin? (y ose n) y
Duke lexuar simbolet nga builds/zeowaa-e115/sdboot.elf...kaluar.
Vetëm duhet ngarkuar jo skedari MIF dhe jo bin, por versionin origjinal në formatin ELF.
Tani mund të dështojmë disa herë për të gjetur adresën ku do të vazhdojë ekzekutimi (kjo është një arsye më shumë pse kompajleri nuk duhej të kuptonte se cikli ishte i pafund). Komanda
set variable $pc=0xADDRlejon të ndryshosh vlerën e regjistrit në flakë (në këtë rast - adresën e instrukcionit aktual). Me të mund të ndryshosh vlerat e ruajtura në memorie (dhe regjistrat e hartuar me memorie).
Në fund të fundit, arrita në përfundimin (nuk jam i sigurt se është i saktë), se kemi "imazhin e kartës sd të sistemit të gabuar", dhe duhet të kalojmë jo në fillimin e të dhënave të ngarkuara, por në 0x89800 bytë më tej:
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 .rodataNdoshta kjo është gjithashtu e lidhur me faktin që, pa patur një kartë të panevojshme 4Gb në dorë, mora një kartë 2Gb dhe duke e provuar e zëvendësova në Makefile. DEMO_END=11718750 në DEMO_END=3078900 (mos kërkoni kuptim në përkufizimin konkret - nuk ka, thjesht tani imazhi vendoset në kartë).
Niveli i dytë, U-Boot
Tani ende po «bien», por tani jemi në adresën e duhur 0x0000000080089a84. Këtu duhet të pranoj: në të vërtetë, tregimi nuk po shkon «me të gjitha ndalesat», por pjesërisht shkruhet tashmë «më vonë», prandaj këtu kam arritur të vendos skedarin e duhur dtb nga SoC ynë, duke e korrigjuar këtë në konfigurimin. HiFive_U-Boot variablin CONFIG_SYS_TEXT_BASE=0x80089800 (në vend të 0x08000000), që adresa e ngarkimit përputhet me të vërtetën. Tani ngarkojmë një kartë të nivelit të ardhshëm një tjetër imazh:
(gdb) file ..\/freedom-u-sdk\/work\/HiFive_U-Boot\/u-boot
(gdb) tui enDhe shohim:
â304
/* â
â305 * hyrja e grushtit â
â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) âPĂ«r mĂ« tepĂ«r, ne kĂ«rcyem midis rreshtave 308 dhe 309. Dhe nuk Ă«shtĂ« befasuese, duke pasur parasysh se nĂ« $sp ndodhet vlera 0xfffffffe31cdc0a0. FatkeqĂ«sisht, ajo gjithashtu vazhdimisht «ikĂ«n» pĂ«r shkak tĂ« rreshtit 307. Prandaj do tĂ« provojmĂ« tĂ« vendosim njĂ« pikĂ« ndalese nĂ« trap_entry, dhe pastaj tĂ« kthehemi pĂ«rsĂ«ri nĂ« 0x80089800 (pikĂ«n e hyrjes U-Boot), dhe shpresojmĂ« se ajo nuk kĂ«rkon vendosen e saktĂ« tĂ« regjistrave para kalimit... Duket se funksionon:
(gdb) b trap_entry
Breakpoint 1 në 0x80089a80: skedari \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S, linja 308.
(gdb) vendos variablën $pc=0x80089800
(gdb) c
Duke vazhduar.
Breakpoint 1, trap_entry () në \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S:308
(gdb) p\/x $sp
$4 = 0x81cf950Një tregues i tillë i grumbullit, për ta thënë, është duke treguar krejtësisht jashtë memorizimit (nëse, sigurisht, nuk kemi ende përkthimin e adresave, por të shpresojmë për variantin e thjeshtë).
Do të provojmë të zëvendësojmë treguesin në 0x881cf950. Në fund të fundit, arrijmë në atë që handle_trap thirret dhe thirret, duke u larguar në _exit_trap me argumentin epc=2148315240 (në formën decimal):
(gdb) x/10i 2148315240
0x800cb068 : lbu a4,0(a5)
0x800cb06c : bnez a4,0x800cb078
0x800cb070 : sub a0,a5,a0
0x800cb074 : ret
0x800cb078 : addi a5,a5,1
0x800cb07c : j 0x800cb064
0x800cb080 : addi sp,sp,-32
0x800cb084 : sd s0,16(sp)
0x800cb088 : sd ra,24(sp)
0x800cb08c : li s0,0Vëmë një pikë ndalese në strnlen, vazhdojmë dhe shohim:
(gdb) bt
#0 strnlen (s=s@entry=0x10060000 "", count=18446744073709551615) në lib/string.c:283
#1 0x00000000800cc14c në string (buf=buf@entry=0x881cbd4c "", end=end@entry=0x881cc15c "", s=0x10060000 "", field_width=, precision=, flags=) në lib/vsprintf.c:265
#2 0x00000000800cc63c në vsnprintf_internal (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=0x800d446e "s , epc x , ra lxn", fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=0x881cc1a0,
args@entry=0x881cc188) në lib/vsprintf.c:619
#3 0x00000000800cca54 në vsnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) në lib/vsprintf.c:710
#4 0x00000000800cca68 në vscnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) në lib/vsprintf.c:717
#5 0x00000000800ccb50 në printf (fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn") në lib/vsprintf.c:792
#6 0x000000008008a9f0 në _exit_trap (regs=, epc=2148315240, code=) në arch/riscv/lib/interrupts.c:92
#7 handle_trap (mcause=, epc=, regs=) në arch/riscv/lib/interrupts.c:55
#8 0x0000000080089b10 në trap_entry () në /hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot/arch/riscv/cpu/HiFive/start.S:343
Backtrace stopped: frame did not save the PCDuket se _exit_trap dëshiron të ofrojë informacionin e debugut për përjashtimin që ndodhi, por nuk po ia del. Pra, diçka sërish burimet tona nuk po shfaqen. vendos direktoriumet ..../freedom-u-sdk/HiFive_U-Boot/ O! Tani po shfaqen!
Siç duket, do ta nisim përsëri dhe do të shohim përmes shtegu të grumbullimit arsyen e problemit fillestar që shkaktoi gabimin e parë (mcause == 5). Nëse e kuptoj saktë atë që është shkruar në fq. 37, kjo përjashtim do të thotë Gabimi i aksesit në ngarkim. Arsyetimi, ndoshta është këtu
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 ka atĂ« vlerĂ«n e gabuar, dhe brenda board_init_f_init_reserve ndodh gabimi. Duket se ja dhe fajtori: variabla me emrin e qartĂ« CONFIG_SYS_INIT_SP_ADDR. Ajo Ă«shtĂ« e definuar nĂ« skedarin HiFive_U-Boot/include/configs/HiFive-U540.hNĂ« njĂ« moment, mendova madje, ndoshta mund ta lĂ« mĂ« pas, duke e pĂ«rmirĂ«suar ngarkuesin pĂ«r procesorin â ndoshta Ă«shtĂ« mĂ« e lehtĂ« tĂ« rregulloj pak procesorin? Por mĂ« pas pashĂ« se kjo duket mĂ« shumĂ« si njĂ« artifact nga konfigurimi i papĂ«rfunduar pĂ«r njĂ« konfigĆ«racion tjetĂ«r memorjeje, dhe mund tĂ« provoj ta bĂ«j kĂ«shtu:#if 0-
diff --git a/include/configs/HiFive-U540.h b/include/configs/HiFive-U540.h
index ca89383..245542c 100644
--- a/include/configs/HiFive-U540.h
+++ b/include/configs/HiFive-U540.h
@@ -65,12 +65,9 @@
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_0
#endif
#if 1
-
#define CONFIG_NR_DRAM_BANKS 1/
+#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM_0 0x80000000 /* SDRAM Bank #1 */
-#define PHYS_SDRAM_1
- (PHYS_SDRAM_0 + PHYS_SDRAM_0_SIZE) /* SDRAM Bank #2 */
-#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GB */
-#define PHYS_SDRAM_1_SIZE 0x10000000 /* 256 MB */
+#define PHYS_SDRAM_0_SIZE 0x40000000 /* 1 GB */
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_0
#endif
/*
@@ -81,7 +78,7 @@
#define CONSOLE_ARG "console=ttyS0,115200 "
/* Init Stack Pointer */
-#define CONFIG_SYS_INIT_SP_ADDR (0x08000000 + 0x001D0000 -
+#define CONFIG_SYS_INIT_SP_ADDR (0x80000000 + 0x001D0000 -
GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_LOAD_ADDR 0xa0000000 /* partway up SDRAM */Në një moment, numri i parregullimeve arriti një nivel kritik. Pas disa përpjekjesh, arrita në përfundimin se duhet të bëj një port korrekt për pllakën time. Për këtë duhet të kopjoj dhe rregulloj disa skedarë për konfigurimin tonë.
Pra, përafërsisht, ja pak
trosinenko@trosinenko-pc:/hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot$ git show --name-status
commit 39cd67d59c16ac87b46b51ac1fb58f16f1eb1048 (HEAD -> zeowaa-1gb)
Author: Anatoly Trosinenko
Date: Tue Jul 2 17:13:16 2019 +0300
Mbështetje fillestare për pllakën Zeowaa A-E115FB
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.hDetajet mund të shihen në .
Si duket, nĂ« kĂ«tĂ« pllakĂ« tĂ« SiFive, regjistrat e disa pajisjeve kanĂ« adresa tĂ« tjera. Po ashtu, u zbulua se U-Boot konfigurohet me mekanizmin e njohur tĂ« Kconfig â pĂ«r shembull, mund tĂ« urdhĂ«rosh krijo menuconfig, dhe pĂ«rpara teje do tĂ« shfaqet njĂ« ndĂ«rfaqe tekstuale e pĂ«rshtatshme me pĂ«rshkrime tĂ« parametrave ? Dhe kĂ«shtu, duke bashkuar pĂ«rshkrimet e dy pllakatave pĂ«r tĂ« krijuar njĂ« pĂ«rshkrim tĂ« tretĂ«, duke hequr çdo parametĂ«r pompues tĂ« PLL (duke dukur se kjo lidhet me menaxhimin nga kompjuteri host pĂ«rmes PCIe, por nuk Ă«shtĂ« e sigurt), kam marrĂ« njĂ« firmware qĂ«, nĂ« kushte tĂ« mira nĂ« Mars, mĂ« shfaqte pĂ«rmes UART mesazhin se nga cili hash ishte ndĂ«rtuar dhe se sa DRAM kisha (por kĂ«tĂ« informacion e kisha shkruajtur vetĂ« nĂ« header).
FatkeqĂ«sisht, pas kĂ«saj, pllaka zakonisht ndalonte sĂ« pĂ«rgjigjuri pĂ«rmes JTAG tĂ« procesorit, ndĂ«rsa ngarkimi nga karta SD â njĂ« proces, fatkeqĂ«sisht, i ngadaltĂ« nĂ« konfigurimin tim. Nga ana tjetĂ«r, ndonjĂ«herĂ« BootROM jepte njĂ« mesazh qĂ« ERROR, nuk arriti tĂ« ngarkohej, dhe menjĂ«herĂ« shfaqej U-Boot. AtĂ«herĂ« e kuptova: duket se pas rinisjes bitstream nĂ« PLIS, kujtesa nuk pĂ«rditĂ«sohej, nuk arrin "tĂ« zbrazet" e kĂ«shtu me radhĂ«. NĂ« thelb, mund tĂ« lidhesha thjesht sapo shfaqej mesazhi LOADING / tĂ« lidhem me debugin dhe tĂ« jap urdhrin set variable $pc=0x80089800, duke shmangur kĂ«shtu kĂ«tĂ« ngarkim tĂ« gjatĂ« (sigurisht, me supozimin se herĂ«n e fundit dĂ«shtoi mjaft herĂ«t dhe nuk arriti tĂ« ngarkojĂ« diçka mbi kodin origjinal).
Për më tepër, a është në të vërtetë normale që procesori të ngrihet plotësisht, dhe JTAG-debugger nuk mund të lidhet me mesazhet
Gabim: e pamundur të ndalohet hart 0
Gabim: dmcontrol=0x80000001
Gabim: dmstatus =0x00030c82Ndalo! KĂ«tĂ« e kam parĂ« mĂ« parĂ«! Diçka e ngjashme ndodh kur ka dhe deadlock nĂ« TileLink, dhe autori i kontrolluesit tĂ« memories nuk mĂ« beson shumĂ« â vetĂ« e kam shkruar⊠Papritur, pas ndĂ«rtimit tĂ« parĂ« suksesĂ«s pas redaktimit tĂ« kontrolluesit, pashĂ«:
INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING
BOOT
U-Boot 2018.09-g39cd67d-dirty (03 Korrik 2019 - 13:50:33 +0300)
DRAM: 1 GiB
MMC:
BEFORE LOAD ENVBEFORE FDTCONTROLADDRBEFORE LOADADDRIn: serial
Out: serial
Err: serial
Goditni çelĂ«sin pĂ«r tĂ« ndaluar autoboot: 3NĂ« kĂ«tĂ« rresht tĂ« çuditshĂ«m pĂ«rpara In: serial Mos iu kujtoni â kjo Ă«shtĂ« unĂ« qĂ« pĂ«rpiqesha tĂ« kuptoja nĂ« njĂ« procesor tĂ« ngadalshĂ«m nĂ«se funksionon siç duhet me ambientin. ĂfarĂ« do tĂ« thotĂ«, "PĂ«r dhjetĂ« minuta po ngec kĂ«shtu"? A Ă«shtĂ« tĂ« paktĂ«n arrirĂ« tĂ« rilokohesh dhe tĂ« kalosh nĂ« menunĂ« e ngarkimit! NjĂ« shpjegim i vogĂ«l: megjithĂ«se U-Boot ngarkon mes 2^24 bajtĂ«ve nĂ« kartĂ«n SD, sapo tĂ« niset, ai kopjon veten nĂ« njĂ« adresĂ« tjetĂ«r, ose tĂ« regjistruar nĂ« kreun e konfigurimit, ose thjesht nĂ« adresat mĂ« tĂ« larta tĂ« memories, bĂ«n rilokimin e simboleve ELF dhe i kalon atij kontrollin. Pra, duket se kaluam kĂ«tĂ« nivel dhe si bonus morĂ«m njĂ« procesor qĂ« nuk ngec pas kĂ«saj.
Pra, pse nuk funksionon timeri? Duket se orĂ«t nĂ« pĂ«rgjithĂ«si nuk ecin pĂ«r ndonjĂ« arsyeâŠ
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000ĂfarĂ«, nĂ«se e rrotullojme dorezĂ«n me dorĂ«?
(gdb) set variable *0x0200bff8=310000000
(gdb) cAtëherë:
Shtypni ndonjë çelës për të ndaluar autoboot: 0
MMC_SPI: 0 në 0:1 hz 20000000 moda 0Përfundimi: orët nuk ecin. Padyshim, për këtë arsye nuk funksionon as hyrja me tastierë:
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:
/* Karakteri i parë i sekuencës ANSI 'e' */
if (c == 'e') {
*esc = 1;
*key = KEY_NONE;
}
break;
case 1:
/* Karakteri i dytë i ANSI '[' */
if (c == '[') {
...Problemi ishte se unë paksa e teprua: unë shtova në konfigurimin e procesorit çelësin:
case DTSTimebase => BigInt(0)⊠duke u orientuar nĂ« atĂ« qĂ« nĂ« koment ishte e thĂ«nĂ« "nĂ«se nuk e dini â lĂ«reni 0". Dhe, pĂ«r mĂ« tepĂ«r, WithNBigCores nĂ« tĂ« vĂ«rtetĂ« e vendoste nĂ« 1MHz (siç ishte shprehur nĂ« konfigurimin e U-Boot). Por unĂ«, pĂ«r hir tĂ« vĂ«rtetĂ«s, isha shumĂ« i kujdesshĂ«m dhe i saktĂ«: atje nuk e di, kĂ«tu 25MHz! Si rezultat, asgjĂ« nuk funksionon. E hoqa "pĂ«rmirĂ«simet" e mia dhe...
Shtypni ndonjë çelës për të ndaluar autoboot: 0
MMC_SPI: 0 në 0:1 hz 20000000 moda 0
## Lloji i tabelës së particionit të panjohur 0
libfdt fdt_path_offset() ktheu FDT_ERR_NOTFOUND
** Asnjë tabelë particionesh - mmc 0 **
## Informacion: madhësia e të dhënave të hyrjes = 34 = 0x22
Dërgimi i uEnv.txt boot2...
## Gabim: "boot2" nuk është e definuar
HiFive-Unleashed #Mund tĂ« futen madje edhe komandat! PĂ«r shembull, pas pak ndihmĂ«s dhe duke u pĂ«rpjekur, mund tĂ« kuptoni pĂ«rfundimisht tĂ« futni mmc_spi 1 10000000 0; mmc part, duke ulur frekuencĂ«n SPI nga 20MHz nĂ« 10MHz. Pse? Po, nĂ« konfigurim ishte shkruar frekuenca maksimale 20MHz, ajo Ă«shtĂ« aty edhe tani. Por, sa kuptova, interface-t, tĂ« paktĂ«n kĂ«tu, funksionojnĂ« kĂ«shtu: kodi ndan frekuencĂ«n e bllokut harduerik (nĂ« rastin tim â kudo 25MHz) me atĂ« tĂ« synuar, dhe vendos vlerĂ«n e marrĂ« si ndarĂ«s nĂ« regjistrin pĂ«rkatĂ«s tĂ« menaxhimit. Problemi Ă«shtĂ« se, nĂ«se pĂ«r UART-in 115200Hz do tĂ« ishte pĂ«rafĂ«rsisht ajo qĂ« nevojitet, atĂ«herĂ« nĂ«se e ndajmĂ« saktĂ«sisht 25000000 me 20000000 do tĂ« rezultojĂ« 1, dmth do tĂ« punojĂ« me 25MHz. Ndoshta, kjo Ă«shtĂ« e pranueshme, por nĂ«se vendosen kufizime, do tĂ« thotĂ« se dikujt i nevojitet (por kjo nuk Ă«shtĂ« e sigurt)⊠NĂ« çdo rast, Ă«shtĂ« mĂ« e lehtĂ« tĂ« vendosĂ«sh dhe tĂ« vazhdosh â larg dhe, fatkeqĂ«sisht, pĂ«r njĂ« kohĂ« tĂ« gjatĂ«. 25MHz â kjo nuk Ă«shtĂ« njĂ« Core i9.
Të dhënat e konsolës
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 0x82000000Mirë, kemi kaluar në një nivel të ri, por ende ngatërron. Ndonjëherë ndihmon dhe me eksepsione. Mund ta shohësh mcause duke pritur kodin në adresën e dhënë. $pc dhe pas si të gjendesh në trap_entry. Procesori nga U-Boot mund të shfaqë vetëm për mcause = 0..4, prandaj përgatituni të filloni nga e para në ngarkimin e pasaktë. Këtu hyra në konfigurim, e kontrollova çfarë kam ndryshuar dhe e kujtova: aty është conf/rvboot-fit.txt thuhet:
fitfile=image.fit
# mĂ« poshtĂ« duhet tĂ« pĂ«rputhet me atĂ« qĂ« Ă«shtĂ« nĂ« FIT (ugha)ĂfarĂ«, le tĂ« sjellim tĂ« gjithĂ« skedarĂ«t nĂ« pĂ«rputhje, do ta zĂ«vendĂ«sojmĂ« komandĂ«n e kernels ndjeshĂ«m kĂ«shtu, pasi kemi dyshime se SIF0 â Ă«shtĂ« njĂ« dalje diku pĂ«rmes PCIe:
-bootargs=console=ttySIF0,921600 debug
+bootargs=console=ttyS0,125200 debugDhe gjithashtu do ta ndryshojmĂ« algoritmin e kriptimit nga SHA-256 nĂ« MD5: qĂ«ndrueshmĂ«ria kriptografike nuk mĂ« nevojitet (pĂ«r mĂ« tepĂ«r, gjatĂ« rregullimit), konsiderohet qĂ« Ă«shtĂ« shumĂ« e ngadalshme, dhe pĂ«r kapjen e gabimeve tĂ« integritetit gjatĂ« ngarkimit, MD5 Ă«shtĂ« mjaftueshĂ«m. ĂfarĂ« Ă«shtĂ« rezultati? Kalimi nĂ« nivelin e mĂ«parshĂ«m Ă«shtĂ« bĂ«rĂ« dukshĂ«m mĂ« i shpejtĂ« (pĂ«r shkak tĂ« kriptimit mĂ« tĂ« thjeshtĂ«), dhe u hap niveli tjetĂ«r:
...
Verifikimi i Integritetit të Hash-it ... md5+ OK
Ngarkimi i ngarkesave nga 0x90a5a758 në 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
chosen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
libfdt fdt_path_offset() ktheu FDT_ERR_NOTFOUND
chosen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
Ngarkimi i Imazhit të Kernel-it ... OK
Duke ngarkuar kernelin në
3Veçse orët nuk po bëjnë tik-tak...
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000Ups, duket se rregullimi i orës ishte një placebo, megjithatë dukeshin se ndihmoi atëherë. Jo, duhet të riparojmë, por le të fillojmë të rrotullojmë akset manualisht dhe të shohim se çfarë ndodh:
0x00000000bff6dbb0 në ?? ()
(gdb) set variable *0x0200bff8=1000000
(gdb) c
Duke vazhduar.
^C
Programi mori sinjalin SIGINT, Ndërprerje.
0x00000000bff6dbb0 në ?? ()
(gdb) set variable *0x0200bff8=2000000
(gdb) c
Duke vazhduar.
^C
Programi mori sinjalin SIGINT, Ndërprerje.
0x00000000bff6dbb0 në ?? ()
(gdb) set variable *0x0200bff8=3000000
(gdb) c
Duke vazhduar.Ndërkohë...
Ngarkimi i Imazhit të Kernel-it ... OK
Duke ngarkuar kernelin në
3
2
1
0
## Duke filluar aplikacionin nĂ« 0x80000000 ...Jo, do tĂ« shkoj tĂ« automatizoj kalimin e orĂ«ve â ndoshta ai do tĂ« pĂ«rpiqet tĂ« kalibrojĂ« timerin atje!
Dhe adresa e instruksionit aktual tani tregon diku në
0000000080001c20 :
80001c20: 1141 addi sp,sp,-16
80001c22: e022 sd s0,0(sp)
80001c24: 842a mv s0,a0
80001c26: 00005517 auipc a0,0x5
80001c2a: 0ca50513 addi a0,a0,202 # 80006cf0
80001c2e: e406 sd ra,8(sp)
80001c30: f7fff0ef jal ra,80001bae
80001c34: 8522 mv a0,s0
80001c36: 267000ef jal ra,8000269c
80001c3a: 00010797 auipc a5,0x10
80001c3e: 41e78793 addi a5,a5,1054 # 80012058
80001c42: 639c ld a5,0(a5)
80001c44: c399 beqz a5,80001c4a
80001c46: 72c000ef jal ra,80002372
80001c4a: 45a1 li a1,8
80001c4c: 4501 li a0,0
80001c4e: dc7ff0ef jal ra,80001a14
80001c52: 10500073 wfi
80001c56: bff5 j 80001c52ndĂ«r Berkeley Boot Loader. Personalish mĂ« shqetĂ«son pĂ«rmendja htif â ndĂ«rfaqja e hostit, qĂ« pĂ«rdoret pĂ«r nisjen e bashkuar tĂ« kernelit (dmth nĂ« bashkĂ«punim me hostin ARM), unĂ« mendoja se do tĂ« ishte standalone. MegjithatĂ«, nĂ«se e gjeni kĂ«tĂ« funksion nĂ« burimin, shihet se nuk Ă«shtĂ« aq keq:
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"); }
}
}Krijo një orë
Kërkimi për regjistrat në CLINT na çon te
val io = IO(new Bundle {
val rtcTick = Bool(INPUT)
})
val time = RegInit(UInt(0, width = timeWidth))
when (io.rtcTick) { time := time + UInt(1) }I cili lidhet nĂ« RTC, ose nĂ« misteriozen MockAON, pĂ«r tĂ« cilin fillimisht mendoja: «ĂfarĂ« Ă«shtĂ« kjo kĂ«tu? E paqartĂ«? E çaktivizojmĂ«!» PĂ«r shkak se ende nuk e kuptoj se çfarĂ« magjie taktike ndodh atje, prandaj thjesht do ta riprogramoj kĂ«tĂ« logjikĂ« nĂ« System.scala:
val rtcDivider = RegInit(0.asUInt(16.W)) // për çdo rast do ta mbaj deri në 16GHz, jam optimist :)
val mhzInt = p(DevKitFPGAFrequencyKey).toInt
// Supozoni se frekuenca është e barabartë me një numër të plotë megahertz
rtcDivider := Mux(rtcDivider === (mhzInt - 1).U, 0.U, rtcDivider + 1.U)
outer.clintOpt.foreach { clint =>
clint.module.io.rtcTick := rtcDivider === 0.U
}Duke kaluar te Linux kernel
Këtu tregimi tashmë është shtrirë dhe është bërë pak monoton, prandaj do ta përshkruaj sipërfaqësisht:
BBL parashikonte një FDT në adresën 0xF0000000, dhe unë e kam korrigjuar! Po mirë, do të kërkoj përsëri⊠E gjeta në HiFive_U-Boot/arch/riscv/lib/boot.c, e zëvendësova me 0x81F00000, që u përcaktua në konfigurimin e nisjes së U-Boot.
Pastaj BBL ankohej se nuk kishte memorie. Rruga ime ishte nĂ« funksionin mem_prop, se nĂ« riscv-pk/machine/fdt.c: aty mĂ«sova se duhej tĂ« shĂ«nja lĂ«ndĂ«n fdt ram si device_type = "memory" â ndoshta, mĂ« vonĂ« do t'i duhet tĂ« rregulloj gjeneratorin e procesorit, por pĂ«r tani thjesht do ta shkruaj manualisht â pĂ«r çdo rast, unĂ« e kam transferuar kĂ«tĂ« skedar me dorĂ«.
Tani kam marrë një mesazh (i paraqitur në një format të strukturuar, me rikthime karte):
Kjo është bbl's dummy_payload. Për të nisur një bërthamë reale, ribëni konfigurimin e bbl
me flamurin --with-payload=PATH, pastaj rindërtoni bbl. Përndryshe,
bbl mund të përdoret në modalitetin vetëm firmware duke shtuar nyjat e pemës së pajisjeve
për një ngarkesë të jashtme dhe përdorni opsionet -bios dhe -kernel të QEMU.Duket se janë specifikuar mundësitë siç duhet. riscv,kernel-start dhe riscv,kernel-end në DTB, por analizohen zero. Debagimi query_chosen tregon se BBL po përpiqet të analizojë një adresë 32-bitësh, ndërsa i ndodhet një çift <0x0 0xADDR>, dhe vlera e parë, duket, është bitet më të ulëta. Shtova në seksionin chosen
chosen {
#address-cells = ;
#size-cells = ;
...
}dhe e rregullova gjenerimin e vlerave: mos shtoni 0x0 si elementin e parë.
Këto 100500 hapa të thjeshtë do të ndihmojnë lehtësisht për të parë se si bie pingvini:
Tekst i fshehur
Verifikimi i integritetit të Hash-it ... md5+ OK
Ngarkimi i përmbajtjeve nga 0x90a5a758 në 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
zgjedhur {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
#address-cells = ;
#size-cells = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() ktheu FDT_ERR_NOTFOUND
zgjedhur {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
#address-cells = ;
#size-cells = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
stdout-path = "uart0:38400n8";
};
Ngarkimi i imazhit të kernelit ... OK
Startimi i kernelit në
3
2
1
0
## Duke nisur aplikacionin në 0x80000000 ...
bbl ngarkues
SIFIVE, INC.
5555555555555555555555555
5555 5555
5555 5555
5555 5555
5555 5555555555555555555555
5555 555555555555555555555555
5555 5555
5555 5555
5555 5555
5555555555555555555555555555 55555
55555 555555 55555
55555 55555 55555
55555 5 55555
55555 55555
55555 55555
55555 55555
55555 55555
55555 55555
555555555
55555
5
SiFive RISC-V Core IP
[ 0.000000] OF: fdt: Duke inekot të dhënash 0x80000000 - 0x80200000
[ 0.000000] Versioni i Linux-it 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Mër 3 Korrik 21:29:21 MSK 2019
[ 0.000000] bootconsole [early0] e aktivizuar
[ 0.000000] Ramdisk fillestar në: 0x(____ptrval____) (16777216 bytes)
[ 0.000000] Zona e rangjeve:
[ 0.000000] DMA32 [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Normal [mem 0x00000000c0000000-0x00000bffffffffff]
[ 0.000000] Fillimi i zonës së lëvizshme për çdo nyje
[ 0.000000] Rangjet e hershëm të memorjes
[ 0.000000] nyja 0: [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Setup i memorizimit të nyjës 0 [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Në nyjën 0 totalpages: 261632
[ 0.000000] Zona DMA32: 3577 faqe përdoren për memmap
[ 0.000000] Zona DMA32: 0 faqe rezervuar
[ 0.000000] Zona DMA32: 261632 faqe, LIFO të grupeve:63
[ 0.000000] TLB e softuerit IO: e mapuar [mem 0xbb1fc000-0xbf1fc000] (64MB)(BBL shfaq emblemën, dhe ajo që ka etiketat e kohës - është bërthama).
Fatmirësisht, nuk e di si është kudo, por në RocketChip me lidhjen e debaguerit përmes JTAG, mund të kapen grushtat nga kutia - debagueri do të ndalet pikërisht në këtë pikë.
Programi mori sinjal SIGTRAP, Grushtimi / grushtimi.
0xffffffe0000024ca në ?? ()
(gdb) bt
#0 0xffffffe0000024ca në ?? ()
Grushtimi i prapambetur u ndal: çelësi i mëparshëm është identik me këtë çelës (stack i korruptuar?)
(gdb) skeda punë/linux/vmlinux
Një program është duke u debaguar tashmë.
Jeni të sigurt se doni të ndryshoni skedari? (y ose n) y
Duke lexuar simbolet nga punë/linux/vmlinux... tamam.
(gdb) bt
#0 0xffffffe0000024ca në setup_smp () në /hdd/trosinenko/fpga/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:75
#1 0x0000000000000000 në ?? ()
Grushtimi i prapambetur u ndal: çelësi nuk e ruajti PC-në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); // < JENI JENI KET | ĐĐ ĐĐĐĐ ĐŹĐąĐ, ЧйРĐйРРĐĐĐ
}Si thoshte një anekdotë e vjetër, CPU nuk u gjet, duke punuar me emulim softueri. Apo jo duke punuar. U Humbën në një bërthamë të vetme të procesorit.
/* The lucky hart to first increment this variable will boot the other cores */
atomic_t hart_lottery;
unsigned long boot_cpu_hartid;NjĂ« koment i mirĂ« nĂ« linux/arch/riscv/kernel/setup.c â njĂ« lloj ngjyrosjeje me metodĂ«n e Tom Sawyer. NĂ« pĂ«rgjithĂ«si, sot nuk u gjetĂ«n fitues, çmimi kalon pĂ«r edicionin e ardhshĂ«m...
Në këtë pikë, propozoj të mbyllim artikullin e zgjatur.
Vazhdimi pason. Në të do të ketë një përballje me një gabim të mençur, i cili arrin të fshihet nëse i afrohemi ngadalë nëpërmjet singlestep.
Screencast i ngarkesës (link i jashtëm):
Burimi: habr.com
