إعادة توجيه printf () من STM32 إلى Qt Creator Console

kdpv.svg


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


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



إن عملية الاستضافة بطيئة إلى حد ما ، ترتبط RTT بحلول الأجهزة والبرامج Segger * ، USB ليس في كل متحكم. لذلك ، عادةً ، أفضل الأخيرين - استخدام UART و ITM. عنهم وسيتم مناقشتها أدناه.


* التحديث. - في الواقع ، كما هو مقترح في التعليقات ، هذا ليس كذلك. هناك خيارات في كل من البرنامج والأجهزة. لذلك ، من بين الطرق المذكورة أعلاه ، ستكون RTT هي الأكثر عالمية.


وعلى الفور بعض التفسير على البرنامج الذي سيتم استخدامه بعد ذلك. كوني نظام تشغيل ، لدي الآن Fedora 28 ، والحزمة الحالية من البرامج للعمل مع ميكروكنترولر هي:



إعادة توجيه printf () في دول مجلس التعاون الخليجي


لذلك ، من أجل إعادة توجيه إخراج printf () في GCC ، تحتاج إلى إضافة مفاتيح رابط


-specs=nosys.specs -specs=nano.specs 

إذا كنت بحاجة إلى عرض أرقام الفاصلة العائمة ، فأنت بحاجة إلى تذكر المفتاح


 -u_printf_float 

وتنفيذ وظيفة _write (). على سبيل المثال ، شيء من هذا القبيل


 int _write(int fd, char* ptr, int len) { (void)fd; int i = 0; while (ptr[i] && (i < len)) { retarget_put_char((int)ptr[i]); if (ptr[i] == '\n') { retarget_put_char((int)'\r'); } i++; } return len; } 

حيث retarget_put_char () هي وظيفة ستحمل الحرف مباشرة إلى الواجهة المطلوبة.


printf () -> ITM -> Qt Creator


تعد أداة تتبع Macrocell (ITM) عبارة عن كتلة داخل مجموعة Cortex-M3 / M4 / M7 الأساسية المستخدمة لإخراج (تتبع) أنواع مختلفة من المعلومات التشخيصية. لتنفيذ printf () حول ITM ، تحتاج إلى معرفة ما يلي:


  • يستخدم ساعة TRACECLKIN ، التي يساوي ترددها عادة التردد الأساسي
  • لديه 32 قطعة من منافذ التحفيز ما يسمى لإخراج البيانات
  • تتضمن CMSIS وظيفة ITM_SendChar () ، والتي تقوم بتحميل رمز في منفذ التحفيز 0
  • يتم إخراج البيانات إما من خلال ناقل متزامن (TRACEDATA ، TRACECLK) أو عبر خط SWO أحادي الأسلاك غير متزامن (TRACESWO)
  • عادة ما يتم مضاعفة خط SWO مع JTDO ، مما يعني أنه يعمل فقط في وضع التصحيح بواسطة SWD
  • يتم السحب بواسطة SWO إما باستخدام رمز مانشستر أو NRZ (UART 8N1)
  • يتم نقل البيانات في إطارات بتنسيق معين - تحتاج إلى محلل على جانب الاستقبال
  • عادةً ما يتم تكوين ITM من IDE أو الأداة المساعدة المقابلة (ومع ذلك ، لا أحد يحظر إعداده في رمز البرنامج - ثم سيعمل الإخراج إلى SWO دون جلسة تصحيح أخطاء مرفوعة)

إن الطريقة الأكثر ملاءمة لاستخدام ITM هي الإخراج عبر SWO باستخدام ترميز NRZ - وبالتالي ، فأنت بحاجة إلى سطر واحد فقط ، وسيكون من الممكن استلام البيانات ليس فقط باستخدام مصحح أخطاء مع إدخال خاص ، ولكن أيضًا بمحول USB-UART منتظم ، وإن كان ذلك بسرعة أقل.


تابعت المسار باستخدام مصحح أخطاء ، واضطررت إلى تعديل الصينية STLink-V2 لدعم SWO. ثم أصبح كل شيء بسيطًا - فنحن نقوم بتوصيل متحكم JTDO / TRACESWO بلوحة تصحيح الأخطاء المقابلة ، وننتقل إلى تهيئة البرنامج.


يحتوي Openocd على الأمر "tpiu config" - حيث يمكنك تكوين طريقة عرض معلومات التتبع (بمزيد من التفاصيل في دليل مستخدم OpenOCD ). لذلك على سبيل المثال باستخدام الحجج


 tpiu config internal /home/esynr3z/itm.fifo uart off 168000000 

سيقوم بتكوين الإخراج إلى ملف / home/esynr3z/itm.fifo ، واستخدام تشفير NRZ ، وحساب معدل النقل الأقصى بناءً على تردد TRACECLKIN البالغ 168 MHz - بالنسبة STLink فهو 2 MHz. وفريق آخر


 itm port 0 1 

سيمكن منفذ الصفر لنقل البيانات.


تتضمن شفرة المصدر OpenOCD الأداة المساعدة itmdump (مساهمة / itmdump.c) - حيث يمكنك تحليل السلاسل من البيانات المستلمة.


لتجميع ندخل


 gcc itmdump.c -o itmdump 

عند بدء التشغيل ، حدد الملف / pipe / ttyUSB * الضروري ومفتاح التبديل -d1 لعرض وحدات بايت البيانات المستلمة كسلسلة


 ./itmdump -f /home/esynr3z/itm.fifo -d1 

وآخر واحد. لإرسال حرف عبر SWO ، نقوم باستكمال _write () ، الموضح أعلاه ، بوظيفة


 int retarget_put_char(int ch) { ITM_SendChar((uint32_t)ch); return 0; } 

لذلك ، فإن الخطة العامة هي: داخل Qt Creator ، نقوم بتكوين openocd لحفظ جميع المعلومات التي تم تلقيها على SWO إلى توجيه إخراج مسمى تم إنشاؤه مسبقًا ، ويمكننا قراءة خطوط توجيه الإخراج وتحليلها وعرضها باستخدام itmdump قيد التشغيل كأداة خارجية. بالطبع ، هناك طريقة أكثر أناقة لحل المشكلة - لكتابة المكون الإضافي المناسب لـ Qt Creator. ومع ذلك ، آمل أن يكون النهج الموضح أدناه مفيدًا لشخص ما.


انتقل إلى إعدادات Bare Metal plugin (أدوات-> خيارات-> أجهزة-> Bare Metal).


config_baremetal.png


حدد خادم GDB المستخدم وأضف أوامر تهيئة السطر إلى نهاية القائمة


 monitor tpiu config internal /home/esynr3z/itm.fifo uart off 168000000 monitor itm port 0 1 

الآن ، قبل أن يضع المصحح المؤشر في بداية main () ، سيتم تكوين ITM.


أضف itmdump كأداة خارجية (أدوات-> خارجية-> تكوين ...).


external_itmdump.png


لا تنسى ضبط المتغير


 QT_LOGGING_TO_CONSOLE=1 

لعرض إخراج الأداة المساعدة على وحدة التحكم Qt Creator (اللوحة 7 رسائل عامة).


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


بعد إجراء بحث قصير ، تبين أنه يجب تخزين الأسطر الموجودة في itmdump وعرضها في stderr - ثم تظهر في وحدة التحكم بشكل تفاعلي ، أثناء تصحيح البرنامج. لقد قمت بتحميل نسخة معدلة من itmdump إلى GitHub .


هناك واحد أكثر تحذير. سيتم تعليق التصحيح عند بدء التشغيل على تنفيذ الأمر "monitor tpiu config ..." إذا لم يتم تشغيل itmdump مسبقًا. يحدث هذا بسبب حظر فتح الأنبوب (/home/esynr3z/itm.fifo) داخل openocd للكتابة ، وسوف يتعطل المصحح حتى يتم فتح توجيه الإخراج للقراءة من الطرف الآخر.


هذا غير سار إلى حد ما ، خاصة إذا لم تكن هناك حاجة إلى ITM في وقت ما ، ولكن يجب عليك تشغيله بشكل خاطئ ، إما أن تقوم دائمًا بتبديل خادم GDB أو حذف / إضافة خطوط في إعداداته. لذلك ، اضطررت إلى حفر بعض مصادر openocd والعثور على المكان الذي تحتاج إلى استبدال عكاز صغير.


في الملف src / target / armv7m_trace.c ، يوجد خط مع إجراء الفتح المطلوب


 armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab"); 

يحتاج إلى استبداله


 int fd = open(CMD_ARGV[cmd_idx], O_CREAT | O_RDWR, 0664); armv7m->trace_config.trace_file = fdopen(fd, "ab"); 

الآن سيتم فتح أنبوبنا على الفور ولن يلمع. لذلك يمكنك ترك إعدادات Bare Metal بمفردها ، ولا يعمل إلا عند الضرورة.


نتيجة لذلك ، يبدو إخراج الرسائل أثناء تصحيح الأخطاء بهذا الشكل


debug.png


printf () -> UART -> Qt Creator


في هذه الحالة ، كل شيء هو نفسه تقريبا:


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

أنا رسمت مثل هذه الأداة في C - uartdump . الاستخدام بسيط للغاية - تحتاج فقط إلى تحديد اسم المنفذ والبودرات.


external_uartdump.png


ومع ذلك ، تجدر الإشارة إلى ميزة واحدة. لا تعتمد هذه الأداة المساعدة على تصحيح الأخطاء ، ولا يقدم Qt Creator أي خيارات لإغلاق الأدوات الخارجية قيد التشغيل. لذلك ، لإيقاف قراءة منفذ COM ، أضفت أداة خارجية أخرى.


external_uartdump_close.png


حسنًا ، فقط في حالة ، سيتم إرفاق ارتباط بقالب CMake للمشروع الذي ظهر على لقطات - GitHub .

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


All Articles