حول إساءة استخدام نظام التشغيل في مشاريع ميكروكنترولر

تتميز وحدات التحكم الدقيقة الحديثة بأداء عالٍ إلى حد ما وهذا يمنح العديد من المبرمجين الفرصة للتفكير في السياق التالي تقريبًا: - "لا بأس إذا ذهب 1-5٪ من الأداء إلى صيانة نظام التشغيل. لكن الكود الخاص بي سيتم تصحيحه بسهولة وصريح! " يتم دعم هذه الأفكار من خلال كمية كبيرة من الذاكرة غير المتطايرة (الفلاش) لتخزين رمز نظام التشغيل وذاكرة التشغيل (RAM / SRAM) لتخصيص مكدسها الخاص لكل مهمة. ومع ذلك ، في معظم الحالات هذه الفكرة خاطئة. وفي هذه المقالة سأخبرك لماذا.

حول المشاريع التي أعمل معها


في ممارستي ، غالباً ما يتعين علي العمل مع "مصمم". وصفت هذا النهج بالتفصيل في مقالتي السابقة حول استخدام C ++ في ميكروكنترولر . ثم لم أخبر الشيء الأكثر أهمية. ترتبط معظم "الكتل" الخاصة بـ "المُنشئ" بطريقة ما بنظام تشغيل في الوقت الفعلي. معظم "الكتل" لها تدفق خاص بها (المهمة ، من حيث نظام التشغيل في الوقت الحقيقي FreeRTOS المستخدم). وهذا ، في المتوسط ​​، يحتوي المشروع على حوالي 10-15 مهمة. في بعض الأحيان تصل هذه القيمة إلى 35-40.

أين كثيرا؟


فيما يلي قائمة قصيرة بالمهام التي تمت مواجهتها في كل مشروع:
  • صيانة ADC (تتم صيانة كل وحدة بواسطة تدفقها الخاص) ؛
  • wdt الصيانة (إذا تعطل نظام التشغيل ، فلن تتم إعادة تعيين المهمة وسيتم إعادة تشغيل الجهاز) ؛
  • العمل مع صفحات الإعدادات (يتحكم تيار منفصل في العمل باستخدام ذاكرة الفلاش) ؛
  • الحفاظ على بروتوكول التفاعل مع العالم الخارجي (المصب إلى الواجهة. على سبيل المثال ، uart) ؛

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

البساطة الواضحة


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

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

إساءة استخدام نظام التشغيل


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

تجاهل وظيفة الأجهزة متحكم


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

استخدام حلقة لا نهائية بدلاً من جهاز الحالة


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

تجاهل "جدولة الأجهزة"


العديد من microcontrollers اثنين وثلاثين بت لديها وحدة تحكم مقاطعة مدروس مع نظام أولوية للتخصيص. في حالة stm32f4 ، يكون له اسم NVIC ، ولديه القدرة على تحديد أولويات المقاطعة بـ 16 مستوى (دون التفكير في المستويات الفرعية).
يمكن كتابة معظم التطبيقات ضمن FreeRTOS التي تعين علي معالجتها كأجهزة حالة تسمى في المقاطعات ذات الأولويات التي تم تكوينها بشكل صحيح. وفي حالة عودة المعالج إلى "التنفيذ العادي" - انتقل إلى "النوم". في هذه الحالة ، لن تكون هناك حاجة لمنع الوصول إلى معظم الموارد (المتغيرات وغيرها). سوف تفقد التطبيقات مستوى إضافي من التجريد. وفي هذه الحالة - بعيدا عن الحر. ومع ذلك ، يتطلب هذا النهج التخطيط المعماري المدروس لكل مشروع. في المشروعات ، "المصممون" - جميع المقاطعات لها أولوية واحدة ، وفي الواقع ، هناك حاجة من أجل "تصفية" البيانات. ثم ضع البقايا في قائمة الانتظار ، حيث سيتم التقاطها من دفق الكائن للفئة المقابلة.

النتائج


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

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


All Articles