பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது В முந்தைய பகுதி அதிகமாகவோ அல்லது குறைவாகவோ செயல்படும் மெமரி கன்ட்ரோலர் செயல்படுத்தப்பட்டது அல்லது குவார்டஸிலிருந்து ஐபி கோர் மீது ஒரு ரேப்பர், இது டைல்லிங்கிற்கான அடாப்டராகும். இன்று, "நாங்கள் ராக்கெட்ஷிப்பை சைக்ளோனுடன் அதிகம் அறியப்படாத சீனப் பலகைக்கு போர்ட் செய்கிறோம்" என்ற பிரிவில் நீங்கள் ஒரு வேலை செய்யும் கன்சோலைக் காண்பீர்கள். செயல்முறை சிறிது நேரம் எடுத்தது: நான் லினக்ஸை விரைவாகத் தொடங்குவேன் என்று ஏற்கனவே நினைத்தேன், ஆனால் அது அப்படி இல்லை. இந்த பகுதியில், U-Boot, BBL மற்றும் லினக்ஸ் கர்னலை துவக்குவதற்கான பயமுறுத்தும் முயற்சிகளை தொடங்கும் செயல்முறையை பார்க்க நான் முன்மொழிகிறேன். ஆனால் ஒரு கன்சோல் உள்ளது - U-Boot, மற்றும் மிகவும் மேம்பட்டது, முழு அளவிலான கன்சோலில் இருந்து நீங்கள் எதிர்பார்ப்பதில் அதிகம் உள்ளது.

வன்பொருளில் SPI இடைமுகம் வழியாக இணைக்கப்பட்ட SD கார்டு மற்றும் UART ஆகியவை அடங்கும். மென்பொருள் பகுதியில், BootROM மாற்றப்படும் xip மீது sdboot மற்றும், உண்மையில், பின்வரும் ஏற்றுதல் நிலைகள் சேர்க்கப்பட்டுள்ளன (SD கார்டில்).

வன்பொருளை முடித்தல்

எனவே, பணி: நீங்கள் ஒரு “பெரிய” மையத்திற்கு மாறி UART (ராஸ்பெர்ரியிலிருந்து) மற்றும் ஒரு SD அடாப்டரை இணைக்க வேண்டும் (நாங்கள் ஆறு ஊசிகளைக் கொண்ட கேடலெக்ஸிலிருந்து ஒரு அட்டையைப் பயன்படுத்தினோம்: GND, VCC, MISO, MOSI, SCK, CS) .

கொள்கையளவில், எல்லாம் மிகவும் எளிமையானது. ஆனால் இதை நான் புரிந்துகொள்வதற்கு முன்பு, நான் பக்கத்திலிருந்து பக்கமாக சிறிது தூக்கி எறியப்பட்டேன்: முந்தைய நேரத்திற்குப் பிறகு, நான் மீண்டும் கலக்க வேண்டும் என்று முடிவு செய்தேன். System போன்ற ஏதாவது HasPeripheryUART (மற்றும் அதற்கேற்ப செயல்படுத்துதல்), SD கார்டுக்கு அதே - மற்றும் எல்லாம் தயாராக இருக்கும். பின்னர் அது ஒரு "தீவிர" வடிவமைப்பில் எவ்வாறு செயல்படுத்தப்பட்டது என்பதைப் பார்க்க முடிவு செய்தேன். எனவே, இதில் என்ன தீவிரம்? ஆர்ட்டி, வெளிப்படையாக, பொருந்தவில்லை - அசுரன் உள்ளது unleahshed.DevKitConfigs. திடீரென்று எல்லா இடங்களிலும் சில மேலடுக்குகள் இருந்தன, அவை விசைகள் மூலம் அளவுருக்கள் மூலம் சேர்க்கப்பட்டன. இது அநேகமாக மிகவும் நெகிழ்வானதாகவும், கட்டமைக்கக்கூடியதாகவும் இருக்கும் என்று நான் நினைக்கிறேன், ஆனால் முதலில் ஏதாவது ஒன்றை இயக்க விரும்புகிறேன்... உங்களிடம் அதே விஷயம் இல்லையா, எளிமையானது மற்றும் எரிச்சலூட்டும் விஷயம்? அப்போதுதான் நான் கண்ணில் பட்டேன் vera.iofpga.FPGAChip மைக்ரோசெமி எஃப்பிஜிஏக்களுக்காக, உடனடியாக மேற்கோள்களுக்காக அதைத் தவிர்த்து, ஒப்புமை மூலம் எனது சொந்த செயலாக்கத்தை உருவாக்க முயற்சித்தேன், அதிர்ஷ்டவசமாக ஒரே கோப்பில் முழு “மதர்போர்டு தளவமைப்பு” அதிகமாகவோ அல்லது குறைவாகவோ உள்ளது.

நீங்கள் உண்மையில் சேர்க்க வேண்டும் என்று மாறியது System.scala வரி

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

வகுப்பு உடலில் கோடு System எங்கள் SoC இன் இந்த பகுதி dts கோப்பில் செயல்படும் அதிர்வெண் பற்றிய தகவலைச் சேர்க்கிறது. நான் புரிந்து கொண்ட வரையில், டிடிஎஸ்/டிடிபி என்பது உட்பொதிக்கப்பட்ட சாதனங்களுக்கான பிளக் அண்ட்-ப்ளே தொழில்நுட்பத்தின் நிலையான அனலாக் ஆகும்: டிடிஎஸ் விளக்க மரமானது பைனரி டிடிபி கோப்பாக தொகுக்கப்பட்டு, பூட்லோடரால் கர்னலுக்கு மாற்றப்படும், இதனால் அதை சரியாக உள்ளமைக்க முடியும். வன்பொருள். சுவாரஸ்யமாக, வரி இல்லாமல் tlclock எல்லாம் சரியாக ஒருங்கிணைக்கிறது, ஆனால் BootROM ஐ தொகுக்கிறது (நான் உங்களுக்கு நினைவூட்டுகிறேன், இப்போது இது ஏற்கனவே இருக்கும் sdboot) வேலை செய்யாது - தொகுத்தல் செயல்பாட்டின் போது அது dts கோப்பை பாகுபடுத்தி மேக்ரோவுடன் ஒரு தலைப்பை உருவாக்குகிறது TL_CLK, வெளிப்புற இடைமுகங்களுக்கான அதிர்வெண் வகுப்பிகளை அவர் சரியாக உள்ளமைக்க முடியும்.

நீங்கள் "வயரிங்" ஐ சிறிது சரிசெய்ய வேண்டும்:

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
}

பதிவுச் சங்கிலிகள், நேர்மையாகச் சொல்வதானால், அசல் குறியீட்டில் உள்ள வேறு சில இடங்களுடன் ஒப்பிடுவதன் மூலம் எளிமையாகச் சேர்க்கப்பட்டன. பெரும்பாலும், அவர்கள் எதிராக பாதுகாக்க வேண்டும் மெட்டாஸ்டபிலிட்டி. ஒருவேளை உள்ளே некоторых தொகுதிகள் ஏற்கனவே அவற்றின் சொந்த பாதுகாப்பைக் கொண்டுள்ளன, ஆனால் முதலில் நான் அதை குறைந்தபட்சம் "உயர்தர மட்டத்தில்" தொடங்க விரும்புகிறேன். MISO மற்றும் MOSI ஏன் வித்தியாசமாகத் தொங்குகின்றன என்பது எனக்கு மிகவும் சுவாரஸ்யமான கேள்வி dq? நான் இன்னும் பதிலைக் கண்டுபிடிக்கவில்லை, ஆனால் மீதமுள்ள குறியீடு அத்தகைய இணைப்பை மட்டுமே நம்பியுள்ளது.

உடல் ரீதியாக, நான் பிளாக்கில் உள்ள இலவச தொடர்புகளுக்கு வடிவமைப்பு ஊசிகளை ஒதுக்கினேன் மற்றும் மின்னழுத்த தேர்வு ஜம்பரை 3.3V க்கு நகர்த்தினேன்.

SD அடாப்டர்

மேலே இருந்து பார்க்க:

பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

கீழ் பார்வை:

பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

மென்பொருள் பிழைத்திருத்தம்: கருவிகள்

முதலில், கிடைக்கக்கூடிய பிழைத்திருத்த கருவிகள் மற்றும் அவற்றின் வரம்புகளைப் பற்றி பேசலாம்.

மினிகாம்

முதலில், பூட்லோடர் மற்றும் கர்னல் வெளியீடு என்ன என்பதை எப்படியாவது படிக்க வேண்டும். லினக்ஸில் இதைச் செய்ய (இந்த விஷயத்தில், RaspberryPi இல்), எங்களுக்கு Minicom நிரல் தேவை. பொதுவாக, சீரியல் போர்ட்டுடன் வேலை செய்யும் எந்த நிரலும் செயல்படும்.

தொடங்கும் போது, ​​போர்ட் சாதனத்தின் பெயர் இவ்வாறு குறிப்பிடப்பட வேண்டும் என்பதை நினைவில் கொள்ளவும் -D /dev/ttyS0 - விருப்பத்திற்குப் பிறகு -D. சரி, முக்கிய தகவல்: வெளியேற, பயன்படுத்த Ctrl-A, X. இந்த கலவை வேலை செய்யாதபோது எனக்கு உண்மையில் ஒரு வழக்கு இருந்தது - நீங்கள் அண்டை SSH அமர்விலிருந்து வெறுமனே சொல்லலாம் killall -KILL minicom.

இன்னும் ஒரு அம்சம் உள்ளது. குறிப்பாக, RaspberryPi இரண்டு UARTகளைக் கொண்டுள்ளது, மேலும் இரண்டு போர்ட்களும் ஏற்கனவே ஏதாவது ஒன்றை மாற்றியமைக்கப்படலாம்: ஒன்று புளூடூத்துக்கு, மற்றொன்று முன்னிருப்பாக கர்னல் கன்சோலை வெளியிடுகிறது. அதிர்ஷ்டவசமாக, இந்த நடத்தை மேலெழுதப்படலாம் இந்த கையேட்டின் படி.

நினைவகத்தை மீண்டும் எழுதுதல்

பிழைத்திருத்தம் செய்யும் போது, ​​ஒரு கருதுகோளைச் சோதிக்க, நான் சில நேரங்களில் செய்ய வேண்டியிருந்தது ஏற்ற ஏற்றி (மன்னிக்கவும்) ஹோஸ்டிலிருந்து நேரடியாக RAM இல். ஒருவேளை இது GDB இலிருந்து நேரடியாகச் செய்யப்படலாம், ஆனால் இறுதியில் நான் ஒரு எளிய வழியைப் பின்பற்றினேன்: நான் தேவையான கோப்பை ராஸ்பெர்ரிக்கு நகலெடுத்தேன், SSH வழியாக போர்ட் 4444 ஐ அனுப்பினேன் (OpenOCD இலிருந்து telnet) மற்றும் கட்டளையைப் பயன்படுத்தினேன் load_image. நீங்கள் அதைச் செய்யும்போது, ​​​​எல்லாம் உறைந்திருப்பது போல் தெரிகிறது, ஆனால் உண்மையில் "அது தூங்கவில்லை, அது மெதுவாக கண் சிமிட்டுகிறது": இது கோப்பைப் பதிவிறக்குகிறது, அது வினாடிக்கு இரண்டு கிலோபைட் வேகத்தில் செய்கிறது.

இடைவெளிகளை நிறுவும் அம்சங்கள்

வழக்கமான நிரல்களை பிழைத்திருத்தம் செய்யும் போது பலர் இதைப் பற்றி சிந்திக்க வேண்டியதில்லை, ஆனால் பிரேக் பாயிண்ட்கள் எப்போதும் வன்பொருளில் அமைக்கப்படுவதில்லை. சில சமயங்களில் பிரேக் பாயின்ட் அமைப்பது என்பது தற்காலிகமாக சரியான இடத்தில் சிறப்பு வழிமுறைகளை எழுதுவதை உள்ளடக்குகிறது நேரடியாக இயந்திரக் குறியீட்டில். எடுத்துக்காட்டாக, எனது நிலையான கட்டளை இப்படித்தான் செயல்படுகிறது b GDB இல். பின்வருபவை இங்கே:

  • ROM என்பதால் BootROM க்குள் ஒரு புள்ளியை வைக்க முடியாது
  • SD கார்டில் இருந்து RAM இல் ஏற்றப்பட்ட குறியீட்டில் பிரேக் பாயிண்ட்டை அமைக்கலாம், ஆனால் அது ஏற்றப்படும் வரை நீங்கள் காத்திருக்க வேண்டும். இல்லையெனில், நாங்கள் குறியீட்டின் ஒரு பகுதியை மீண்டும் எழுத மாட்டோம், ஆனால் ஏற்றி எங்கள் பிரேக் பாயின்ட்டை மீண்டும் எழுதும்

ஹார்டுவேர் பிரேக் பாயின்ட்களைப் பயன்படுத்த நீங்கள் வெளிப்படையாகக் கேட்கலாம் என்று நான் நம்புகிறேன், ஆனால் அவை எப்படியும் குறைந்த எண்ணிக்கையில் உள்ளன.

விரைவான BootROM மாற்றீடு

பிழைத்திருத்தத்தின் ஆரம்ப கட்டத்தில், பெரும்பாலும் BootROM ஐ சரிசெய்து மீண்டும் முயற்சிக்க ஆசை உள்ளது. ஆனால் ஒரு சிக்கல் உள்ளது: BootROM என்பது FPGA இல் ஏற்றப்பட்ட வடிவமைப்பின் ஒரு பகுதியாகும், மேலும் அதன் தொகுப்பு சில நிமிடங்கள் ஆகும் (இது C மற்றும் Assembler இலிருந்து BootROM படத்தை உடனடியாக தொகுத்த பிறகு...). அதிர்ஷ்டவசமாக, உண்மையில் எல்லாம் மிக வேகமாக: செயல்களின் வரிசை பின்வருமாறு:

  • bootrom.mif ஐ மீண்டும் உருவாக்கு (நான் HEX க்கு பதிலாக MIF க்கு மாறினேன், ஏனெனில் எனக்கு எப்போதும் HEX இல் சில சிக்கல்கள் இருந்தன, மேலும் MIF என்பது Alter இன் சொந்த வடிவம்)
  • குவார்டஸில் கூறுகின்றனர் Processing -> Update Memory Initialization File
  • அசெம்பிளர் உருப்படியில் (பணிகளின் இடது நெடுவரிசையில்) கட்டளையை மீண்டும் தொடங்கவும்

எல்லாவற்றையும் பற்றி எல்லாம் - இரண்டு பத்து வினாடிகள்.

SD கார்டைத் தயாரிக்கிறது

இங்கே எல்லாம் ஒப்பீட்டளவில் எளிமையானது, ஆனால் நீங்கள் பொறுமையாக இருக்க வேண்டும் மற்றும் 14Gb வட்டு இடத்தை வைத்திருக்க வேண்டும்:

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

அதன் பிறகு, நீங்கள் ஒரு சுத்தமான, அல்லது அதற்கு பதிலாக, தேவையான எதுவும் இல்லாத ஒன்றைச் செருக வேண்டும், SD கார்டைச் செருகவும்.

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

… எங்கே sdX - அட்டைக்கு ஒதுக்கப்பட்ட சாதனம். கவனம்: அட்டையில் உள்ள தரவு நீக்கப்படும், மேலெழுதப்படும் மற்றும் பொதுவாக! முழு சட்டசபையையும் கீழே இருந்து செய்வது மதிப்புக்குரியது அல்ல sudoஏனெனில் அனைத்து கட்டிட கலைப்பொருட்களும் சொந்தமாக இருக்கும் root, மற்றும் சட்டசபை கீழே இருந்து செய்யப்பட வேண்டும் sudo தொடர்ந்து.

இதன் விளைவாக நான்கு பகிர்வுகளுடன் GPT இல் குறிக்கப்பட்ட ஒரு அட்டை உள்ளது, அவற்றில் ஒன்று FAT உடன் உள்ளது uEnv.txt மற்றும் FIT வடிவத்தில் ஒரு துவக்கக்கூடிய படம் (அதில் பல துணை படங்கள் உள்ளன, ஒவ்வொன்றும் அதன் சொந்த பதிவிறக்க முகவரி), மற்ற பகிர்வு காலியாக உள்ளது, இது Linux க்காக Ext4 இல் வடிவமைக்கப்பட வேண்டும். இன்னும் இரண்டு பிரிவுகள் - மர்மமான: U-Boot ஒன்றில் வாழ்கிறது (அதன் ஆஃப்செட், நான் புரிந்து கொண்டவரை, BootROM இல் ஹார்ட்கோட் செய்யப்பட்டுள்ளது), மறுபுறம், அதன் சூழல் மாறிகள் வாழ்கின்றன, ஆனால் நான் அவற்றை இன்னும் பயன்படுத்தவில்லை.

நிலை ஒன்று, BootROM

பிரபலமான ஞானம் கூறுகிறது: "நிரலாக்கத்தில் ஒரு டம்பூருடன் நடனமாடுகிறது என்றால், மின்னணுவியலில் தீயை அணைக்கும் கருவியுடன் நடனமாடுவதும் உள்ளது." ஒருமுறை நான் பலகையை கிட்டத்தட்ட எரித்தேன், "சரி, GND அதே குறைந்த நிலை" என்று முடிவு செய்தேன். (வெளிப்படையாக, ஒரு மின்தடையம் வலிக்காது...) கைகள் அங்கிருந்து வளரவில்லை என்றால், எலக்ட்ரானிக்ஸ் ஒருபோதும் ஆச்சரியத்தைத் தருவதை நிறுத்தாது: இணைப்பியை பலகையில் சாலிடரிங் செய்யும் போது, ​​​​தொடர்புகளை சரியாக சாலிடர் செய்ய முடியவில்லை - சாலிடர் எவ்வாறு நேரடியாக பரவுகிறது என்பதை வீடியோ காட்டுகிறது. முழு இணைப்பிலும், ஒரு சாலிடரிங் இரும்பைப் பயன்படுத்துங்கள், என்னைப் பொறுத்தவரை, அவர் சீரற்ற முறையில் "அடித்தார்". சரி, சாலிடரிங் இரும்பின் வெப்பநிலைக்கு சாலிடர் பொருத்தமானதாக இல்லை, ஒருவேளை வேறு ஏதாவது இருக்கலாம் ... பொதுவாக, நான் ஏற்கனவே ஒரு டஜன் தொடர்புகளைக் கொண்டிருப்பதைப் பார்த்தபோது, ​​நான் கைவிட்டு, பிழைத்திருத்தத்தை ஆரம்பித்தேன். பின்னர் அது தொடங்கியது மர்மமான: நான் UART இலிருந்து RX/TX ஐ இணைத்தேன், ஃபார்ம்வேரை ஏற்றுகிறேன் - அது கூறுகிறது

INIT
CMD0
ERROR

சரி, எல்லாம் தர்க்கரீதியானது - நான் SD கார்டு தொகுதியை இணைக்கவில்லை. நாங்கள் நிலைமையை சரிசெய்கிறோம், ஃபார்ம்வேரை ஏற்றுகிறோம் ... மற்றும் அமைதி ... நான் ஏன் என் மனதை மாற்றவில்லை, ஆனால் சிறிய பெட்டி திறக்கப்பட்டது: தொகுதி ஊசிகளில் ஒன்று VCC உடன் இணைக்கப்பட வேண்டும். என் விஷயத்தில், தொகுதி மின்சாரம் வழங்குவதற்கு 5V ஐ ஆதரிக்கிறது, எனவே இருமுறை யோசிக்காமல், தொகுதியிலிருந்து வரும் கம்பியை போர்டின் எதிர் பக்கத்தில் செருகினேன். இதன் விளைவாக, வளைந்த சாலிடர் இணைப்பு வளைந்துவிட்டது, மற்றும் UART தொடர்பு வெறுமனே துண்டிக்கப்பட்டது. facepalm.jpg பொதுவாக, "கெட்ட தலை கால்களுக்கு ஓய்வு கொடுக்காது" மற்றும் வளைந்த கைகள் தலைக்கு ஓய்வு கொடுக்காது.

இதன் விளைவாக, நான் நீண்டகாலமாக எதிர்பார்க்கப்பட்டதைப் பார்த்தேன்

INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /

மேலும், அது நகரும் மற்றும் ஏற்றுதல் காட்டி சுழலும். எனது பள்ளி நாட்களும், நெகிழ் வட்டில் இருந்து MinuetOSஐ நிதானமாக ஏற்றியதும் எனக்கு உடனடியாக ஞாபகம் வந்தது. ஓட்டு அரைக்கவில்லை என்றால்.

பிரச்சனை என்னவென்றால், BOOT செய்திக்குப் பிறகு எதுவும் நடக்காது. ஓபன்ஓசிடி வழியாக ராஸ்பெர்ரிக்கும், ஹோஸ்டில் உள்ள ஜிடிபிக்கும், அது என்னவென்று பார்க்க வேண்டிய நேரம் இது.

முதலாவதாக, GDB ஐப் பயன்படுத்தி இணைப்பது உடனடியாகக் காட்டியது $pc (நிரல் கவுண்டர், தற்போதைய அறிவுறுத்தலின் முகவரி) க்கு பறக்கிறது 0x0 - இது பல பிழைகளுக்குப் பிறகு நடக்கும். எனவே, செய்தி வெளியிடப்பட்ட உடனேயே BOOT எல்லையற்ற வளையத்தைச் சேர்ப்போம். இது அவரை சிறிது நேரம் தாமதப்படுத்தும் ...

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

இத்தகைய தந்திரமான குறியீடு "நம்பகத்தன்மைக்காக" பயன்படுத்தப்படுகிறது: முடிவில்லாத சுழற்சி ஒரு வரையறுக்கப்படாத நடத்தை என்று நான் எங்கோ கேள்விப்பட்டேன், ஆனால் கம்பைலர் யூகிக்க வாய்ப்பில்லை (படி நான் உங்களுக்கு நினைவூட்டுகிறேன் 0x10000 BootROM அமைந்துள்ளது).

பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

வேறு என்ன எதிர்பார்க்க வேண்டும் என்று தோன்றுகிறது - கடுமையான உட்பொதிக்கப்பட்டவை, எந்த வகையான மூல குறியீடுகள் உள்ளன? ஆனால் உள்ளே அந்த கட்டுரை ஆசிரியர் 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.

பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

நீங்கள் MIF கோப்பு அல்லது தொட்டியை பதிவிறக்கம் செய்ய வேண்டும், ஆனால் அசல் பதிப்பை ELF வடிவத்தில் பதிவிறக்க வேண்டும்.

செயல்படுத்தல் தொடரும் முகவரியை இப்போது நீங்கள் nவது முயற்சியில் யூகிக்க முடியும் (லூப் எல்லையற்றது என்று கம்பைலர் யூகிக்காமல் இருப்பதற்கு இது மற்றொரு காரணம்). குழு

set variable $pc=0xADDR

பறக்கும்போது பதிவு மதிப்பை மாற்ற உங்களை அனுமதிக்கிறது (இந்த வழக்கில், தற்போதைய அறிவுறுத்தலின் முகவரி). அதன் உதவியுடன், நீங்கள் நினைவகத்தில் எழுதப்பட்ட மதிப்புகளை மாற்றலாம் (மற்றும் நினைவக-வரைபட பதிவுகள்).

இறுதியில், எங்களிடம் "தவறான அமைப்பின் SD கார்டு படம்" உள்ளது என்ற முடிவுக்கு வந்தேன் (எது சரியானது என்று தெரியவில்லை), மேலும் நாம் பதிவிறக்கம் செய்யப்பட்ட தரவின் ஆரம்பத்திற்கு செல்ல வேண்டியதில்லை, ஆனால் 0x89800 மேலும் பைட்டுகள்:

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

கையில் தேவையில்லாத 4ஜிபி கார்டு இல்லாததால், 2ஜிபி ஒன்றை எடுத்து மேக்ஃபைலில் சீரற்ற முறையில் மாற்றியதால் இதுவும் பாதிக்கப்பட்டிருக்கலாம். DEMO_END=11718750 மீது DEMO_END=3078900 (ஒரு குறிப்பிட்ட அர்த்தத்தில் அர்த்தத்தைத் தேட வேண்டாம் - எதுவும் இல்லை, இப்போது படம் அட்டையில் வைக்கப்பட்டுள்ளது).

நிலை இரண்டு, U-Boot

இப்போது நாம் இன்னும் "விழுகிறோம்", ஆனால் நாங்கள் ஏற்கனவே சரியான இடத்தில் இருக்கிறோம் 0x0000000080089a84. இங்கே நான் ஒப்புக்கொள்ள வேண்டும்: உண்மையில், விளக்கக்காட்சி "அனைத்து நிறுத்தங்களுடனும்" செல்லாது, ஆனால் "பின்னர்" ஓரளவு எழுதப்பட்டுள்ளது, எனவே இங்கே நான் ஏற்கனவே எங்கள் SoC இலிருந்து சரியான dtb கோப்பைச் செருக முடிந்தது, அதை அமைப்புகளில் சரிசெய்யவும். HiFive_U-Boot மாறி CONFIG_SYS_TEXT_BASE=0x80089800 (அதற்கு பதிலாக 0x08000000) அதனால் பதிவிறக்க முகவரி உண்மையான முகவரியுடன் பொருந்துகிறது. இப்போது அடுத்த கட்டத்தின் வரைபடத்தை ஏற்றுகிறோம், மற்றொரு படம்:

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

மற்றும் நாம் பார்க்கிறோம்:

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

மேலும், நாம் வரிகள் 308 மற்றும் 309 இடையே குதிக்கிறோம். மேலும், இதில் ஆச்சரியப்படுவதற்கில்லை. $sp பொருள் பொய் 0xfffffffe31cdc0a0. ஐயோ, இது 307 வது வரியின் காரணமாக தொடர்ந்து "ஓடிவிடும்". எனவே, ஒரு இடைவெளியை அமைக்க முயற்சிப்போம். trap_entry, பின்னர் மீண்டும் செல்லவும் 0x80089800 (U-Boot இன் நுழைவுப் புள்ளி), மேலும் குதிக்கும் முன் பதிவேடுகளை சரியாக அமைக்க வேண்டிய அவசியமில்லை என்று நம்புவோம்... இது வேலை செய்கிறது போல் தெரிகிறது:

(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

ஸ்டாக் பாயிண்டர் மிகவும் வெளிப்படையாகச் சொன்னால்: இது ரேமை முழுவதுமாகப் புறக்கணிப்பதைச் சுட்டிக்காட்டுகிறது (நிச்சயமாக, எங்களிடம் ஏற்கனவே முகவரி மொழிபெயர்ப்பு இல்லை, ஆனால் ஒரு எளிய விருப்பத்தை நம்புவோம்).

சுட்டியை மாற்ற முயற்சிப்போம் 0x881cf950. இதன் விளைவாக, நாங்கள் ஒரு முடிவுக்கு வருகிறோம் handle_trap அழைக்கப்பட்டது மற்றும் அழைத்தது, அதே நேரத்தில் நாங்கள் உள்ளே செல்கிறோம் _exit_trap ஒரு வாதத்துடன் epc=2148315240 (தசமத்தில்):

(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

பிரேக் பாயிண்ட்டை அமைக்கவும் strnlen, நாங்கள் தொடர்கிறோம் மற்றும் பார்க்கிறோம்:

(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

என்று தெரிகிறது, _exit_trap ஏற்பட்ட விதிவிலக்கு பற்றிய பிழைத்திருத்தத் தகவலை வழங்க விரும்புகிறது, ஆனால் அவனால் முடியாது. எனவே, எப்படியோ எங்கள் ஆதாரங்கள் மீண்டும் காட்டப்படவில்லை. set directories ../freedom-u-sdk/HiFive_U-Boot/ பற்றி! இப்போது காட்டப்பட்டுள்ளது!

சரி, அதை மீண்டும் இயக்குவோம், முதல் பிழையை ஏற்படுத்திய அசல் சிக்கலின் காரணத்தை அடுக்கிலிருந்து பார்க்கலாம் (mcause == 5) நான் எழுதியதை சரியாகப் புரிந்து கொண்டால் இங்கே பக்கம் 37 இல், இந்த விதிவிலக்கு அர்த்தம் Load access fault. காரணம் இங்கே தெரிகிறது

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 அதே தவறான அர்த்தம் மற்றும் உள்ளே உள்ளது board_init_f_init_reserve ஒரு பிழை ஏற்படுகிறது. இது குற்றவாளி போல் தெரிகிறது: தெளிவற்ற பெயரைக் கொண்ட மாறி CONFIG_SYS_INIT_SP_ADDR. இது கோப்பில் வரையறுக்கப்பட்டுள்ளது HiFive_U-Boot/include/configs/HiFive-U540.h. ஒரு கட்டத்தில் நான் கூட நினைத்தேன், ஒருவேளை, நான் செயலிக்கு ஒரு துவக்க ஏற்றி சேர்க்க வேண்டும் - ஒருவேளை செயலியை சிறிது சரிசெய்வது எளிதாக இருக்கும்? ஆனால் அது முழுமையாக முடிக்கப்படாத ஒரு கலைப்பொருளாக இருந்ததை நான் பார்த்தேன்#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 */

ஒரு கட்டத்தில் ஊன்றுகோல் எண்ணிக்கை தொழில்நுட்ப ஃபாஸ்டென்சர்கள் ஒரு முக்கியமான கட்டத்தை எட்டியுள்ளது. கொஞ்சம் சிரமப்பட்டு, என் போர்டை சரியான போர்ட் செய்ய வேண்டிய அவசியம் வந்தது. இதைச் செய்ய, நமது உள்ளமைவுக்கு ஏற்றவாறு பல கோப்புகளை நகலெடுத்து சரிசெய்ய வேண்டும்.

சரி, தோராயமாக, இங்கே ஒரு சிறிய அட்டவணை

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

விவரங்களைக் காணலாம் களஞ்சியங்கள்.

அது முடிந்தவுடன், இந்த SiFive போர்டில் சில சாதனங்களின் பதிவேடுகள் வெவ்வேறு முகவரிகளைக் கொண்டுள்ளன. U-Boot ஆனது Kconfig பொறிமுறையைப் பயன்படுத்தி கட்டமைக்கப்பட்டுள்ளது, இது ஏற்கனவே லினக்ஸ் கர்னலில் இருந்து நன்கு அறியப்பட்டதாகும் - எடுத்துக்காட்டாக, நீங்கள் கட்டளையிடலாம் make menuconfig, மற்றும் அளவுருக்களின் விளக்கங்களைக் காட்டும் வசதியான உரை இடைமுகம் உங்கள் முன் தோன்றும் ? முதலியன பொதுவாக, இரண்டு பலகைகளின் விளக்கங்களிலிருந்து மூன்றாவதாக ஒரு விளக்கத்தை ஒன்றாக இணைத்து, எல்லாவிதமான பாசாங்குத்தனமான PLL மறுகட்டமைவுகளையும் அங்கிருந்து தூக்கி எறிந்துவிட்டு (வெளிப்படையாக, இது எப்படியாவது ஹோஸ்ட் கணினியிலிருந்து PCIe வழியாக கட்டுப்பாட்டுடன் இணைக்கப்பட்டுள்ளது, ஆனால் இது உறுதியாகத் தெரியவில்லை) , நான் சில ஃபார்ம்வேரைப் பெற்றேன், செவ்வாய் கிரகத்தில் சரியான வானிலையில் இது எந்த கமிட் ஹாஷ் தொகுக்கப்பட்டது மற்றும் என்னிடம் எவ்வளவு DRAM உள்ளது என்பது பற்றிய செய்தியை UART மூலம் எனக்கு அனுப்பியது (ஆனால் இந்த தகவலை நானே தலைப்பில் எழுதியுள்ளேன்).

ஒரே பரிதாபம் என்னவென்றால், இதற்குப் பிறகு போர்டு வழக்கமாக JTAG செயலி வழியாக பதிலளிப்பதை நிறுத்தியது, மேலும் SD கார்டில் இருந்து ஏற்றுவது, ஐயோ, எனது உள்ளமைவில் வேகமாக இல்லை. மறுபுறம், சில நேரங்களில் BootROM ஒரு செய்தியைக் கொடுத்தது ERROR, துவக்க முடியவில்லை, U-Boot உடனடியாக பாப்-அப் ஆனது. அப்போதுதான் அது எனக்குப் புரிந்தது: வெளிப்படையாக, பிட்ஸ்ட்ரீமை FPGA இல் மறுதொடக்கம் செய்த பிறகு, நினைவகம் அழிக்கப்படவில்லை, அதற்கு "பயிற்சி பெற" நேரம் இல்லை, முதலியன. சுருக்கமாக, ஒரு செய்தி தோன்றும் போது உங்களால் முடியும் LOADING / பிழைத்திருத்தி மற்றும் கட்டளையுடன் இணைக்கவும் set variable $pc=0x80089800, இதன் மூலம் இந்த நீண்ட ஏற்றுதலைத் தவிர்க்கலாம் (நிச்சயமாக, கடந்த முறை அது அசல் குறியீட்டின் மேல் எதையும் ஏற்றுவதற்கு நேரமில்லாத அளவுக்கு சீக்கிரம் உடைந்து விட்டது என்ற அனுமானத்தில்).

பொதுவாக, செயலி முற்றிலும் உறைந்துவிடும் மற்றும் JTAG பிழைத்திருத்தி அதை செய்திகளுடன் இணைக்க முடியாது என்பது பொதுவாக இயல்பானதா?

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

எனவே, காத்திருங்கள்! இதை நான் ஏற்கனவே பார்த்திருக்கிறேன்! TileLink முட்டுக்கட்டையாக இருக்கும்போது இதேபோன்ற ஒன்று நடக்கும், மேலும் நினைவகக் கட்டுப்படுத்தியின் ஆசிரியரை நான் எப்படியாவது நம்பவில்லை - அதை நானே எழுதினேன் ... திடீரென்று, கட்டுப்படுத்தியைத் திருத்திய பிறகு செயலியின் முதல் வெற்றிகரமான மறுகட்டமைப்பிற்குப் பிறகு, நான் பார்த்தேன்:

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

முன்பு இந்த விசித்திரமான வரிக்கு In: serial கவனம் செலுத்த வேண்டாம் - தொங்கும் செயலி சுற்றுச்சூழலுடன் சரியாகச் செயல்படுகிறதா என்பதைப் புரிந்துகொள்ள முயற்சித்தேன். “பத்து நிமிஷம் இப்படியே தொங்கிக்கிட்டு இருக்கு” ​​என்று என்ன சொல்கிறீர்கள்? குறைந்தபட்சம் அது இடமாற்றம் செய்து துவக்க மெனுவிற்குச் செல்ல முடிந்தது! ஒரு சிறிய விலகல்: U-Boot ஆனது SD கார்டில் இருந்து முதல் 2^24 பைட்டுகளில் ஏற்றப்பட்டாலும், அது தொடங்கும் போது, ​​அது தன்னை ஒரு தொலைதூர முகவரிக்கு நகலெடுக்கிறது, ஒன்று உள்ளமைவு தலைப்பில் எழுதப்பட்டிருக்கும், அல்லது வெறுமனே RAM இன் உயர் முகவரிகளுக்கு. , மற்றும் ELF இடமாற்றம் - பாத்திரங்களைச் செய்கிறது மற்றும் அங்கு கட்டுப்பாட்டை மாற்றுகிறது. எனவே: நாங்கள் இந்த நிலையைத் தாண்டிவிட்டோம், அதன் பிறகு செயலி இறுக்கமாகத் தொங்கவில்லை என்ற போனஸைப் பெற்றோம்.

எனவே டைமர் ஏன் வேலை செய்யவில்லை? சில காரணங்களால் கடிகாரம் வேலை செய்யவில்லை போல் தெரிகிறது...

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

அம்புகளை கைமுறையாக திருப்பினால் என்ன செய்வது?

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

பின்னர்:

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

முடிவு: கடிகாரம் இயங்கவில்லை. விசைப்பலகை உள்ளீடு வேலை செய்யாததற்கு இதுவே காரணமாக இருக்கலாம்:

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

நான் கொஞ்சம் புத்திசாலியாக இருந்ததால் சிக்கல் மாறியது: செயலி கட்டமைப்பில் விசையைச் சேர்த்தேன்:

  case DTSTimebase => BigInt(0)

... கருத்து "உங்களுக்குத் தெரியாவிட்டால், 0 ஐ விட்டு விடுங்கள்" என்று கூறியதன் அடிப்படையில். மற்றும் அனைத்து பிறகு WithNBigCores நான் அதை 1MHz ஆக அமைத்தேன் (அது U-Boot கட்டமைப்பில் குறிப்பிடப்பட்டுள்ளது). ஆனால் அடடா, நான் சுத்தமாகவும் உன்னிப்பாகவும் இருக்கிறேன்: அங்கு எனக்குத் தெரியாது, இதோ 25MHz! இறுதியில், எதுவும் வேலை செய்யாது. நான் எனது "மேம்பாடுகளை" அகற்றி...

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 #

நீங்கள் கட்டளைகளை உள்ளிடலாம்! எடுத்துக்காட்டாக, சிறிது குத்திய பிறகு, நீங்கள் இறுதியாக நுழைவதை யூகிக்க முடியும் mmc_spi 1 10000000 0; mmc part, SPI அதிர்வெண்ணை 20MHz இலிருந்து 10MHz ஆக குறைக்கிறது. ஏன்? சரி, 20MHz இன் அதிகபட்ச அதிர்வெண் கட்டமைப்பில் எழுதப்பட்டது, அது இன்னும் அங்கு எழுதப்பட்டுள்ளது. ஆனால், நான் புரிந்துகொண்டவரை, இடைமுகங்கள், குறைந்தபட்சம் இங்கே, இதுபோல் செயல்படுகின்றன: குறியீடு வன்பொருள் அலகு (என்னுடையது எல்லா இடங்களிலும் 25MHz) அதிர்வெண்ணை இலக்கால் பிரிக்கிறது, மேலும் அதன் விளைவாக வரும் மதிப்பை தொடர்புடைய கட்டுப்பாட்டில் வகுப்பியாக அமைக்கிறது. பதிவு. பிரச்சனை என்னவென்றால், 115200Hz UARTக்கு தோராயமாக என்ன தேவை என்றால், நீங்கள் 25000000 ஐ 20000000 ஆல் வகுத்தால் 1 கிடைக்கும், அதாவது. இது 25MHz இல் வேலை செய்யும். ஒருவேளை இது இயல்பானதாக இருக்கலாம், ஆனால் கட்டுப்பாடுகள் அமைக்கப்பட்டால், யாரோ ஒருவருக்கு இது தேவை என்று அர்த்தம் (ஆனால் இது உறுதியாகத் தெரியவில்லை)... பொதுவாக, அதை அமைத்து நகர்த்துவது எளிது - தொலைவில் மற்றும், ஐயோ, நீண்ட காலமாக. 25MHz ஒரு கோர் i9 அல்ல.

கன்சோல் வெளியீடு

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

சரி, நாங்கள் அடுத்த கட்டத்தை அடைந்துவிட்டோம், ஆனால் அது இன்னும் உறைநிலையில் உள்ளது. மற்றும் சில நேரங்களில் அது விதிவிலக்குகளை தெளிக்கிறது. குறிப்பிட்ட முகவரியில் குறியீட்டிற்காக காத்திருப்பதன் மூலம் mcause ஐப் பார்க்கலாம் $pc மற்றும் பிறகு si அப்படியே இருக்கட்டும் trap_entry. U-Boot கையாளுபவர் mcause = 0..4 க்கு மட்டுமே வெளியிட முடியும், எனவே தவறான துவக்கத்தில் சிக்கிக்கொள்ள தயாராகுங்கள். பின்னர் நான் கட்டமைப்பிற்குள் சென்று, நான் என்ன மாற்றுகிறேன் என்று பார்க்க ஆரம்பித்தேன், நினைவில்: அங்கே conf/rvboot-fit.txt எழுதப்பட்டது:

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

சரி, எல்லா கோப்புகளையும் இணக்கமாக கொண்டு வருவோம், கர்னல் கட்டளை வரியை இதுபோன்ற ஒன்றை மாற்றுவோம், ஏனெனில் சந்தேகங்கள் உள்ளன SIF0 - இது PCIe வழியாக எங்காவது வெளியீடு:

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

ஹாஷிங் அல்காரிதத்தை SHA-256 இலிருந்து MD5 க்கு மாற்றுவோம்: எனக்கு கிரிப்டோகிராஃபிக் வலிமை தேவையில்லை (குறிப்பாக பிழைத்திருத்தம் செய்யும் போது), இது மிகவும் நீண்ட நேரம் எடுக்கும், மேலும் ஏற்றும்போது ஒருமைப்பாடு பிழைகளைப் பிடிக்க, MD5 மிகவும் எளிதானது. இறுதி முடிவு என்ன? முந்தைய நிலை குறிப்பிடத்தக்க வகையில் வேகமாக முடிக்கத் தொடங்கினோம் (எளிமையான ஹாஷிங் காரணமாக), அடுத்தது திறக்கப்பட்டது:

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

ஆனால் கடிகாரம் ஓடவில்லை...

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

அச்சச்சோ, கடிகாரத்தை சரிசெய்வது ஒரு மருந்துப்போலியாக மாறியது போல் தெரிகிறது, ஆனால் அது உதவியது என்று எனக்கு அப்போது தோன்றியது. இல்லை, நிச்சயமாக அது சரி செய்யப்பட வேண்டும், ஆனால் முதலில் அம்புகளை கைமுறையாக திருப்பி என்ன நடக்கிறது என்று பார்ப்போம்:

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.

இதற்கிடையில்…

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

இல்லை, நான் கடிகாரத்தை தானியக்கமாக்கப் போகிறேன் - இல்லையெனில் அவர் டைமரை அளவீடு செய்ய முடிவு செய்வார்!

இதற்கிடையில், தற்போதைய அறிவுறுத்தலின் முகவரி எங்காவது சுட்டிக்காட்டுகிறது

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>

ஏற்றப்பட்ட பெர்க்லி பூட் லோடரின் உள்ளே. தனிப்பட்ட முறையில், இதைப் பற்றி என்னைக் குழப்புவது குறிப்பிடுவதுதான் htif — கர்னலின் இணைக்கப்பட்ட வெளியீட்டிற்குப் பயன்படுத்தப்படும் ஹோஸ்ட் இடைமுகம் (அதாவது, ஹோஸ்ட் ARM உடன் இணைந்து), நான் தனித்தனியாகக் கருதினேன். இருப்பினும், மூலக் குறியீட்டில் இந்த செயல்பாட்டை நீங்கள் கண்டால், எல்லாம் மிகவும் மோசமாக இல்லை என்பதை நீங்கள் காணலாம்:

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

குவெஸ்ட்: கடிகாரத்தைத் தொடங்கவும்

CLINT இல் பதிவேடுகளைத் தேடுவது நம்மை வழிநடத்துகிறது

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

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

இது RTC அல்லது மர்மமான MockAON உடன் இணைக்கிறது, இதைப் பற்றி நான் முதலில் நினைத்தேன்: "அப்படியானால், இங்கே என்ன இருக்கிறது? தெளிவில்லாததா? அணைப்போம்!" அங்கு என்ன வகையான கடிகார மந்திரம் நடக்கிறது என்பது எனக்கு இன்னும் புரியாததால், இந்த தர்க்கத்தை மீண்டும் செயல்படுத்துகிறேன் 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
  }

லினக்ஸ் கர்னலுக்குச் செல்கிறோம்

இங்கே கதை ஏற்கனவே இழுத்துச் செல்லப்பட்டு கொஞ்சம் சலிப்பானதாக மாறிவிட்டது, எனவே நான் அதை மேலிருந்து கீழாக விவரிக்கிறேன்:

இல் FDT இருப்பதை BBL கருதியது 0xF0000000, ஆனால் நான் ஏற்கனவே அதை சரி செய்துவிட்டேன்! சரி, மீண்டும் பார்ப்போம்... கிடைத்தது HiFive_U-Boot/arch/riscv/lib/boot.c, மாற்றப்பட்டது 0x81F00000, U-Boot பூட் கட்டமைப்பில் குறிப்பிடப்பட்டுள்ளது.

பின்னர் BBL நினைவகம் இல்லை என்று புகார் கூறினார். என் பாதை செயல்பாட்டில் இருந்தது mem_prop, என்ன உள்ளே riscv-pk/machine/fdt.c: fdt ram nodeஐ இவ்வாறு குறிக்க வேண்டும் என்பதை அங்கிருந்து அறிந்து கொண்டேன் device_type = "memory" - பின்னர், ஒருவேளை, செயலி ஜெனரேட்டரை சரிசெய்ய வேண்டும், ஆனால் இப்போதைக்கு நான் அதை கைமுறையாக எழுதுகிறேன் - எப்படியிருந்தாலும், நான் இந்த கோப்பை கைமுறையாக மாற்றினேன்.

இப்போது எனக்கு செய்தி கிடைத்தது (வடிவமைக்கப்பட்ட வடிவத்தில் வழங்கப்பட்டது, வண்டி திரும்பும்):

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.

விருப்பங்கள் தேவைக்கேற்ப சுட்டிக்காட்டப்பட்டதாகத் தெரிகிறது riscv,kernel-start и riscv,kernel-end DTB இல், ஆனால் பூஜ்ஜியங்கள் பாகுபடுத்தப்படுகின்றன. பிழைத்திருத்தம் query_chosen BBL ஒரு 32-பிட் முகவரியை அலச முயற்சிக்கிறது, ஆனால் அது ஒரு ஜோடியைக் காட்டுகிறது <0x0 0xADDR>, மற்றும் முதல் மதிப்பு குறைந்த குறிப்பிடத்தக்க பிட்கள் போல் தெரிகிறது. பிரிவில் சேர்க்கப்பட்டது chosen

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

மற்றும் மதிப்புகளின் தலைமுறையை சரிசெய்தது: சேர்க்க வேண்டாம் 0x0 முதல் உறுப்பு.

இந்த 100500 எளிய வழிமுறைகள் பென்குயின் வீழ்ச்சியைப் பார்ப்பதை எளிதாக்கும்:

மறைக்கப்பட்ட உரை

   Verifying Hash Integrity ... md5+ OK
   Loading loadables from 0x90a5a758 to 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
chosen {
        linux,initrd-end = <0x83000000>;
        linux,initrd-start = <0x82000000>;
        riscv,kernel-end = <0x80a00000>;
        riscv,kernel-start = <0x80200000>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
chosen {
        linux,initrd-end = <0x83000000>;
        linux,initrd-start = <0x82000000>;
        riscv,kernel-end = <0x80a00000>;
        riscv,kernel-start = <0x80200000>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000000>;
        bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
        stdout-path = "uart0:38400n8";
};
   Loading Kernel Image ... OK
Booting kernel in
3
2
1
0
## Starting application at 0x80000000 ...
bbl loader

                SIFIVE, INC.

         5555555555555555555555555
        5555                   5555
       5555                     5555
      5555                       5555
     5555       5555555555555555555555
    5555       555555555555555555555555
   5555                             5555
  5555                               5555
 5555                                 5555
5555555555555555555555555555          55555
 55555           555555555           55555
   55555           55555           55555
     55555           5           55555
       55555                   55555
         55555               55555
           55555           55555
             55555       55555
               55555   55555
                 555555555
                   55555
                     5

           SiFive RISC-V Core IP
[    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[    0.000000] Linux version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Wed Jul 3 21:29:21 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] Initial ramdisk at: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] On node 0 totalpages: 261632
[    0.000000]   DMA32 zone: 3577 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 261632 pages, LIFO batch:63
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)

(லோகோ BBL ஆல் காட்டப்படும், மேலும் நேர முத்திரையுடன் கூடியது கர்னலால் காட்டப்படும்).

அதிர்ஷ்டவசமாக, இது எல்லா இடங்களிலும் எப்படி இருக்கிறது என்று எனக்குத் தெரியவில்லை, ஆனால் ராக்கெட்ஷிப்பில், நீங்கள் JTAG வழியாக பிழைத்திருத்தியை இணைக்கும்போது, ​​பெட்டியின் வெளியே பொறிகளைப் பிடிக்கலாம் - பிழைத்திருத்தி இந்த கட்டத்தில் சரியாக நின்றுவிடும்.

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

பழைய ஜோக் சொன்னது போல், CPU கிடைக்கவில்லை, மென்பொருள் எமுலேஷனை இயக்குகிறது. சரி, அல்லது ஓடவில்லை. ஒரு செயலி மையத்தில் தொலைந்தது.

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

நல்ல கருத்து linux/arch/riscv/kernel/setup.c - டாம் சாயர் முறையைப் பயன்படுத்தி வேலியின் ஒரு வகையான ஓவியம். பொதுவாக, சில காரணங்களால் இன்று வெற்றியாளர்கள் இல்லை, பரிசு அடுத்த டிராவிற்கு மாற்றப்படுகிறது ...

ஏற்கனவே நீண்ட கட்டுரையை முடிக்க நான் முன்மொழிகிறேன்.

தொடரும். நீங்கள் மெதுவாக சிங்கிள்ஸ்டெப்பில் ஏறினால் மறைக்க நிர்வகிக்கும் ஒரு தந்திரமான பிழையுடன் சண்டை இருக்கும்.

உரை பதிவிறக்க ஸ்கிரீன்காஸ்ட் (வெளிப்புற இணைப்பு):
பகுதி 3: லினக்ஸை SD கார்டில் இருந்து RocketChip க்கு ஏற்றுகிறது

ஆதாரம்: www.habr.com

கருத்தைச் சேர்