ميلاد سعيد Quartusel ، أو كيف أن المعالج قد حان لهذه الحياة



عند تصحيح البرامج العادية ، يمكن تعيين نقاط التوقف في كل مكان تقريبًا وبكميات كبيرة إلى حد ما. للأسف. عند تنفيذ برنامج على وحدة التحكم ، لا يتم تطبيق هذه القاعدة. إذا كان هناك قسم يتشكل فيه مخطط الوقت ، فإن المحطة ستدمر كل شيء. والممر في الترددات المنخفضة والعالية ليست هي الشيء نفسه. شروط الحدود هي بلاء من المطورين. أو ، على سبيل المثال ، حافلة USB. في NIOS II ، لم أكن أعمل معها ، ولكن في STM32 أمر فظيع. وأريد أن أرى شيئًا ما ، وعندما تتوقف ، يمكنك قضاء وقت ممتع. بشكل عام ، في كثير من الأحيان ، على الرغم من وجود تصحيح JTAG المتقدم ، فإن سلوك البرنامج في المناطق الحساسة للوقت محجوب. سيكون من الرائع أن نرى ، على الأقل بعد التنفيذ ، السلسلة التي مر بها البرنامج ، وأي الفروع نجحت وأيها لم تنجح!

من الأهمية بمكان معرفة تاريخ الاستثناءات. على NIOS II ، لم أفعل ذلك ، ولكن على Cyclone V SoC في ARM - تمامًا. عند تصحيح الأخطاء ، يعمل كل شيء ، وإذا قمت بتشغيل البرنامج من ROM ، فستحصل على استثناء. من الواضح كيف دخلوا ، ونوع تطور الموقف الذي أدى إلى هذا الأمر ليس كذلك. تتبع أيضا كسر جميع الأغطية.

المقالات السابقة في السلسلة:
  1. تطوير أبسط "البرامج الثابتة" لأجهزة FPGA المثبتة في Redd ، وتصحيح الأخطاء باستخدام اختبار الذاكرة كمثال
  2. تطوير أبسط "البرامج الثابتة" لأجهزة FPGA المثبتة في Redd. الجزء 2. رمز البرنامج
  3. تطوير جوهرها الخاص لتضمينها في نظام المعالج على أساس FPGA
  4. تطوير برامج للمعالج المركزي Redd على سبيل المثال من الوصول إلى FPGA
  5. أول التجارب باستخدام بروتوكول الدفق على سبيل المثال من وحدة المعالجة المركزية والاتصالات المعالج في Redd FPGA

مقدمة


من المعتاد أن تكتب مقالات تعليمية ذات وجه جاد ، تحدد المواد بهدوء ونزاهة. لكن للأسف ، هذا لا ينجح دائمًا. الآن ، وفقًا للخطة ، يجب أن يكون هناك مقال عن تحسين المعالج المركب في مجمع Redd ، والذي نحتاج فيه إلى التحدث عن ميزات العمل مع ذاكرة التخزين المؤقت. التالي هو مقال عن التأخير عند الوصول إلى الحافلة. بشكل عام ، كل هذا يمكن أن يظهر على الذبذبات. لقد فعلت هذا بالفعل في مقال عن DMA (" DMA: الخرافات والواقع "). لكنني أردت أن أوضح كل شيء باستخدام المعالج نفسه ، لقد أجريت مثل هذه الفحوصات على نواة ARM في FPGA Cyclone V SoC. مريحة للغاية (على الرغم من عدم نشر النتائج). لهذا السبب ، قررت التعامل مع آلية التتبع الكامنة في كتلة JTAG. إنه لأمر مؤسف أنني لم أتمكن حتى الآن من عرض موارد مجانية قابلة للتنزيل مع عدد مرات التغلب على هذا الأمر أو تلك القيادة ، ولكن كانت هناك مواد يمكن من خلالها أن يسأل البرنامج دائمًا كيف وصل إلى هذه الحياة. حسنًا ، وإلى جانب ذلك ، بينما لا تزال ذكريات الأمسيات العاصفة جديدة في ذاكرتي ، إلا أنني سأرميها بطريقة عاطفية إلى حد ما. حتى اليوم سيكون هناك العديد من المذكرات ونظرية مفيدة قليلا.

الجزء الأجهزة


لذلك ، غالبًا عند تصحيح برنامج لأحد المتحكمين ، من المستحسن معرفة المسار الذي سلكه ، ويجب أن يمر بأقصى سرعة. بالنسبة إلى حالة NIOS II ، تتوفر هذه الآلية ويتم تضمينها هنا في علامة التبويب هذه لخصائص كور المعالج:



يقوم نوع التتبع بتعيين نوع المعلومات التي سيتم تخزينها. لا يمكنك حفظ أي شيء (سيؤدي ذلك إلى حفظ ذاكرة الشريحة) ، يمكنك فقط حفظ محفوظات الأوامر (غالباً ما يكون هذا كافياً) ، أو يمكنك حفظ محفوظات كل من الأوامر والبيانات. تجدر الإشارة إلى أن الوثائق تقول إن حفظ المعلومات في الوضع الأخير صعب إلى حد ما ، في حين أن التراكبات مع تاريخ الأوامر ممكنة ، وتستهلك ذاكرة أكبر. لذلك استخدم هذا الوضع فقط عندما يكون ذلك ضروريًا حقًا.

تعيّن المعلمة Trace Storage نوع الذاكرة التي سيتم حفظ التتبع فيها. تشير الوثائق إلى أن الذاكرة الخارجية لا تدعمها بيئة التطوير القياسية. لذلك ، من الأفضل اختيار فقط من الداخل.



حسنًا ، يحدد Onchip Trace Frame Size حجم المخزن المؤقت. كلما زاد حجم المخزن المؤقت ، كلما أمكن وضع المزيد من الأحداث فيه ، كلما كان من الممكن مراعاة السجل. ولكن أقل ستكون ذاكرة الكريستال لتلبية الاحتياجات الأخرى.



ليست هناك حاجة لتمكين مربع الاختيار من إنشاء منفذ JTAG منفصل. السماح لكل شيء سيارات الأجرة على واحد منتظم.

دعم البرمجيات


حسنا. لذلك قمنا بإعداد المعالج الأساسي ، ماذا بعد؟ اوووه! ثم تبدأ قصة المباحث. إذا كان يجب تفسير الأرقام أعلاه كدليل للعمل ، فسوف تتبع الرسوم التوضيحية التي تظهر الفوضى والإسكات. يقول عدد من المستندات أنه للعمل مع التتبع ، يجب عليك استخدام برامج باهظة الثمن تابعة لجهات خارجية وحتى معدات JTAG الخاصة. لكن في بعض الوثائق ، يمكنك أن تأخذ شيئا بدوام كامل.

تجارب الكسوف


غرامة. دعونا ننظر حولنا في الكسوف. أذكركم أنني أستخدم بيئة تطوير Quartus Prime 17.1. حسنا ، لقد حدث ذلك. نبدأ تشغيل برنامج التصحيح وننتقل إلى عنصر القائمة الذي يسمح لك بفتح العديد من النوافذ:



هناك نختار Debug-> نافذة التحكم في التتبع:



ونحصل على مثل هذه الدمية:



ولكن بدأت جلسة تصحيح الأخطاء. علاوة على ذلك ، ظهرت عناصر القائمة ابدأ التتبع وإيقاف التتبع (قبل فتح هذه النافذة لم تكن كذلك). لكن تم حظرهم. ولم أستطع تفعيلها.



عبثا لم تملأ جوجل مع طلبات مختلفة. في الوثائق القديمة ، توصف هذه العناصر بأنها تعمل جيدًا ، لكن في البنود الحديثة ، لم يتم ذكرها ببساطة. لا أحد يذكرهم على المنتديات. ربما شخص ما في التعليقات سوف اقول لك شيئا؟

مشاكل مع أحدث إصدار من Eclipse


حسنا. ماذا عن أحدث نسخة من بيئة التطوير؟ ربما كل شيء يعمل هناك؟ Yyyyyy! هذا موضوع لفصل منفصل. أحدث إصدار للأعاصير الرابعة والخامسة هو 18.1.1. أي ، يجب عليك أولاً تنزيل الإصدار 18.1 ، ثم تثبيت التحديث 18.1.1. إذا قرر شخص ما أن لدي الكثير من وقت الفراغ ، وأعيد ترتيب البرامج من أجل كل شيء صغير ، فكل شيء على ما يرام. وكان الاختيار الرئيسي حول مشاكل ذاكرة التخزين المؤقت. إنها أكثر جدية ، أردت التحقق منها في الإصدار الجديد ، أنا لا أكتب عنها هنا.

لذلك ، قمت بتنزيله. المعمول بها. أولاً ، تم إطلاق الإصدار 18.1 ضمن WIN7 ، ولكن 18.1.1 لم يعثر على DLL. حسنا. اكتشفت أنني بحاجة إلى تنزيل Redist من Visual Studio 2015. لقد قمت بتثبيته. بدأ الجري. إنشاء مشروع مع نظام المعالج. حتى انه استعد. سأذهب إلى Eclipse ، فأقوم بإنشاء برنامج مع BSP بناءً عليه ، كل شيء ، كما فعلنا بالفعل عدة مرات ... وأحصل على شيء من هذا القبيل ...



المشروع لن. إذا قمت بالخروج والدخول ، فسيتم فتحه جزئيًا فقط.



رؤية المجلد مغلقة؟ ها أنت ذا. لماذا؟ وجميلة! ثلاثة ملفات لها:



هذه هي السمات الرائعة للحماية:



لذلك لا يمكن فتحها أو تغييرها ... إذا أعطيت مزيدًا من الحقوق ، فسيتم فتح المشروع ، لكن لم يتم إنشاء الملفات بالكامل ، لذلك لن يعمل على تجميعها. حاول منح الحقوق حتى يتم إغلاق Eclipse ، ثم قم بحفظ المشروع. والنتيجة هي نفسها.

هل يمكن تحميل Windows 7 بسرعة الشيخوخة؟ لا عجب أنني افتقرت المكتبات! أنا وضعت Quartus جديدة على WIN10 ، أحصل على نتيجة متطابقة تماما لإنشاء المشروع! لدي صديق بحكم مكان عمله ، يواجه في بعض الأحيان منتجات الشركات المصنعة المحلية. وهو يعبر عن سلسلة من الأفكار عن أنفسهم وعن أقاربهم. حسنًا ، عن حقيقة أن "من يبني هذا؟" كما تعلمون ، عند النظر إلى أفراح برنامج Intel ، بدأت أعتقد أنه بعيد عن بلد المنشأ ... في الواقع ، لم يكن هذا هو الحال في Alter ... أي شيء حدث ، لكنني لا أتذكر ذلك.

لقد خرجت للتو. قمت بنسخ المشروع إلى محرك أقراص USB محمول باستخدام نظام الملفات FAT32. لا توجد سمات أمنية. فتحت المشروع منه وذهبت إلى Eclipse وأنشأت الكود. لا توجد سمات أمنية - لا مشكلة. ثم قمت بنسخه مرة أخرى إلى القرص الصلب و ... حسنًا ، بالطبع ، واجهت مشاكل في توليد BSP. لأن الملف * .bsp يحتوي على العديد من المسارات النسبية والأخرى المطلقة. من الجيد أن أخرجت محرك أقراص فلاش. خلاف ذلك ، لم أكن لألاحظ أن BSP يسقط عليه (حيث أن هذا هو مسقط رأس المشروع) ، ويتم جمع المشروع على القرص الصلب. فيما يلي مثال لمثل هذا المسار (تم تصحيحه بالفعل):



حسنًا ، حسنًا ... تم إنشاء كل شيء وتجميعه ... وهو يعمل بنفس الطريقة تمامًا كما في الإصدار 17.1 ... وبالنسبة لوحدات تحكم شركة نفط الجنوب في البيئة الجديدة ، عليك أيضًا إعادة إنشاء سلسلة JTAG في كل مرة في مبرمجها. في الإصدار 17.1 ، كان يكفي القيام بذلك مرة واحدة وحفظ ... Eeeeeh. حسنا حسنا ...

ألتيرا مونيتور ومشكلتها


بطريقة أو بأخرى ، بحثت شبكة عن الكلمات "بدء التتبع وإيقاف التتبع" قادني إلى وثائق مثيرة للاهتمام. يصفون إصدارات مختلفة من برنامج مضحك يسمى Altera Monitor اليوم (كان الاسم مختلفًا في المستندات القديمة). العثور عليها كان سهلا نسبيا. تحتاج إلى تنزيل حزمة برنامج الجامعة لإصدار بيئة التطوير لديك. إيلاء الاهتمام لقيود الترخيص. لكن بما أننا ندرس الآن ، فنحن لسنا خائفين من ذلك. ولكن للعمل التجاري - كل شيء سيء هناك. التفاصيل هنا: www.intel.com/content/www/us/ar/programmable/support/training/university/materials-software.html

تنزيل ، وضع ... هناك مستند مرفق بالإصدار الحالي (لأن الإصدارات المنتشرة على الإنترنت تختلف اختلافًا كبيرًا). حاولت حتى أن أضرب مثالاً على لوح الخبز DE0-Nano-SoC. هو يعمل. لكن عندما حاولت تنفيذ مشروعي ، لم ينجح الأمر. يتم تحميل ملف * .sof في FPGA ، وبعد ذلك ، بعد فترة ، يتم عرض رسالة:



فقط لا توجد معلومات في النافذة المحددة. إذا حاولت التنزيل مرة أخرى: حسنًا ، فسيظهر النص في تلك النافذة فقط:
لا يمكن الاستعلام عن معرفات مثيل JTAG.

يرجى التأكد من تكوين FPGA باستخدام ملف .sof الصحيح.

أي نوع من المشاكل هذا؟ لقد بحثت على جوجل. وجدت العديد من المنتديات مع نفس المشكلة. في أحدها ، سأل أحد موظفي شركة Intel عن التردد الذي لدى المؤلف في JTAG واقترح وضع معيار واحد. على الرغم من ذلك ، بحلول ذلك الوقت فهمت بالفعل أنه لم يكن مسألة تواتر: مثال الشركات عملت ، وكيفية ضبطه؟ في أحد المنتديات ، كتب المؤلف أنه مر بطريقة ما. لم يفهم كيف. وقال إنه إذا قمت بكل شيء بعناية وفقًا للتعليمات ، فسيعمل كل شيء. كانت بقية الصورة هي نفسها. يسأل الرجل. لا يجيبونه. بعد ستة أشهر أو سنة ، يكتب شخص ما لديه نفس الموقف ، هل كان هناك حل؟ والصمت aaaaaaaa ...

محاولات الحل ذوي الخبرة


حسنا. ماذا يمكن أن يكون السبب؟ في البداية قررت أن أنظر حولي في مثال عملي. أي نوع من معرف JTAG الغامض؟ يمكن أن يكون هذا بسبب وجود نظام معرف نظام العمل؟



يضاف إلى نفسه ، لم يساعد. ربما يتم توجيه اللوم إلى JTAG to Avalon bridge ، والتي ترتبط بها جميع الأجهزة الطرفية بشكل إضافي ،؟



وأضاف - لم يساعد. جربت بعض الفرضيات الأخرى ، لكنني أدركت أنه يمكنك تخمينها إلى الأبد. مع الحزن ، سألت حتى ياندكس ، بنج ، وحتى بايدو. انهم جميعا يعرفون أقل من جوجل. أصبح من الواضح أننا اضطررنا إلى التعامل مع عملية إزالة التجميع لاستخراج ما يحتاج إليه من البرنامج نفسه. دققت في اللغة المكتوبة في البرنامج. اتضح أن في جاوة. يتم تخزين bytecode في ملف Altera_Monitor_Program.jar. حسنا ، هذا غريب. باستثناء حقيقة أنني لا أعرف هذا جافا على الإطلاق. على Java Script ، كانت هناك حالة ، انخرطت في Internet of Things ، لكنني لم أجد Java حقيقيًا. لكن أين لم تختف!

JAVA bytecode analysis للعثور على المشكلة


كيفية فتح رمز البايت؟ أدت Google إلى مقال عن Habré ، والذي ينص على أنك بحاجة إلى استخدام JD-GUI لهذا الغرض. وجدت على جيثب ، وتنزيلها. لقد حددت مشكلة المنطقة بسرعة إلى حد ما ، نظرًا لأن JD-GUI بها نظام تفاعلي رائع. من الرسالة إلى الموقع ، خرجت خلال 10 دقائق. يستدعي هذا القسم برنامجًا تابعًا لجهة خارجية ، وبعد ذلك يقوم بتحليل رده. المكالمة تبدو مثل هذا:
systemConsoleCommand[index] = "system-console"; systemConsoleCommand[var24++] = "--script=" + Globals.gHost.getMonitorProgramRootDir("bin/jtag_instance_check.tcl", true); systemConsoleCommand[var24++] = cable; systemConsoleCommand[var24++] = Globals.gProject.system.sofFilename; try { Process sysConsoleProc = NiosIIShell.executeCommand(systemConsoleCommand).start(); BufferedReader gdbIn = new BufferedReader(new InputStreamReader(sysConsoleProc.getInputStream())); 

حسنًا ، والمزيد - تحليل الإجابة التي لا نعتبرها بعد.

باستخدام هذا الرمز ، حاولت فتح وحدة التحكم NIOS II:



هناك ذهبت إلى الدليل حيث يوجد ملف sof وقاد سطر الأوامر:
نظام وحدة التحكم --script = jtag_instance_check.tcl USB-0 test.sof

صحيح ، لهذا اضطررت إلى نسخ الملف C: \ intelFPGALite \ 17.1 \ University_Program \ Monitor_Program \ bin \ jtag_instance_check.tcl إلى نفس المكان الذي يوجد فيه sof ، حتى لا أعاني من المسار. في النهاية ، حصلت على استجابة لائقة جدا:

TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH jtag_uart_0 (INSTANCE_ID: 0)

TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH nios2_gen2_0 (INSTANCE_ID: 0)


يبدو أن كل شيء جميل ...

جافا Bytecode تتبع


إذا حدثت القضية اليوم ، فلن يكون هذا القسم موجودًا. ولكن حدث ما حدث بالأمس. ما زلت أفهم جافا سيئة للغاية. ما كتب هناك أثناء تحليل النص كان غابة مظلمة بالنسبة لي. صحيح ، لمدة عامين حضر طفلي دورات البرمجة الأولمبية في 1 الامتياز السوفياتي (كانت الشهادات والنشرات 1 السوفياتي). أعطيت المال مجنون لهذه الدورات. وعلموهم هناك فقط في جاوة. لذلك ، لم يفهم أيضًا ما تمت كتابته في الكود (مع الاحتفاظ بالمكائد ، سأنشر الكود أقل قليلاً ، ليس الآن). بشكل عام ، كان هناك شعور مستمر بأن الوقت قد حان لتتبع. أعرف القسم السيئ ، وأرى أنه تم استلام الخطوط هناك وأن البرنامج لا يعجبهم بشيء. ماذا بعد؟

وجدني الطفل مقالًا رائعًا جدًا www.crowdstrike.com/blog/native-java-bytecode-debugging-without-source-code

يتحدث عن مكون إضافي مفيد للغاية لـ Eclipse ، والذي يسمح لك بالعمل مع JARs ، ووضع نقاط توقف فيها. من أين يمكنني التنزيل ، وجدت هنا: marketplace.eclipse.org/content/bytecode-visualizer/help

لقد قمت بتنزيل Eclipse ، وقمت بتنزيل المكون الإضافي للتثبيت في وضع عدم الاتصال مع الحزن إلى النصف ... بدأت التثبيت - لا توجد مكتبات كافية. بدأت القراءة. اتضح أن هناك ثلاثة إصدارات من البرنامج المساعد. ضمن Eslipse 4.5 (Mars) و 4.4 (Luna) و 4.3 (لا أتذكر الاسم). حسنا ، كل شيء بسيط. نذهب إلى موقع Eclipse ، ونرى رابطًا لتنزيل إصدار Mars for Java ... و ... لقد مات. لا يهم! هناك ما يقرب من عشرة مرايا .. وجميع الروابط معهم ميتة. نحن نحاول Luna for Java ، هناك روابط إلى x64 ميتة ، و x86 هناك عيش واحد ... كما يقول صديق لي: "البواسير ، إنها شاملة". بشكل عام ، واجهت Google وقتًا عصيبًا ، لكن وجدت لي مجموعة Java 64 بت من إصدار المريخ على بعض الخوادم غير الرسمية. قمت بتنزيله لمدة نصف ساعة ، لكنني قمت بتنزيله.

نفذت البرنامج المساعد ، أنشأ مشروع ... الرعب! هناك ، التتبع ليس على مستوى الكود المصدري ، ولكن على مستوى المجمّع. باختصار ، يتم تتبع شفرة البايت المشفرة. ولكن في الواقع ، لا يهم! بعد كل شيء ، يمكنك دائمًا التحقق من المصادر التي تم فك شفرتها والتي تم فتحها في نافذة أخرى ، بالإضافة إلى أن المكوّن الإضافي يعرض تعليقات جيدة جدًا ... واتضح أيضًا أنه لا يمكن تعيين نقاط التوقف في أي مكان ، ولكن عند مدخل الوظيفة فقط. لكن لا أستطيع التوقف! ليس هناك الكثير وتحتاج إلى المشي من مدخل منطقة المشكلة.

اسمحوا لي أن أذكرك بأن الخطوط المعالجة تبدو كما يلي:
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH jtag_uart_0 (INSTANCE_ID: 0)

TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH nios2_gen2_0 (INSTANCE_ID: 0)

وهنا هو رمز جافا:
 if (str.contains("(INSTANCE_ID:")) { Pattern getInstance = Pattern.compile("\\(INSTANCE_ID:(\\d+)\\)"); Matcher idMatcher = getInstance.matcher(str); if (idMatcher.find()) { String foundstr = idMatcher.group(1); instance = Integer.parseInt(foundstr); } 

يعزل تماما معرف مثيل. وهنا هو الكود:
  Pattern getHPath = Pattern.compile("FULL_HPATH (.+?)\\|(.+?) \\("); Matcher hpathMatcher = getHPath.matcher(str); if (hpathMatcher.find()) { hpath = hpathMatcher.group(2).replace("|", "."); } 

متغير hpath لا يملأ. اليوم أنا أعرف بالفعل أن التعبير العادي:
 "FULL_HPATH (.+?)\\|(.+?) \\(" 

يتطلب كلمتين مفصولة شريط عمودي. حسنًا ، إذن ما هو فقط بعد أخذ الخط. لم أكن أعرف بالأمس. أكثر إثارة للاهتمام هو آخر. درس الطفل العمل في جاوة لمدة عامين ولم يتعلم التعبيرات العادية! لا ، من الواضح أنهم لم يتعلموا اللغة ، ولكن برمجة أوليمبياد عن طريق اللغة ، لكن كما أفهمها ، فإن التعبيرات المنتظمة في جافا هي في ترتيب الأشياء. إنهم يأخذون مثل هذه الأموال ، وهم يهزون الشهادات من الشركات ذات السمعة الطيبة ، لكنهم لا يعلمون أشياء مهمة ... لكنني أحفر.

ضوء في نهاية النفق


ما هو الخط العمودي؟ نأخذ المشروع الذي نجح ونمنحه نفس الفريق ونحصل على هذه الإجابة:

TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART (INSTANCE_ID: 0)

TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_2nd_Core (INSTANCE_ID: 1)

TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_for_ARM_0 (INSTANCE_ID: 2)

TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_for_ARM_1 (INSTANCE_ID: 3)

TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH Computer_System: The_System | Nios2 (INSTANCE_ID: 0)

TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH Computer_System: The_System | Nios2_2nd_Core (INSTANCE_ID: 1)

ما هو نظام الكمبيوتر: The_System؟ كل شيء بسيط هنا. في هذه السلسلة من المقالات ، أشجع فكرة متقدمة حيث يكون نظام الكمبيوتر في المستوى الأعلى من التسلسل الهرمي.
وهذا المثال لديه طبقة فيريلوج:
 module DE0_Nano_SoC_Computer ( //////////////////////////////////// // FPGA Pins //////////////////////////////////// // Clock pins input CLOCK_50, input CLOCK2_50, input CLOCK3_50, // ADC output ADC_CONVST, output ADC_SCLK, output ADC_SDI, input ADC_SDO, // ARDUINO inout [15:0] ARDUINO_IO, inout ARDUINO_RESET_N, // GPIO inout [35:0] GPIO_0, inout [35:0] GPIO_1, // KEY input [1:0] KEY, // LED output [7:0] LED, // SW input [3:0] SW, //////////////////////////////////// // HPS Pins //////////////////////////////////// // DDR3 SDRAM output [14:0] HPS_DDR3_ADDR, output [2:0] HPS_DDR3_BA, output HPS_DDR3_CAS_N, output HPS_DDR3_CKE, output HPS_DDR3_CK_N, output HPS_DDR3_CK_P, output HPS_DDR3_CS_N, output [3:0] HPS_DDR3_DM, inout [31:0] HPS_DDR3_DQ, inout [3:0] HPS_DDR3_DQS_N, inout [3:0] HPS_DDR3_DQS_P, output HPS_DDR3_ODT, output HPS_DDR3_RAS_N, output HPS_DDR3_RESET_N, input HPS_DDR3_RZQ, output HPS_DDR3_WE_N, // Ethernet output HPS_ENET_GTX_CLK, inout HPS_ENET_INT_N, output HPS_ENET_MDC, inout HPS_ENET_MDIO, input HPS_ENET_RX_CLK, input [3:0] HPS_ENET_RX_DATA, input HPS_ENET_RX_DV, output [3:0] HPS_ENET_TX_DATA, output HPS_ENET_TX_EN, // Accelerometer inout HPS_GSENSOR_INT, // I2C inout HPS_I2C0_SCLK, inout HPS_I2C0_SDAT, inout HPS_I2C1_SCLK, inout HPS_I2C1_SDAT, // Pushbutton inout HPS_KEY, // LED inout HPS_LED, // LTC inout HPS_LTC_GPIO, // SD Card output HPS_SD_CLK, inout HPS_SD_CMD, inout [3:0] HPS_SD_DATA, // SPI output HPS_SPIM_CLK, input HPS_SPIM_MISO, output HPS_SPIM_MOSI, inout HPS_SPIM_SS, // UART input HPS_UART_RX, output HPS_UART_TX, // USB inout HPS_CONV_USB_N, input HPS_USB_CLKOUT, inout [7:0] HPS_USB_DATA, input HPS_USB_DIR, input HPS_USB_NXT, output HPS_USB_STP ); //======================================================= // REG/WIRE declarations //======================================================= wire hps_fpga_reset_n; //======================================================= // Structural coding //======================================================= Computer_System The_System ( //////////////////////////////////// // FPGA Side //////////////////////////////////// // Global signals .system_pll_ref_clk_clk (CLOCK_50), .system_pll_ref_reset_reset (1'b0), // ADC .adc_sclk (ADC_SCLK), .adc_cs_n (ADC_CONVST), .adc_dout (ADC_SDO), .adc_din (ADC_SDI), // Arduino GPIO .arduino_gpio_export (ARDUINO_IO), // Arduino Reset_n .arduino_reset_n_export (ARDUINO_RESET_N), // Slider Switches .slider_switches_export (SW), // Pushbuttons .pushbuttons_export (~KEY), // Expansion JP1 .expansion_jp1_export ({GPIO_0[35:19], GPIO_0[17], GPIO_0[15:3], GPIO_0[1]}), // Expansion JP7 .expansion_jp7_export ({GPIO_1[35:19], GPIO_1[17], GPIO_1[15:3], GPIO_1[1]}), // LEDs .leds_export (LED), //////////////////////////////////// // HPS Side //////////////////////////////////// // DDR3 SDRAM .memory_mem_a (HPS_DDR3_ADDR), .memory_mem_ba (HPS_DDR3_BA), .memory_mem_ck (HPS_DDR3_CK_P), .memory_mem_ck_n (HPS_DDR3_CK_N), .memory_mem_cke (HPS_DDR3_CKE), .memory_mem_cs_n (HPS_DDR3_CS_N), .memory_mem_ras_n (HPS_DDR3_RAS_N), .memory_mem_cas_n (HPS_DDR3_CAS_N), .memory_mem_we_n (HPS_DDR3_WE_N), .memory_mem_reset_n (HPS_DDR3_RESET_N), .memory_mem_dq (HPS_DDR3_DQ), .memory_mem_dqs (HPS_DDR3_DQS_P), .memory_mem_dqs_n (HPS_DDR3_DQS_N), .memory_mem_odt (HPS_DDR3_ODT), .memory_mem_dm (HPS_DDR3_DM), .memory_oct_rzqin (HPS_DDR3_RZQ), // Accelerometer .hps_io_hps_io_gpio_inst_GPIO61 (HPS_GSENSOR_INT), // Ethernet .hps_io_hps_io_gpio_inst_GPIO35 (HPS_ENET_INT_N), .hps_io_hps_io_emac1_inst_TX_CLK (HPS_ENET_GTX_CLK), .hps_io_hps_io_emac1_inst_TXD0 (HPS_ENET_TX_DATA[0]), .hps_io_hps_io_emac1_inst_TXD1 (HPS_ENET_TX_DATA[1]), .hps_io_hps_io_emac1_inst_TXD2 (HPS_ENET_TX_DATA[2]), .hps_io_hps_io_emac1_inst_TXD3 (HPS_ENET_TX_DATA[3]), .hps_io_hps_io_emac1_inst_RXD0 (HPS_ENET_RX_DATA[0]), .hps_io_hps_io_emac1_inst_MDIO (HPS_ENET_MDIO), .hps_io_hps_io_emac1_inst_MDC (HPS_ENET_MDC), .hps_io_hps_io_emac1_inst_RX_CTL (HPS_ENET_RX_DV), .hps_io_hps_io_emac1_inst_TX_CTL (HPS_ENET_TX_EN), .hps_io_hps_io_emac1_inst_RX_CLK (HPS_ENET_RX_CLK), .hps_io_hps_io_emac1_inst_RXD1 (HPS_ENET_RX_DATA[1]), .hps_io_hps_io_emac1_inst_RXD2 (HPS_ENET_RX_DATA[2]), .hps_io_hps_io_emac1_inst_RXD3 (HPS_ENET_RX_DATA[3]), // I2C .hps_io_hps_io_i2c0_inst_SDA (HPS_I2C0_SDAT), .hps_io_hps_io_i2c0_inst_SCL (HPS_I2C0_SCLK), .hps_io_hps_io_i2c1_inst_SDA (HPS_I2C1_SDAT), .hps_io_hps_io_i2c1_inst_SCL (HPS_I2C1_SCLK), // Pushbutton .hps_io_hps_io_gpio_inst_GPIO54 (HPS_KEY), // LED .hps_io_hps_io_gpio_inst_GPIO53 (HPS_LED), // LTC .hps_io_hps_io_gpio_inst_GPIO40 (HPS_LTC_GPIO), // SD Card .hps_io_hps_io_sdio_inst_CMD (HPS_SD_CMD), .hps_io_hps_io_sdio_inst_D0 (HPS_SD_DATA[0]), .hps_io_hps_io_sdio_inst_D1 (HPS_SD_DATA[1]), .hps_io_hps_io_sdio_inst_CLK (HPS_SD_CLK), .hps_io_hps_io_sdio_inst_D2 (HPS_SD_DATA[2]), .hps_io_hps_io_sdio_inst_D3 (HPS_SD_DATA[3]), // SPI .hps_io_hps_io_spim1_inst_CLK (HPS_SPIM_CLK), .hps_io_hps_io_spim1_inst_MOSI (HPS_SPIM_MOSI), .hps_io_hps_io_spim1_inst_MISO (HPS_SPIM_MISO), .hps_io_hps_io_spim1_inst_SS0 (HPS_SPIM_SS), // UART .hps_io_hps_io_uart0_inst_RX (HPS_UART_RX), .hps_io_hps_io_uart0_inst_TX (HPS_UART_TX), // USB .hps_io_hps_io_gpio_inst_GPIO09 (HPS_CONV_USB_N), .hps_io_hps_io_usb1_inst_D0 (HPS_USB_DATA[0]), .hps_io_hps_io_usb1_inst_D1 (HPS_USB_DATA[1]), .hps_io_hps_io_usb1_inst_D2 (HPS_USB_DATA[2]), .hps_io_hps_io_usb1_inst_D3 (HPS_USB_DATA[3]), .hps_io_hps_io_usb1_inst_D4 (HPS_USB_DATA[4]), .hps_io_hps_io_usb1_inst_D5 (HPS_USB_DATA[5]), .hps_io_hps_io_usb1_inst_D6 (HPS_USB_DATA[6]), .hps_io_hps_io_usb1_inst_D7 (HPS_USB_DATA[7]), .hps_io_hps_io_usb1_inst_CLK (HPS_USB_CLKOUT), .hps_io_hps_io_usb1_inst_STP (HPS_USB_STP), .hps_io_hps_io_usb1_inst_DIR (HPS_USB_DIR), .hps_io_hps_io_usb1_inst_NXT (HPS_USB_NXT) ); endmodule 


لقد أحضرتُه بالكامل على وجه التحديد للتأكيد على الكود غير الضروري تمامًا الذي يتعين عليك كتابته في هذه الحالة. وإذا تمت إضافة الأرجل أو إزالتها ، فسيتعين أيضًا تحرير هذا الرمز. في الواقع ، الخطوط


نفس النص:
 ... Computer_System The_System ( //////////////////////////////////// // FPGA Side //////////////////////////////////// // Global signals .system_pll_ref_clk_clk (CLOCK_50), ... 


واعطاء هذه البادئة. يعتقد المؤلفون أن التسلسل الهرمي يجب أن يكون هكذا ، هذا فقط وليس غيره. لا يمكن إزالة نظام المعالج بشكل أعمق ولا يمكن حمله.

يجب أن لا ننتظر الرحمة من الطبيعة ، أعتبر - مهمتنا!


هل قمنا حقا بمثل هذه المهمة لمجرد تحمل هذه المسألة؟ كما يحب أحد أصدقائي أن يقول: "العمل غير الضروري أسوأ من السكر" ، وإنشاء مثل هذه الطبقة هو حالة نموذجية للعمل غير الضروري. لذلك ، سنحاول الالتفاف على هذا القيد. تذكر أنه عند الاتصال ببرنامج JAVA لجهة خارجية ، استبدل الرمز بعض النصوص tcl ، كما قمت بنسخه إلى الدليل المجاور للملف sof؟ إنه خلاصنا! إنه هو الذي يخبر وحدة التحكم في النظام بالإجراءات التي يجب اتخاذها وهو الذي يقوم بتنسيق الاستجابة. التنسيق مثل هذا:

نفس النص:
 # PRINT OUT INSTANCE ID INFO FOR EVERYTHING: set i 0 foreach path [lsort -command compare_node_number [get_service_paths bytestream]] { # If this path corresponds to a JTAG UART, incr i if {[string match *$cable_name* $path ] && [string match *jtag_uart* [marker_get_type $path] ]} { puts "[marker_get_info $path] (INSTANCE_ID:$i)" incr i } } set i 0 foreach path [lsort -command compare_node_number [get_service_paths processor]] { # If this path corresponds to a NiosII, incr i if {[string match *$cable_name* $path ] && [string match *nios2* [marker_get_type $path] ]} { puts "[marker_get_info $path] (INSTANCE_ID:$i)" incr i } } 


تقوم الكتلة الأولى بتنسيق معلومات حول كتل JTAG_UART ، والثانية - حول مراكز المعالج. الآن ، إذا أضفنا خطوطًا عمودية إلى تيار الإخراج! صحح زميلي هذا القسم على النحو التالي:
 # PRINT OUT INSTANCE ID INFO FOR EVERYTHING: set i 0 foreach path [lsort -command compare_node_number [get_service_paths bytestream]] { # If this path corresponds to a JTAG UART, incr i if {[string match *$cable_name* $path ] && [string match *jtag_uart* [marker_get_type $path] ]} { set info [marker_get_info $path] if {[string first "|" $info] == -1} { set info [string map {"FULL_HPATH " "FULL_HPATH a:b|"} $info] } puts "$info (INSTANCE_ID:$i)" incr i } } set i 0 foreach path [lsort -command compare_node_number [get_service_paths processor]] { # If this path corresponds to a NiosII, incr i if {[string match *$cable_name* $path ] && [string match *nios2* [marker_get_type $path] ]} { set info [marker_get_info $path] if {[string first "|" $info] == -1} { set info [string map {"FULL_HPATH " "FULL_HPATH a:b|"} $info] } puts "$info (INSTANCE_ID:$i)" incr i } } 

الآن ، إذا لم تكن هناك شرطة ، فسيتم إضافتها. وأخيرا ، سوف يعمل البرنامج ليس فقط مع رهيب ، ولكن أيضا مع نظام معالج مكتوب على النحو الأمثل!

إعداد مشروع في Altera Monitor


Uffff. هذا كل شيء. نهاية التلاعب ، على الطرق الوعرة والضعف (على الرغم من أنه على الطرق الوعرة - هذا ليس دقيقًا). الآن مرة أخرى ، الرسومات الموجودة في المقالة تعكس تعليمات العمل! لدينا مشروع لـ FPGAs ، بالإضافة إلى برنامج يقوم ببناء وتشغيل Eclipse. الآن قم بتشغيل Altera Monitor وإنشاء مشروع.



نقوم بإنشاء كتالوج مع المشروع (أضعه بشكل منفصل عن مشروع FPGA) ونعطي اسم المشروع. اختر أيضًا بنية المعالج



النظام الذي اخترته هو نظام مخصص. يجب عليك تحديد ملفاتي * .sof و * .sopcinfo. أنا حددهم في الدلائل العاملة. نظامنا لا يحتاج إلى تحميل مسبق.



حدد نوع البرنامج مع دعم برنامج تشغيل الجهاز ، ثم سيتم بناء مكتبة BSP:



يوجد ملف عمل واحد فقط حتى الآن (تم إنشاؤه في Eclipse). أنا هنا إضافته:



في النافذة الأخيرة ، لا أغير أي شيء:



نحن نوافق على تنزيل ملف sof:



إذا قمنا فقط بتثبيت البرنامج ، فنتحول إلى وضع المصدر. سيتم تشغيله بالفعل (سأريكم كيف تبدو القائمة عندما يكون كل شيء قيد التشغيل بالفعل ، وسيكون هناك أيضًا عنصر لإدراجه).



لدي أبسط برنامج C:
 #include "sys/alt_stdio.h" int main() { alt_putstr("Hello from Nios II!\n"); volatile int i=0; i += 1; i += 2; i += 3; i += 4; i += 5; i += 6; i += 7; i += 8; i += 9; i += 10; i += 11; i += 12; /* Event loop never exits. */ while (1); return 0; } 

أحاول جمعها:



لقد حصلت على خطأ:
c: /intelfpga/17.1/nios2eds/bin/gnu/h-x86_64-mingw32/bin /../ lib / gcc / nios2-elf / 5.3.0 /../../../../ .. /H-x86_64-mingw32/nios2-elf/bin/ld.exe: المنطقة `Code 'التي فاضت عليها 15888 بايت

هذا لأنني لم أقم بإضافة SDRAM إلى النظام ، فقد حصرته في ذاكرة FPGA الداخلية. ولكن لماذا كان كل شيء مناسبا في الكسوف ، ولكن ليس هنا؟ لأنني اخترت BSP هناك مع لاحقة Small ، ولكن هنا تم صنع حزمة تلقائية بشكل تلقائي. لذلك ، افتح الملف: C: \ Work \ Play2 \ BSP \ settings.bsp

ونبدأ الضبط اليدوي.





إعادة بناء BSP:



ومرة أخرى نجمع المشروع. هذه المرة بنجاح. الآن قم بتحميله:



وأخيرا ، فإن التتبع الحقيقي


أنت لم تنسى لماذا أفعل كل هذا؟ أفعل هذا للبحث عن المفقودين. يجب تفعيلها. للقيام بذلك ، انتقل إلى علامة تبويب التتبع وحدد تمكين التتبع في قائمة السياق:



سوف أضع نقطة توقف في نهاية الوظيفة الرئيسية () في علامة تبويب Disassembly (كم هو لطيف أن يعتني مجمع RISC بتجميع مكدس الرهيب الذي يتم فيه تحويل كود Java!)

هنا بداية الوظيفة الرئيسية:



قم بالتمرير قليلاً ووضع نقطة توقف هنا:



نبدأ ، ننتظر التوقف ونذهب إلى علامة تبويب التتبع.

بشكل عام ، كل شيء ليس جيد جدا. في البداية ، كان من الواضح أن هناك نوعًا ما من التوقعات (كان لدينا استنتاج في JTAG هناك ، لذلك فهو شيء مشروع):



في النهاية - بعض الرموز الأخرى ... لكنني لا أرى رمز الوظيفة الرئيسية! هذه هي النهاية:



أنا لا أعرف حتى ما أقوله. لكن على أي حال ، إذا لم تضع واحدة ، ولكن نقطتي توقف (في بداية ونهاية الوظيفة الرئيسية) ، ثم بعد التشغيل من الأول إلى الثاني ، ستكون الصورة مناسبة:



استنتاجات موجزة


لذلك ، اكتشفنا أنه من الممكن معرفة كيفية عمل موقع معين. لذلك ، تم الكشف عن موضوع المقال ("... كيف وصل المعالج إلى هذه الحياة"). إنه أكثر إثارة للاهتمام كيف أن كل أولئك الذين كان يتعين حل مشاكلهم من أجل الحصول على نتيجة قد وصلوا إلى هذه الحياة؟ ومن المؤسف أنه حتى الآن لم أتمكن من تحديد عدد الأعمدة التي أنجزها فريق معين. من مقتطفات الوثائق ، من الواضح أن هذا يبدو ممكنًا تقنيًا ، ولكن البرنامج الذي سيسمح بذلك غير واضح. هناك رأي مفاده أن وثيقة تحليل وتصحيح التصميمات مع وحدة تحكم النظام ، والتي اضطررت إلى قراءتها عند تحليل البرنامج النصي tcl ، ستساعدنا. يحتوي هذا الجهاز على جهاز لوحي مثير للاهتمام. الجدول 10-15: أوامر تتبع النظام ، لكن شخصياً ، ليس لدي وقت لدراسة مفصلة لهذه المسألة. لكن ربما سيكون من الأهمية بمكان لشخص يقوم بتنفيذ كل شيء. يتم تضمين هذه الأوامر في البرامج النصية tcl.

حسنًا ، في المقالات التالية ، يجب إجراء القياسات بالطريقة القديمة ، باستخدام منظار الذبذبات.

Source: https://habr.com/ru/post/ar464795/


All Articles