في الجزء السابق ، تم تطبيق وحدة تحكم في الذاكرة تعمل بشكل أو بآخر ، أو بالأحرى ، برنامج التفاف عبر IP Core من Quartus ، وهو محول إلى TileLink. اليوم ، تحت عنوان "نحن ننقل RocketChip إلى لوحة أم صينية غير معروفة مع Cyclone" ، سترى وحدة تحكم تعمل. استمرت العملية قليلاً: اعتقدت بالفعل أنني سأقوم بتشغيل Linux بسرعة والمضي قدماً ، لكن لم يكن هناك. في هذا الجزء ، أقترح إلقاء نظرة على عملية بدء تشغيل تهيئة نواة U-Boot و BBL و Linux kidel. ولكن هناك وحدة تحكم - U-Boot-ovsky ، ومتطورة للغاية ، تحتوي على الكثير مما تتوقعه من وحدة تحكم متكاملة.
في الجهاز ، سيتم إضافة بطاقة SD متصلة عبر SPI ، وكذلك UART. في جزء البرنامج ، سيتم استبدال xip
من xip
إلى sdboot
، وفي الواقع ، ستتم إضافة مراحل التمهيد التالية (على بطاقة SD).
تعاطي المنشطات
المهمة: تحتاج إلى التبديل إلى النواة "الكبيرة" وتوصيل UART (من Raspberry) ومحول SD (تم استخدام نوع من لوحة Catalex بستة دبابيس: GND ، VCC ، MISO ، MOSI ، SCK ، CS).
من حيث المبدأ ، كان كل شيء بسيطًا جدًا. ولكن قبل أن أدرك هذا ، تم إلقاؤي قليلاً من جانب إلى آخر: بعد المرة السابقة ، قررت أنه مرة أخرى تحتاج فقط إلى مزج شيء مثل HasPeripheryUART
في System
(والتنفيذ وفقًا لذلك) ، نفس الشيء بالنسبة لبطاقة SD - وهذا هو كل شيء سوف تكون جاهزة. ثم قررت أن أرى كيف تم تنفيذه في تصميم "جدي". إذن ماذا خرجنا من الجدية؟ آرتي ، على ما يبدو ، لا يصلح - لا يزال الوحش unleahshed.DevKitConfigs
. وفجأة تبين أنه كان هناك في كل مكان نوع من التراكبات التي تمت إضافتها من خلال المعلمات بالمفاتيح. أعتقد أن هذا من المحتمل أن يكون مرنًا للغاية وقابل للتكوين ، لكن يجب أن أبدأ شيئًا في البداية ... ولكن ليس لديك نفس العكازات ، فقط أسهل من العكازات؟ .. ثم صادفت vera.iofpga.FPGAChip
ل FPGAs Microsemi و سحبت على الفور في اقتباسات لقد حاولت تنفيذ عملي عن طريق القياس ، الفائدة هنا هي "تخطيط اللوحة الأم" بأكمله أو أكثر في ملف واحد.
اتضح بالفعل ، أنت فقط بحاجة إلى إضافة خطوط إلى 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
معلومات حول التردد الذي يعمل به هذا الجزء من شركة نفط الجنوب على ملف dts. بقدر ما أفهم ، يعد DTS / DTB بمثابة تناظرية ثابتة لتكنولوجيا التوصيل والتشغيل للأجهزة المدمجة: يتم تجميع شجرة وصف dts في ملف ثنائي dtb ويتم إرسالها بواسطة أداة التحميل إلى kernel حتى يتمكن من تكوين الأجهزة بشكل صحيح. ومن المثير للاهتمام ، أنه بدون خط مع tlclock
يتم تجميع كل شيء تمامًا ، لكنه لن يعمل على ترجمة BootROM (سأذكرك الآن بأنه سيكون sdboot
) - أثناء sdboot
، يقوم بتوزيع ملف dts وإنشاء رأس مع الماكرو TL_CLK
، بفضله يمكنه تكوين فواصل التردد بشكل صحيح واجهات خارجية.
ستحتاج أيضًا إلى إصلاح "الأسلاك" قليلاً:
Platform.scala:
class PlatformIO(implicit val p: Parameters) extends Bundle { ...
تمت إضافة سلاسل التسجيل ، بصراحة ، ببساطة عن طريق القياس مع بعض الأماكن الأخرى في التعليمات البرمجية المصدر. على الأرجح ، يجب أن تحمي ضد النقيلة . ربما تتمتع بعض الكتل بالفعل بحمايتها الخاصة ، لكن أولاً أريد أن أركض على الأقل "على مستوى عالٍ". سؤال أكثر إثارة للاهتمام بالنسبة لي هو لماذا يتعطل MISO و MOSI على dq
مختلفة؟ ما زلت لم أجد الإجابة ، لكن يبدو أن بقية الكود يعتمد على مثل هذا الاتصال.
جسديا ، أنا فقط تعيين استنتاجات التصميم لجهات الاتصال فضفاضة على كتلة وإعادة ترتيبها الطائر اختيار الجهد إلى 3.3V.
محول SDعرض أعلى:

عرض أسفل:

تصحيح جزء البرنامج: الأدوات
أولاً ، دعنا نتحدث عن أدوات تصحيح الأخطاء المتوفرة والقيود الخاصة بها.
Minicom
أولاً ، سنحتاج إلى قراءة ما هو محمل الإقلاع ومخرج kernel بطريقة أو بأخرى. للقيام بذلك ، على نظام Linux (في هذه الحالة ، الموجود على RaspberryPi) ، نحتاج إلى برنامج Minicom. بشكل عام ، أي برنامج للعمل مع منفذ تسلسلي مناسب.
لاحظ أنه عند بدء التشغيل ، يجب تحديد اسم جهاز المنفذ كـ -D /dev/ttyS0
- بعد الخيار -D
. حسنًا ، المعلومات الرئيسية: للخروج ، استخدم Ctrl-A, X
كان لدي حقًا حالة لم ينجح فيها هذا المزيج - ثم يمكنك ببساطة القول killall -KILL minicom
من جلسة SSH المجاورة.
هناك ميزة أخرى. على وجه التحديد ، هناك نوعان من UARTs على RaspberryPi ، ويمكن بالفعل تكييف كلا المنفذين لشيء ما: واحد للبلوتوث ، من خلال الآخر ، يتم عرض وحدة التحكم kernel بشكل افتراضي. لحسن الحظ ، يمكن إعادة تكوين هذا السلوك وفقًا لهذا الدليل .
إعادة كتابة الذاكرة
عند تصحيح الأخطاء ، لاختبار الفرضية ، كان علي أحيانًا تحميل أداة تحميل التشغيل (آسف) في ذاكرة الوصول العشوائي مباشرةً من المضيف. ربما يمكن القيام بذلك مباشرة من GDB ، لكن في النهاية ذهبت بالطريقة البسيطة: قمت بنسخ الملف الضروري إلى Raspberry ، كما أرسل المنفذ 4444 (telnet من OpenOCD) عبر SSH واستخدم الأمر load_image
. عند تنفيذه ، يبدو أن كل شيء مُجمد ، لكن في الواقع "لا ينام ، بل يومض ببطء" : يتم تحميل الملف ، بل يتم تنفيذه بسرعة بضع كيلوبايت في الثانية.
ميزات تثبيت نقاط التوقف
ربما ، لم يكن على الكثير منهم التفكير في هذا الأمر عند تصحيح البرامج العادية ، ولكن نقاط التوقف لا يتم وضعها دائمًا في الأجهزة. في بعض الأحيان ، يتضمن إعداد نقطة توقف كتابة تعليمات خاصة إلى المكان الصحيح مباشرةً في رمز الجهاز . على سبيل المثال ، هذه هي الطريقة التي يعمل بها أمر b
القياسي في GDB. هنا ما يلي من هذا:
- لا يمكنك وضع نقطة داخل BootROM ، لأن ROM
- يمكنك تعيين نقطة توقف على الرمز الذي تم تحميله في ذاكرة الوصول العشوائي من بطاقة SD ، ولكن عليك الانتظار حتى يتم تحميله. خلاف ذلك ، لن نقوم بإعادة كتابة جزء من الشفرة ، ولكن الجرافة ستعيد كتابة نقطة توقفنا
أنا متأكد من أنه يمكنك المطالبة صراحة باستخدام نقاط توقف الأجهزة ، ولكن هناك عددًا محدودًا منها على أي حال.
تبادل سريع BootROM
في المرحلة الأولى من تصحيح الأخطاء ، غالبًا ما تكون هناك رغبة في إصلاح BootROM والمحاولة مرة أخرى. ولكن هناك مشكلة: BootROM هو جزء من التصميم الذي تم تحميله في FPGA ، وتوليفه مسألة عدة دقائق (وهذا بعد تجميع صورة BootROM نفسها على الفور من C و Assembler ...). لحسن الحظ ، في الواقع ، كل شيء أسرع بكثير : تسلسل الإجراءات كما يلي:
- إعادة تشغيل bootrom.mif (انتقلت إلى MIF بدلاً من HEX ، لأنه مع HEX كان لدي دائمًا بعض المشاكل ، و MIF هو تنسيق Alter الأصلي)
- في Quartus نقول
Processing -> Update Memory Initialization File
- على مجمع (في العمود الأيسر من المهام) ، الأمر ابدأ مرة أخرى
لكل شيء عن كل شيء - بضع عشرات من الثواني.
إعداد بطاقة SD
كل شيء بسيط نسبيًا هنا ، ولكن يجب أن تتحلى بالصبر ولديك مساحة تبلغ 14 جيجابايت تقريبًا:
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
الوقت.
والنتيجة هي بطاقة تم uEnv.txt
في GPT مع أربعة أقسام ، أحدها هو FAT مع uEnv.txt
وصورة قابلة للتنزيل بتنسيق FIT (تحتوي على عدة صور فرعية ، لكل منها عنوان التنزيل الخاص به) ، والقسم الآخر فارغ ، ومن المفترض أن يتم تنسيقه في Ext4 لنظام التشغيل Linux. قسمان آخران خفيان : U-Boot يعيش على قسم واحد (الإزاحة ، كما أفهمها ، سلكية في BootROM) ، من ناحية أخرى ، يبدو أن متغيرات البيئة الخاصة به حية ، لكنني لا أستخدمها بعد.
المستوى الأول ، BootROM
تقول الحكمة الشعبية: "إذا كان هناك في البرمجة رقصات مع الدف ، ثم في مجال الالكترونيات - وكذلك مع طفاية حريق." لم يكن الأمر كذلك بمجرد أن أحرقت اللوحة تقريبًا ، وقررت أن "حسنًا ، GND هو نفس المستوى المنخفض" (على ما يبدو ، لا تزال المقاومة لن تؤذي ...) إنها تتعلق أكثر بحقيقة أنه إذا الأيدي لا تنمو من هناك ، ثم الإلكترونيات لا تتوقف عن جلب المفاجآت: عندما كنت أعلق الموصل على اللوحة ، ما زلت لا أستطيع حل جهات الاتصال بشكل طبيعي - يظهر الفيديو كيف ينتشر اللحام بشكل مباشر طوال الاتصال ، فقط قم بتطبيق المكواة ، لقد حصلت عليها على أية حال. حسنًا ، ربما لم يكن اللحام مناسبًا لدرجة حرارة مكواة اللحام ، وربما شيئًا آخر ... بشكل عام ، عندما رأيت أنه كان لدي بالفعل عشرات الاتصالات ، بصق ، وبدأت في تصحيح الأخطاء. ثم بدأ شيء غامض : قمت بتوصيل RX / TX من UART ، أقوم بتحميل البرامج الثابتة - يكتب
INIT CMD0 ERROR
حسنًا ، كل شيء منطقي - لم أقم بتوصيل وحدة بطاقة SD. نحن نصلح الموقف ونحمّل البرامج الثابتة ... والصمت ... ما لم أغير رأيه ، وفتح النعش للتو: كان من الضروري توصيل أحد مخرجات الوحدة النمطية بـ VCC. في حالتي ، دعمت الوحدة 5 فولت للحصول على الطاقة ، لذلك دون التفكير مرتين ، علقت سلكًا ممتدًا من الوحدة إلى الجانب الآخر من اللوحة. ونتيجة لذلك ، فإن الموصل الملتوي الملتوي ملتوي ، وفقد اتصال UART ببساطة. facepalm.jpg بشكل عام ، "الرأس السيئ لا يعطي الراحة للساقين" ، ويداه ملتوية - إلى الرأس ...
في النهاية ، رأيت الذي طال انتظاره في Minicom
INIT CMD0 CMD8 ACMD41 CMD58 CMD16 CMD18 LOADING /
وعلاوة على ذلك، يتحرك مؤشر التحميل هو الغزل. أتذكر مباشرة السنوات الدراسية والتمهيد الممتع لـ MinuetOS من قرص مرن. ما لم يطحن محرك الأقراص.
المشكلة هي أن لا شيء يحدث بعد رسالة BOOT. لذا ، فقد حان الوقت للاتصال من خلال OpenOCD على Raspberry ، GDB على المضيف له ، ومعرفة ما هو عليه.
أولاً ، أظهر الاتصال بـ GDB على الفور أن $pc
(عداد البرنامج ، عنوان التعليمات الحالية) ينتقل إلى 0x0
- ربما يحدث هذا بعد خطأ متعدد. لذلك ، مباشرة بعد إصدار رسالة BOOT
، نضيف حلقة لا نهائية. هذا سوف يؤخره لفترة قصيرة ...
diff --git a/bootrom/sdboot/sd.cb/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; }
يتم استخدام مثل هذا الرمز الصعب "من أجل الموثوقية": لقد سمعت في مكان ما ، على ما يبدو ، أن حلقة لا نهائية هي سلوك غير محدد ، وهنا من غير المرجح أن يخمن المترجم (أذكر أن BootROM يقع في 0x10000
).

قد يبدو ذلك ، لكن ما الذي يمكن توقعه - مضمن قاسي ، ما هو نوع المصدر الموجود. ولكن بعد كل شيء ، في هذه المقالة ، قام المؤلف بتصحيح الكود ... Krex-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.

تحتاج فقط إلى تحميل ملف MIF وليس حاوية ، ولكن النسخة الأصلية بتنسيق ELF.
الآن ، مع محاولة nth لتخمين العنوان حيث سيستمر التنفيذ (وهذا سبب آخر لماذا لا يجب أن يكون المترجم قد خمن أن الحلقة لا نهائية). الفريق
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
ربما تأثر هذا أيضًا بحقيقة عدم امتلاك بطاقة 4Gb غير الضرورية في متناول اليد ، لقد DEMO_END=11718750
إلى 2 جيجابت واستبدلتها في Makefile بـ DEMO_END=11718750
بـ DEMO_END=3078900
(لا ابحث عن المعنى في القيمة المحددة - لا توجد الآن ، إلى البطاقة).
المستوى الثاني ، يو التمهيد
الآن ما زلنا "نقع" ، لكننا بالفعل على العنوان 0x0000000080089a84
. هنا يجب أن أعترف: في الواقع ، لا يذهب العرض التقديمي "مع كل المحطات" ، ولكن تمت كتابته جزئيًا "بعد" ، لذلك تمكنت هنا بالفعل من وضع ملف dtb الصحيح من شركة نفط الجنوب ، واضبط CONFIG_SYS_TEXT_BASE=0x80089800
المتغير في CONFIG_SYS_TEXT_BASE=0x80089800
HiFive_U-Boot
(بدلاً من 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
مرة أخرى إلى 0x80089800
(نقطة الدخول U-Boot) ، ونأمل ألا يتطلب الإعداد الصحيح 0x80089800
قبل الانتقال ... يبدو أن العمل:
(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 %08lx\n", fmt@entry=0x800d4458 "exception code: %d , %s , epc %08x , ra %08lx\n", 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 %08lx\n", 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 %08lx\n", args=args@entry=0x881cc188) at lib/vsprintf.c:717 #5 0x00000000800ccb50 in printf (fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc %08x , ra %08lx\n") 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
على المكدس تتبع سبب المشكلة الأصلية التي تسببت في الخطأ الأول ( mcause == 5
). إذا فهمت بشكل صحيح ما هو مكتوب هنا في الصفحة 37 ، فإن هذا الاستثناء يعني Load access fault
. السبب ، على ما يبدو ، هو لأنه هنا
القوس / riscv / وحدة المعالجة المركزية / 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.hb/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\0" /* 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 <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.h
يمكن العثور على التفاصيل في المستودع .
كما اتضح فيما بعد ، على سجلات SiFive هذه ، تحتوي سجلات بعض الأجهزة على عناوين مختلفة. اتضح أيضًا أن U-Boot قد تم تكوينه بواسطة آلية Kconfig ، المألوفة بالفعل من نواة Linux - على سبيل المثال ، يمكنك أن تطلب إجراء menuconfig ، وسترى واجهة نصية مريحة مع أوصاف المعلمات المعروضة في ?
إلخ بشكل عام ، بعد أن أعمى وصف الثلث من أوصاف اللوحتين ، ورمي أي إعادة تشكيل PLL مثيرة للشفقة من هناك (على ما يبدو ، هذا مرتبط بطريقة أو بأخرى بالتحكم PCIe من الكمبيوتر المضيف ، لكن هذا غير دقيق) ، حصلت على بعض البرامج الثابتة ، والتي ، إذا كان الطقس صحيحًا على المريخ أعطاني رسالة UART حول أي التزام تم جمعه منه ، وكم DRAM لدي (ولكني سجلت هذه المعلومات أيضًا في الرأس).
إنه لأمر مؤسف أنه بعد هذا توقف عادة عن الاستجابة مع JTAG المعالج ، والتشغيل من بطاقة SD ، للأسف ، ليست سريعة في التكوين الخاص بي. من ناحية أخرى ، في بعض الأحيان يعرض BootROM رسالة تفيد بأن ERROR
لا يمكنه التمهيد ، وظهرت U-Boot على الفور. عندها بزغ فجرًا لي: على ما يبدو ، بعد إعادة تشغيل BITSTREAM ، لا تتآكل الذاكرة في FPGA ، وليس لديها وقت "للتمزيق" ، إلخ. باختصار ، يمكنك ببساطة عند ظهور LOADING /
message ، الاتصال set variable $pc=0x80089800
الأوامر 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
— , environment. , « »? ! : U-Boot 2^24 SD-, , , , , 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: if (c == '\e') { *esc = 1; *key = KEY_NONE; } break; case 1: 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 — Core 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>
Berkeley Boot Loader. htif
— host interface, tethered- ( ARM), - standalone. , , , :
void poweroff(uint16_t code) { printm("Power off\r\n"); finisher_exit(code); if (htif) { htif_poweroff(); } else { send_ipi_many(0, IPI_HALT); while (1) { asm volatile ("wfi\n"); } } }
:
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))
Linux kernel
, :
BBL FDT 0xF0000000
, ! , … HiFive_U-Boot/arch/riscv/lib/boot.c , 0x81F00000
, U-Boot.
BBL , . mem_prop
, riscv-pk/machine/fdt.c : , fdt ram 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, — ).
, , , RocketChip JTAG trap- — .
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 not found, running software emulation . running. .
atomic_t hart_lottery; unsigned long boot_cpu_hartid;
linux/arch/riscv/kernel/setup.c — . , - , ...
.
. , , singlestep-.
( ):
