إلى مسألة منظمة الشفافية الدولية

"الآن سأريكم صورة ... هم ... أحذركم من أن هذه صورة ... على أي حال ، يرجى معاملته مثل صورة ...

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

والغرض من هذا التأليف ، بالإضافة إلى تبادل الخبرات المكتسبة ، هو محاولة لإثارة حسد صحي بين مصنعي MK المحليين ، الذين هم منافسين مباشرين لـ TI ("في البلد الذي نزدهر فيه") - المهمة ليست بالامتنان بصراحة ، لكنهم يقولون إن الأحجار تنخفض.

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

لذا ، ما الذي يعلمنا موقع TI الإلكتروني - لبدء العمل مع وحدات التقييم ، تحتاج إلى تنفيذ ثلاث خطوات ضرورية:

  1. شراء وحدات التقييم - القيام به.

    ملاحظة على الهوامش (PNP): سيتعين عليك أيضًا القيام بذلك ، لأنه في بيئة البرمجة المعنية لم أتمكن شخصيًا (للأسف) من العثور على القدرة على محاكاة الأجهزة لتصحيح الأخطاء ، على الأقل في المكان الذي كنت أبحث فيه.
  2. قم بتثبيت بيئة التطوير - قم بتنزيل وتشغيل برنامج التثبيت وكل شيء تم تنفيذه. نحن نربط وحدة التقييم بـ USB - الحطب يرتفع من تلقاء نفسه وكل شيء تم تنفيذه مرة أخرى - تم القيام به. عندما تحاول برمجة الجهاز ، نحصل على رسالة حول الحاجة إلى تحديث البرنامج الثابت ، ونحن نتفق مرة أخرى ، وقد تم تشغيل كل شيء. بشكل عام ، لا يوجد شيء يمكن الكتابة عنه إذا كان الأمر دائمًا وفي كل مكان ...
  3. اذهب ودراسة الدورة التدريبية TI SimpleLink Academy 3.10.01 لـ SimpleLink CC13x0 SDK 3.10 - اقتراح غريب ، يبدو لي أن أعلمني - فقط لكي أفسد ، ولكن فليكن الأمر كذلك ، أفتح الرابط المقابل وأذهل - كم عدد الأشياء المحشوة هنا.

هنا نرى مواد تدريبية حول العمل مع برامج تشغيل الأجهزة SYS / BIOS ومع نظام التشغيل TI-RTOS واستخدام مكدس شبكة NDK ، بما في ذلك USB ، واستخدام البروتوكولات اللاسلكية والعديد من جوانب العمل مع ممثلي مختلف عائلات MK التي تنتجها الشركة. وكل هذه الثروة مصحوبة بأمثلة جاهزة للاستخدام ، وإذا أخذنا في الاعتبار وجود أدلة المستخدم ووصف الوحدات ، فلن يكون هناك ما نرغب فيه. ولكن هناك أيضًا أدوات مساعدة تسهل عمل إعداد رمز البرنامج وتكوينه ، وامض وتصحيح الأخطاء بطرق مختلفة ، كما أن هذه الثروة موثقة تمامًا.

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

حسنًا ، حتى نؤجل دراسة المواد في وقت لاحق ، سوف نفهم كل شيء "على طول الطريق مع الكتلة" وفتح CCS بجرأة. وهي تنفذ مفهوم مساحات العمل ، المستلمة من الوالد - الكسوف. شخصيا ، مفهوم المشروع أقرب إلي ، لكن لا أحد يزعجنا أن نبقي بالضبط مشروعًا واحدًا في الفضاء ، لذلك دعنا ننتقل.

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

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

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

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

Pnp: لكنني وجدت خيارات لتمكين التحقق من توافق MISRA-C.

Pnp: هناك طريقة أخرى هي استخدام الأمر "تنظيف ..." مع التجميع اللاحق ، لا يؤثر الأمر "Build All" لسبب ما على المشروع المرتبط.

ثم نجد أنه لا يتم تصحيح كل شيء دائمًا بشكل طبيعي ، وأحيانًا نجد أنفسنا في مناطق من كود الآلة لا يجد المترجم مصدرها. نظرًا لأن بيئة البرمجة توفر لنا جميع الملفات اللازمة للعمل - نتيجة المعالج المسبق ورمز المجمّع وبطاقة رابط (تحتاج فقط إلى تذكر لتمكين الخيارات المقابلة) ، ننتقل إلى الأخير. نجد منطقتين من رمز البرنامج - بدءًا من 0x0000. وبدءا من 0x1000. (تصميمات 32-بت مفيدة للجميع ، لكن كتابة العنوان ليست وجهة نظرهم القوية). ننتقل إلى وثائق الدائرة المصغرة ونكتشف أن هناك مساحة ROM تم تعيينها على وجه التحديد إلى 0x1000. وهي تحتوي على جزء مضمن من المكتبات. يقال إن استخدام إجراءات منه يحسن الأداء ويقلل الاستهلاك مقارنة بمساحة عنوان 0x000. بينما نتقن MK ، نحن لسنا مهتمين بالمعلمات الأخيرة ، لكن راحة التصحيح أمر بالغ الأهمية. يمكنك تعطيل استخدام ROM (ولكن لأغراضنا) عن طريق تعيين خيار NO_ROM على المترجم ، الذي نقوم به وإعادة تجميع المشروع.

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

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

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

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

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

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

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

من المتوقع إلى حد كبير عملية تحديد معلمات المهمة قبل البدء:

  1. إنشاء بنية المعلمة (محلي ، بالطبع) ،
  2. تعطيه القيم الافتراضية ،
  3. تعيين المعلمات غير القياسية ، و
  4. استخدام الهيكل عند إنشاء المهمة.

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

PNP: في FREE-RTOS المعروفة ، يتم اتباع طريقة مختلفة قليلاً مع معلمات المهمة المشار إليها مباشرة في نص استدعاء API لوظيفة إنشاء المهمة. إيجابيات وسلبيات هذه النهج هي كما يلي:

  1. + يتيح لك عدم تحديد المعلمات التي تتطابق مع القيم الافتراضية بشكل صريح ، + لا يتطلب تذكر ترتيب المعلمات ، مطوّل أكثر ، تكاليف ذاكرة أكبر ، تحتاج إلى معرفة المعلمات الافتراضية ، -إنشاء كائن وسيط مسمى
  2. - يتطلب تحديد جميع المعلمات ، - يتطلب تذكر ترتيب المعلمات ، + أكثر إحكاما ، + يتطلب ذاكرة أقل ، + لا يتطلب كائنات وسيطة مسماة.

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

حسنًا ، هناك خيار رابع آخر ، خالٍ من أي عيوب ، ولكن يتطلب C ++ لا يقل عن 14 - نلعق شفاهنا ونتجاوز.

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

Pnp: نلاحظ ميزة أخرى للتصحيح ، حسناً ، هذا صحيح بالنسبة إلى أي بيئة تطوير - عندما نقوم بتبديل المهام باستخدام sheduler ، نفقد التركيز البؤري ، وسوف تساعدنا نقاط التوقف في حل هذه المشكلة.

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

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

  1. الكائن عالمي ، على الرغم من أنه يستخدم بواسطة الوظيفة الوحيدة لتهيئة المعلمات (في وقت واحد تكلف ممارسة مماثلة تويوتا مبلغًا لائقًا) - حسنًا ، إضافة التوجيه الثابت أمر سهل ؛
  2. كائن التحكم المسمى ، في C لا يوجد حل جميل لهذه المشكلة ، أو بالأحرى ، هناك حل مع نسخة مجهولة المصدر وأعطيته في فترة زمنية طويلة ، ولكن الكثير من الأقواس المناسبة لا تسمح بالاتصال بهذا الخيار الجميل حقًا ، في الإيجابيات هناك حل رائع الجمال ، ولكن ما لحلم حلم الأنابيب ؛
  3. جميع حقول الكائن متكررة بوضوح في عمق البتات ، حتى حقول البتات (تعداد قيمتين محتملتين) يتم تخزينها بكلمات 32 بت ؛
  4. يتم تعريف ثوابت الوضع الرقمي في شكل تعريفات ، مما يجعل من المستحيل التحقق في مرحلة التجميع وضروريًا في وقت التشغيل ؛
  5. تكرار قسم من حلقة لا نهائية في أماكن مختلفة من حالات الفشل المحتملة ، سيكون من الأصح بكثير جعل معالج واحد (في هذه الحالة فارغًا) ؛
  6. حسنًا ، يمكن (ويجب) إخفاء جميع عمليات إعداد المهمة وبدء تشغيلها في وظيفة واحدة أو حتى ماكرو.

لكن تهيئة مخزن التلقي المؤقت تمت بشكل جيد - نستخدم ذاكرة محجوزة مسبقًا ، لا معالجة للكوام ، سلسلة الاتصال معقدة إلى حد ما ، لكن كل شيء قابل للقراءة.

Pnp: في نافذة التصحيح ، أمام أعيننا ، مكدس الاستدعاءات ، يتم كل شيء كما ينبغي - وهو الاحترام والاحترام. الشيء الوحيد الذي يثير الدهشة إلى حد ما هو محاولة لإخفاء هذه النافذة يؤدي إلى نهاية جلسة تصحيح الأخطاء.

حسنًا ، وقرار آخر غير متوقع إلى حد ما - تعيين العدد المحتمل من الكائنات في التعداد ، للمنافذ التسلسلية ولوحة التصحيح هذه تساوي 1 ، في النمط

typedef enum CC1310_LAUNCHXL_UARTName { CC1310_LAUNCHXL_UART0 = 0, CC1310_LAUNCHXL_UARTCOUNT } CC1310_LAUNCHXL_UARTName; 

مثل هذه الحلول قياسية لعمليات النقل الحقيقية ، ولكن لوصف كائنات الأجهزة - ولم أكن أعرف أن هذا ممكن ، على الرغم من أنه يعمل بنفسي. لقد انتهينا من تهيئة الحديد ، دعنا ننتقل.

في مهمة جارية ، نلاحظ حلقة لا نهائية كلاسيكية حيث تتم قراءة البيانات من منفذ تسلسلي بواسطة الوظيفة
 UART_read(uart, &input, 1); 
وأرسلت على الفور من قبل وظيفة
 UART_write(uart, &input, 1); 
. دعنا نذهب إلى الأول ونرى محاولة لقراءة الأحرف من المخزن المؤقت للتلقي
 return (handle->fxnTablePtr->readPollingFxn(handle, buffer, size)) 
(كيف أكره مثل هذه الأشياء ، لكن في C يكون الأمر مستحيلًا على خلاف ذلك) ، فإننا نعمق ونجد أنفسنا في UARTCC26XX_read ، ومنه ندخل في تنفيذ المخزن المؤقت الحلقي - وظيفة
 RingBuf_get(&object->ringBuffer, &readIn) 
. هنا ، الحياة العادية تدخل مرحلة حادة.

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

1) يتم تنفيذ إعادة قراءة مؤشرات القراءة / الكتابة من خلال بقية القسم

 object->tail = (object->tail + 1) % object->length; 

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

Pnp: لقد رأيت مؤخرًا وصفًا للبنية M7 الجديدة في التنفيذ ولا أتذكر أي شخص ، لذلك لسبب ما ، بدأ تقسيم 32 على 32 في 2-12 دورة بدلاً من 2-7. إما أن يكون هذا خطأ في الترجمة ، أو ... لا أعرف حتى ما أفكر فيه.

2) علاوة على ذلك ، يتم تكرار جزء الشفرة هذا في أكثر من مكان واحد - وحدات الماكرو والسطرات الخاصة بـ wimps و ctrl + C و ctrl + V ، مبدأ DRY يمر عبر مجموعة التفرعات ،

3) تم تنفيذ عداد زائدة تمامًا عن أماكن التخزين المؤقت المملوءة ، مما استتبع العيب التالي ،

4) الأقسام الحاسمة في كل من القراءة والكتابة. حسنًا ، ما زلت أعتقد أن مؤلفي هذه الوحدة لا يقرؤون مشاركاتي على Habré (على الرغم من أن هذا السلوك غير مقبول للمهنيين في مجال البرامج الثابتة) ، لكن يجب أن يكونوا على دراية بكتاب Mustang ، فهناك هذه المشكلة يتم فحصها بالتفصيل ،

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

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

بشكل عام ، تتوافق تعليقاتي تمامًا مع السطر الأول من demotivator حول موضوع مراجعة الكود "10 سطور من الكود - 10 تعليقات."

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

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

دعنا ننتبه الآن إلى إرسال البيانات المستلمة إلى القناة التسلسلية ، لأنه عند إنشاء الكائن تم تزويده بذاكرة مؤقتة واحدة فقط - المستلم. في الواقع ، يتم استخدام المخزن المؤقت الداخلي للجهاز لنقل الأحرف ، وعند تعبئته ، يتم إدخال انتظار الاستعداد (على الأقل في وضع حظر التشغيل). لا أستطيع أن أساعد نفسي ، حتى لا ينتقد أسلوب الوظائف المقابلة: 1) لسبب ما ، الكائن يحتوي على مؤشر معمم ، والذي يتحول داخل الوظيفة باستمرار إلى مؤشر للأحرف
 *(unsigned char *)object->writeBuf); 
2) منطق العمل مبهم بالكامل ومربك قليلاً. لكن كل هذا ليس مهمًا جدًا ، لأنه لا يزال مخفيًا عن المستخدم و "لا يؤثر على السرعة القصوى".

في عملية البحث ، صادفنا ميزة أخرى - لا نرى الكود المصدري لبعض الوظائف الداخلية في وضع التصحيح - وهذا بسبب تغيير الأسماء لخيارات الترجمة المختلفة (ROM / NO_ROM). استبدال الملف المصدر المطلوب (C: \ Jenkins \ jobs \ FWGroup-DriverLib \ مساحة العمل \ الوحدات النمطية \ الإخراج \ cc13xx_cha_2_0_ext \ driverlib \ bin \ ccs /./../../../../../ driverlib / uart.c--) لم تنجح (لكنني لم أحاول بجد) ، على الرغم من أنني وجدت المصدر (بالطبع ، في الملف في ملف uart.c ، شكرًا ، نقيب) ، لحسن الحظ ، هذه الشريحة بسيطة ومن السهل التعرف على شفرة المجمّع مع الكود المصدري في C (خاصة إذا كنت تعرف ميزات فريق ITxxx). لا أعرف كيفية حل هذه المشكلة للمكتبات ذات الوظائف المعقدة ، وسنفكر عندما تنشأ الحاجة.

أخيرًا ، ملاحظة صغيرة - أنا على استعداد للاعتقاد بأن أجهزة تطبيق القناة التسلسلية لنماذج MK CC13x0 هي نفسها الخاصة بـ CC26x0 ، ولا يمكن استدعاء محتويات ملف يسمى UARTCC26XX.c --- بالحل الصحيح ، ولكن إنشاء ملف تعريف وسيط مع تضمين أرحب بالملف المصدر ، متغلبًا على الوظائف والتعليق المقابل ، لأن هذا سيجعل البرنامج أكثر قابلية للفهم ، ويجب أن يكون هذا دائمًا موضع ترحيب.

لذلك ، تعمل حالة الاختبار ، لقد تعلمنا الكثير عن البنية الداخلية للمكتبات القياسية ، ولاحظنا نقاط قوتها وليس جوانبها الجيدة ، في ختام المراجعة ، سنحاول إيجاد إجابة على السؤال الذي يهتم به المبرمج عادة في معضلة "OS or not OS" - وقت تبديل السياق. هناك طريقتان ممكنتان هنا: 1) النظر في الكود المصدري هو بالأحرى طريقة نظرية ، فهو يتطلب مستوى من الانغماس في الموضوع الذي لست مستعدًا لإظهاره ، و 2) تجربة عملية. بالطبع ، الطريقة الثانية ، على عكس الطريقة الأولى ، لا تعطي نتائج صحيحة تمامًا ، ولكن "الحقيقة دائمًا ملموسة" ويمكن اعتبار البيانات التي تم الحصول عليها كافية إذا تم تنظيم القياسات بشكل صحيح.

بادئ ذي بدء ، من أجل تقدير وقت التبديل ، نحتاج إلى معرفة كيفية تقييم وقت التنفيذ الكلي لشظايا البرنامج المختلفة. في هذه البنية ، هناك وحدة تصحيح الأخطاء ، جزء منها هو عداد النظام. يمكن الوصول إلى المعلومات حول هذه الوحدة تمامًا ، ولكن الشيطان ، كما هو الحال دائمًا ، يختبئ في التفاصيل. أولاً ، دعنا نحاول تكوين الوضع الضروري بالمقابض مباشرةً من خلال الوصول إلى السجلات. نجد بسرعة كتلة التسجيل CPU_DWT وفيها نجد كلاً من عداد CYCCNT نفسه وسجل التحكم الخاص به مع CTRL مع بت CYCCNTENA. بطبيعة الحال ، أو ، كما يقولون ، بطبيعة الحال ، لم يحدث شيء ، وموقع ARM لديه إجابة على السؤال لماذا - من الضروري تمكين وحدة تصحيح الأخطاء مع بت TRCENA في سجل DEMCR. لكن السجل الأخير ليس بهذه البساطة - في كتلة DWT ، ليس هناك ، في الكتل الأخرى ، من الأسوأ البحث - فهي طويلة جدًا ، لكنني لم أجد أي بحث بالاسم في نافذة التسجيل (لكن سيكون من الجيد الحصول عليها). نحن نذهب إلى نافذة الذاكرة ، وأدخل عنوان السجل (المعروف لنا من التاريخ) (بالمناسبة ، لأن التنسيق السداسي العشري للعنوان ليس افتراضيًا ، تحتاج إلى إضافة بادئة 0x مع الأقلام) ، وفجأة ، نرى خلية ذاكرة مسماة تحمل اسم CPU_CSC_DEMCR. من المضحك ، على أقل تقدير ، سبب إعادة تسمية الشركة للسجلات مقارنة بالأسماء التي اقترحها مرخص البنية ، ربما كان ذلك ضروريًا. وبالضبط ، في مجموعة سجلات CPU_CSC ، نجد السجل الخاص بنا ، ونضع البتة المطلوبة فيه ، ونرجع إلى العداد ، ونمكّنه ، ويعمل كل شيء.

Pnp: لا يزال هناك بحث بالاسم ، يطلق عليه (بشكل طبيعي) من خلال مجموعة Ctrl-F ، إنه موجود فقط في قائمة السياق ، لكن في المعتاد يتم إلغاؤه ، أعتذر للمطورين.

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

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

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

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

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

نبدأ التجربة ، الجزء الأول (فقط في انتظار وقت التنفيذ) أعطى البيانات عن نسبة العدادات 406181 / 58015 = 7 - من المتوقع تمامًا. يعطي الجزء الثاني (مع 10 أحرف متتالية لمدة 10 ثوانٍ تقريبًا) النتائج 351234k-50167k * 7 = 63k / 20 = 3160 دورة ، والرقم الأخير هو الوقت المرتبط بإجراءات تبديل السياق في دورات MK. شخصياً ، يبدو لي أن هذه القيمة أكبر من المتوقع ، فنحن نواصل البحث ، ويبدو أنه لا تزال هناك بعض الإجراءات التي تفسد الإحصاءات.

PNP: خطأ شائع لأحد مجرّفيه هو عدم تقييم النتائج المتوقعة سابقًا والإيمان بالقمامة المستلمة (مرحبًا بـ 737 مطورًا).

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

وإليكم نتائج عمليات التلاعب الصعبة هذه: نجعل المدخلات بواسطة الرزمة وتصبح القراد المفقودة أصغر - 2282 ، أوقف تشغيل الإنتاج وتهبط التكاليف إلى 1222 علامة - إنه أفضل ، رغم أنني كنت آمل في 300 علامة.

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

PNP: على أي حال ، كثيرًا - قمت بحساب الدورات في 100: 30 لحفظ السياق ، و 40 لتحديد المهمة المكتملة و 30 لاستعادة السياق ، لكننا حصلنا على ترتيب أكبر. على الرغم من أن التحسين قد تم إيقافه الآن ، فقم بتشغيل - o2 وشاهد النتيجة: لم يتغير كثيرًا - فقد أصبح 2894 بدلاً من 3160.

هناك فكرة أخرى - إذا كان نظام التشغيل يدعم مهام التبديل من نظير إلى نظير ، فيمكنك تشغيل مهمتين باستخدام عدادات ، والحصول بشكل سحري على بيانات حول عدد المحولات في فترة زمنية ، وحساب فقدان عداد النظام ، ولكن بسبب خصوصيات sheduler ، التي تتعلق بها سبق أن قلت ، فإن هذا النهج لن يؤدي إلى النجاح. على الرغم من إمكانية وجود خيار آخر ، وهو تنفيذ لعبة ping-pong بين مهمتين من نظير إلى نظير (أو حتى نظير إلى نظير) من خلال إشارة سريعة ، فمن السهل حساب عدد مفاتيح تبديل السياق هنا - سيكون عليك تجربتها ، ولكن سيكون غدًا.

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

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


All Articles