تصميم بنية تطبيق مدمجة



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

هذا سؤال قابل للنقاش! لذلك ، يعرضون مشاركة رؤيتهم في التعليقات!
بادئ ذي بدء ، سنحدد المجال: في إطار هذه المقالة ، من خلال التطوير المضمن ، نعني تطوير البرامج للمتحكم الدقيق (المشار إليها فيما يلي باسم MK ، على سبيل المثال STM32) في C / Asm.
يمكن تقسيم مشاريع الأنظمة القائمة على MK بشكل مشروط إلى تلك التي لا تتطلب وتتطلب تعدد المهام. أما بالنسبة للحلول من النوع الأول ، فهي عادة ليست معقدة للغاية (من وجهة نظر هيكلية). على سبيل المثال ، لا يتطلب مشروع بسيط ، حيث من الضروري قراءة البيانات من المستشعر وعرضه على الشاشة ، تعدد المهام ، وهو ما يكفي لتنفيذ التنفيذ المتسلسل للعمليات المذكورة أعلاه.



إذا كان التطبيق أكثر تعقيدًا: في إطاره من الضروري قراءة البيانات من كل من أجهزة الاستشعار الرقمية والتناظرية ، وحفظ القيم التي تم الحصول عليها في الذاكرة (على سبيل المثال ، على بطاقة SD) ، والحفاظ على واجهة المستخدم (عرض + لوحة مفاتيح) ، وتوفير الوصول إلى البيانات من خلال واجهة رقمية (على سبيل المثال ، RS-485 / Modbus أو Ethernet / TCP / IP) وتتفاعل بأسرع وقت ممكن مع أحداث معينة في النظام (الضغط على أزرار الطوارئ ، وما إلى ذلك) ، ثم في هذه الحالة سيكون من الصعب القيام بذلك بدون تعدد المهام. هناك طريقتان لحل مشكلة تعدد المهام: لتنفيذها بنفسك ، أو استخدام نوع من نظام التشغيل (يشار إليه فيما بعد باسم نظام التشغيل). اليوم ، أحد أنظمة التشغيل الأكثر شيوعًا في الوقت الفعلي للأنظمة المضمنة هو FreeRTOS.

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

قمنا بتعيين المهمة بشكل أكثر وضوحًا ، حتى إذا كان من الضروري في إطار تطبيقنا:

  • قراءة البيانات من أجهزة الاستشعار على RS-485 / Modbus.
  • قراءة البيانات من أجهزة الاستشعار في ناقل I2C.
  • قراءة البيانات من المدخلات الرقمية.
  • التحكم في خرج التتابع.
  • الحفاظ على واجهة المستخدم (عرض + لوحة مفاتيح).
  • توفير الوصول إلى البيانات عبر RS-485 / Modbus.
  • حفظ البيانات في الوسائط الخارجية.

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

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

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

لنبدأ في تصميم بنية تطبيقنا!

قاعدة بيانات الوقت الحقيقي




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



العمل مع أجهزة الاستشعار على الإطارات


يتضمن العمل باستخدام المستشعرات ما يلي:

  • قراءة البيانات
  • معالجة البيانات (إذا لزم الأمر) ، والتي تشمل:
    • التحقق من الصحة ؛
    • التحجيم
    • التصفية
    • التحقق من صحة القيم ؛

  • تسجيل البيانات المستلمة في RTDB.

كل هذا العمل يمكن القيام به في مهمة واحدة.



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

"RTDB" هي قاعدة بيانات الوقت الحقيقي الموضحة أعلاه في القسم المقابل.
نقش "Pr: 1" على المهمة يعني الأولوية ، والنهاية هي أن كل مهمة يمكن أن يكون لها أولوية إذا كانت هناك مهمتان تنتظران وقت المعالج لهما أولويات مختلفة ، فإن المورد سوف يتلقى المورد ذو الأولوية الأعلى. إذا كانت المهام لها نفس الأولوية ، فسيتم تشغيل المهمة ذات وقت الانتظار الأطول.

العمل مع المدخلات المنفصلة


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



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

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



كتابة البيانات لوسائل الإعلام الخارجية


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



نقرأ من "RTDB" ونكتب من خلال "برنامج تشغيل المتجر" إلى وسيط خارجي - يمكن أن يكون بطاقة SD أو محرك أقراص USB محمول أو أي شيء آخر. مرة أخرى ، لا تنس أن تضع أغلفة mutex (أو أي أدوات أخرى لتنظيم الوصول إلى المورد) في وظائف الواجهة!

توفير الوصول إلى البيانات في الوقت الحقيقي


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



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

العمل مع واجهة المستخدم


يتضمن العمل مع واجهة المستخدم تحديث البيانات على الشاشة والعمل باستخدام لوحة المفاتيح. قد تبدو هندسة هذا النظام الفرعي مثل هذا.



عامل واجهة المستخدم مسؤول عن قراءة ضغطات المفاتيح ، وأخذ البيانات من "RTDB" وتحديث العرض الذي يراه المستخدم.

هيكل النظام العام


الآن نلقي نظرة على ما حدث في النهاية.



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

ملاحظة
بصفتي أدبًا ، أوصي بـ "إنشاء أنظمة مدمجة: أنماط تصميم لبرامج رائعة" Elecia White ومقالات كتبها Andrey Kournits "FreeRTOS - نظام تشغيل للمتحكم الدقيق"

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


All Articles