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

بالنسبة للكثيرين ، فإن أسلوب البرمجة MK المألوف هو ما يسمى
supercycle . في هذه الحالة ، يتكون الكود من مجموعة من الوظائف والإجراءات والأوصاف (الثوابت والمتغيرات) ، وربما تلك الخاصة بالمكتبات ، والتي تُعرف عمومًا باسم "رمز الخلفية" ، بالإضافة إلى حلقة لا نهائية كبيرة محاطة ببنية
do-loop . عند بدء التشغيل ، تتم تهيئة معدات MK نفسها والأجهزة الخارجية أولاً ، ويتم تعيين الثوابت والقيم الأولية للمتغيرات ، ثم يتم نقل التحكم إلى هذه الدراجة الفائقة اللانهائية.
بساطة supercycle واضحة. معظم المهام التي يؤديها MK ، لأن بطريقة أو بأخرى دورية. العيوب واضحة أيضًا: إذا كان بعض الأجهزة أو الإشارات يتطلب رد فعل فوري ، فستوفر MK ذلك في وقت لا يتجاوز الدورة. إذا كانت مدة الإشارة أقصر من فترة الدورة ، فسيتم تخطي هذه الإشارة.
في المثال أدناه ، نريد التحقق مما إذا كان الزر
مضغوطًا :
do
من الواضح ، إذا كان "بعض الكود" يعمل لفترة كافية ، فقد لا تلاحظ MK ضغطًا سريعًا على زر.
لحسن الحظ ، تم تجهيز MK بنظام مقاطعة يمكن أن يحل هذه المشكلة: يمكن تعليق جميع الإشارات الهامة على المقاطعات ويمكن كتابة معالج لكل منها. لذلك يظهر المستوى التالي: دورة
سوبر مع انقطاع .
يوضح المثال التالي بنية البرنامج باستخدام supercycle ومقاطعة تعالج بنقرة زر واحدة:
on button button_isr
ومع ذلك ، فإن استخدام المقاطعات يمثل مشكلة جديدة: يجب أن يكون رمز معالج المقاطعة بأسرع وأقصر وقت ممكن ؛ داخل الانقطاعات ، وظائف MK محدودة. نظرًا لعدم وجود أجهزة مقاطعة للتسلسل الهرمي AVR ، لا يمكن أن تحدث مقاطعة أخرى داخل المقاطعة - إنها أجهزة معطلة في الوقت الحالي. لذلك يجب تنفيذ المقاطعة في أسرع وقت ممكن ، وإلا سيتم تخطي المقاطعات الأخرى (وربما الأكثر أهمية) ولن تتم معالجتها.
مقاطعة الذاكرةفي الواقع ، بكون MK داخل المقاطعة ، يمكن لـ MK ملاحظة حقيقة مقاطعة أخرى في سجل خاص ، مما يسمح بمعالجتها لاحقًا. ومع ذلك ، لا يمكن معالجة هذا المقاطعة على الفور.
لذلك ، لا يمكننا كتابة شيء معقد في معالج المقاطعة ، خاصةً إذا كان يجب أن يكون لهذا الرمز تأخير - لأنه حتى يعمل التأخير ، لن يعود MK إلى البرنامج الرئيسي (supercycle) وسيصمم إلى المقاطعات الأخرى.
لهذا السبب ، غالبًا ما يتعين عليك داخل معالج المقاطعة الإبلاغ عن حقيقة الحدث بعلامة - علامتك الخاصة بكل حدث - ثم التحقق من الإشارات داخل الدورة الفائقة ومعالجتها. هذا ، بالطبع ، يطيل زمن رد الفعل على الحدث ، لكننا على الأقل لا نفوت شيئًا مهمًا.
وبالتالي ، فإن المستوى التالي من التعقيد ينشأ - دورة
دراجة نارية كبيرة مع المقاطعات والأعلام .
يظهر الكود التالي:
on button button_isr
يقتصر هذا عدد كبير من البرامج MK. ومع ذلك ، فإن مثل هذه البرامج عادة ما تكون بسيطة إلى حد ما. إذا كتبت شيئًا أكثر تعقيدًا ، فإن عدد الأعلام يبدأ في النمو مثل كرة الثلج ، ويصبح الرمز أكثر حيرة وغير قابل للقراءة. بالإضافة إلى ذلك ، في المثال أعلاه ، لم يتم حل مشكلة التأخير. بالطبع ، يمكنك "تعليق" مقاطعة منفصلة على المؤقت ، وفيها ... يمكنك أيضًا التحكم في أعلام مختلفة. لكن هذا يجعل البرنامج قبيحًا تمامًا ، حيث يتزايد عدد الأعلام المترابطة بشكل كبير ، وحتى المطور نفسه بالكاد يستطيع معرفة مثل "رمز المعكرونة" قريبًا. محاولة العثور على خطأ أو تعديل الرمز غالبًا ما تصبح متساوية في الجهود المبذولة لتطوير مشروع جديد.
كيفية حل مشكلة "رمز المعكرونة" وجعلها أكثر قابلية للقراءة وإدارتها؟ يأتي
نظام التشغيل (OS) في عملية الإنقاذ. في ذلك ، يتم تقسيم الوظيفة التي يجب أن تنفذها MK إلى مهام يتم التحكم في تشغيلها بواسطة نظام التشغيل.
أنواع أنظمة التشغيل لـ MK
يمكن تقسيم أنظمة التشغيل لـ MK إلى فئتين كبيرتين: نظام التشغيل المزدحم مع نظام التشغيل التعاوني. في أي من أنظمة التشغيل هذه ، يتم التحكم في المهام بواسطة إجراء خاص يسمى
المرسل . في نظام التشغيل
المزدحم ، يقوم المرسل بتبديل التنفيذ في أي وقت من مهمة إلى أخرى ، مع تخصيص كل عدد معين من دورات الساعة (ربما تكون مختلفة ، اعتمادًا على أولوية المهمة). تعمل هذه الطريقة ككل بشكل رائع ، حيث تتيح لك عدم إلقاء نظرة على محتوى المهام على الإطلاق: يمكنك كتابة رمز المهمة على الأقل
1: goto 1
- ولا يزال سيتم تنفيذ بقية المهام (بما في ذلك هذه المهمة). ومع ذلك ، تتطلب أنظمة التشغيل الوقائية الكثير من الموارد (ذاكرة المعالج ودورات الساعة) ، لأن كل مفتاح يجب أن يحفظ سياق المهمة بالكامل ليتم تعطيله ويحمل سياق الاستئناف. يشير السياق هنا إلى محتويات سجلات الجهاز والمكدس (تستخدم BASCOM مجموعتين - الجهاز واحد لعناوين إرجاع البرامج الفرعية والبرنامج لتمرير الوسائط). لا يتطلب هذا الحمل الكثير من دورات المعالج فحسب ، بل يجب أيضًا تخزين سياق كل مهمة في مكان ما لفترة حتى تعمل. في المعالجات "الكبيرة" ، الموجهة في البداية إلى تعدد المهام ، غالبًا ما يتم دعم هذه الوظائف في الأجهزة ، ولديها المزيد من الموارد. في AVR MK ، لا يوجد دعم أجهزة للمهام المتعددة (كل شيء يجب القيام به "يدويًا") ، والذاكرة المتوفرة صغيرة. لذلك ، فإن إزاحة أنظمة التشغيل ، على الرغم من وجودها ، ليست مناسبة جدًا لأعضاء الكنيست البسيطة.
شيء آخر هو
OS التعاونية . هنا تتحكم المهمة نفسها عند نقطة نقل التحكم إلى المرسل ، مما يسمح له ببدء مهام أخرى. علاوة على ذلك ، فإن المهام هنا مطلوبة للقيام بذلك - وإلا فإن تنفيذ التعليمات البرمجية سوف يتعطل. من ناحية ، يبدو أن هذا النهج يقلل من الموثوقية الإجمالية: إذا تم تعليق المهمة ، فلن يتم استدعاء المرسل مطلقًا ، وسوف يتوقف النظام بالكامل عن الاستجابة. من ناحية أخرى ، لا يكون الرمز الخطي أو دورة الدراجات الفائقة أفضل في هذا الصدد - لأنه يمكن أن يتجمد بنفس المخاطر تمامًا.
ومع ذلك ، فإن نظام التشغيل التعاوني لديه ميزة مهمة. نظرًا لأن المبرمج هنا يضبط لحظة التبديل بنفسه ، لا يمكن أن يحدث ذلك فجأة ، على سبيل المثال ، في حين أن المهمة تعمل مع بعض الموارد أو في منتصف حساب تعبير حسابي. لذلك ، في نظام التشغيل التعاوني ، في معظم الحالات ، يمكنك الاستغناء عن الحفاظ على السياق. يعمل هذا على توفير الوقت والذاكرة للمعالج بشكل كبير ، وبالتالي يبدو أكثر ملاءمة للتنفيذ على MK AVR.
تبديل المهام في BASCOM AVR
من أجل تنفيذ تبديل المهام في بيئة BASCOM AVR ، يجب على رمز المهمة ، الذي يتم تطبيق كل إجراء كإجراء عادي ، استدعاء المرسل - في مكان ما أيضًا - كإجراء عادي.
تخيل أن لدينا مهمتين ، كل منها في مكان ما من الكود الخاص بها تسمى بواسطة المرسل.
sub task1() do
افترض أنه تم تنفيذ المهمة 1. لنرى ما يحدث على المكدس عندما ينفذ "مكالمة مرسل":
إرجاع العنوان إلى الرمز الرئيسي (2 بايت)
أعلى المكدس -> إرجاع عنوان المهمة 1 التي تسمى المرسل (2 بايت)
سوف يشير الجزء العلوي من الرصة إلى عنوان التعليمات في المهمة 1 ، والتي تتبع استدعاء المرسل (تعليمة
الحلقة في مثالنا).
الهدف من المرسل في أبسط الحالات هو نقل التحكم إلى المهمة 2. والسؤال هو كيف نفعل هذا؟ (لنفترض أن المرسل يعرف بالفعل عنوان المهمة 2).
للقيام بذلك ، يجب على المرسل سحب عنوان العودة إلى المهمة 1 من المكدس (ومن مكان ما للتذكر) ، ووضع عنوان المهمة 2 في هذا المكان على المكدس ، ثم إعطاء أمر الإرجاع. سيقوم المعالج باستخراج العنوان الموجود هناك من المكدس ، وبدلاً من العودة إلى المهمة 1 ، سينتقل إلى تنفيذ المهمة 2.
في المقابل ، عندما تستدعي المهمة 2 المرسل ، نقوم أيضًا بسحب المكدس وحفظ العنوان حيث سيكون من الممكن العودة إلى المهمة 2. وتحميل عنوان المهمة المحفوظة مسبقًا على المكدس. .
نتيجة لذلك ، حصلنا على مثل هذه الفوضى:
المهمة 1 -> المرسل -> المهمة 2 -> المرسل -> المهمة 1 ....
ليس سيئا! وهو يعمل. ولكن ، بالطبع ، هذا لا يكفي لنظام التشغيل الذي يمكن استخدامه عمليًا. بعد كل شيء ، لا ينبغي أن تعمل جميع المهام دائمًا وليس دائمًا - على سبيل المثال ، يمكن أن
تتوقع شيئًا ما (انتهاء وقت التأخير ، وظهور بعض الإشارات ، إلخ). لذلك ، يجب أن يكون للمهام
حالة (أعمال ، جاهزة ، متوقعة ، وما إلى ذلك). بالإضافة إلى ذلك ، سيكون من الجيد تعيين المهام
ذات الأولوية . ثم ، إذا كان هناك أكثر من مهمة جاهزة للتنفيذ ، فسيواصل المرسل المهمة ذات الأولوية العليا.
أكوا RTOS
لتنفيذ الفكرة الموضحة ، تم تطوير نظام OS AQUA RTOS التعاوني ، والذي يوفر الخدمات اللازمة للمهام ويسمح بتنفيذ المهام المتعددة التعاونية في بيئة BASCOM AVR.
ملاحظة مهمة بخصوص وضع الإجراءات في BASCOM AVRقبل البدء في وصف AUQA RTOS ، تجدر الإشارة إلى أن بيئة BASCOM AVR تدعم نوعين من إجراءات العنونة. هذا ينظمه config config = new | العمر.
في حالة تحديد الخيار القديم ، سيقوم المترجم ، أولاً ، بتجميع كافة التعليمات البرمجية بشكل خطي ، بغض النظر عما إذا كان يتم استخدامه في مكان ما أم لا ، وثانياً ، سيتم النظر إلى الإجراءات دون وسيطات مصممة في نمط اسم فرعي / نهاية فرعية كإجراءات ، نصب في اسلوب الاسم: / العودة. هذا يسمح لنا بتمرير عنوان الإجراء كتسمية كوسيطة إلى إجراء آخر باستخدام معدل bylabel. ينطبق هذا أيضًا على الإجراءات المصممة في نمط النمط الفرعي للاسم الفرعي / النهاية (تحتاج إلى تمرير اسم الإجراء كتسمية).
في الوقت نفسه ، يفرض الوضع الفرعي = الوضع القديم بعض القيود: يجب ألا تحتوي إجراءات المهمة على وسيطات ؛ يتم تضمين رمز الملفات المتصلة عبر $ include في المشروع العام خطيًا ، وبالتالي ، يجب توفير تجاوز في الملفات المتصلة - انتقل من البداية إلى النهاية باستخدام goto والتسمية.
وبالتالي ، في AQUA RTOS ، يجب على المستخدم إما استخدام تدوين الإجراء القديم فقط في أسلوب task_name: / return للمهام ، أو استخدام اسم فرعي / نهاية فرعي أكثر شيوعًا ، مضيفًا الفرعيود modifier = old في بداية الكود ، وتجاوز في الملفات المضمّنة غوتو تسمية / وتشمل رمز الملف / التسمية:.
حالات مهمة AQUA RTOS
يتم تعريف الحالات التالية للمهام في AQUA RTOS:
OSTS_UNDEFINE OSTS_READY OSTS_RUN OSTS_DELAY OSTS_STOP OSTS_WAIT OSTS_PAUSE OSTS_RESTART
إذا لم تتم تهيئة المهمة بعد ،
فسيتم تعيين الحالة
OSTS_UNDEFINE .
بعد التهيئة ، يكون للمهمة الحالة
OSTS_STOP .
إذا كانت المهمة
جاهزة للتنفيذ ،
فسيتم تعيين الحالة
OSTS_READY .
المهمة قيد التشغيل حاليًا لها الحالة
OSTS_RUN .
ومنه ، يمكنها الانتقال إلى الحالات
OSTS_STOP و OSTS_READY و OSTS_DELAY و OSTS_WAIT و OSTS_PAUSE .
الحالة
OSTS_DELAY لديها مهمة تفي
بالتأخير .
يتم تعيين الحالة
OSTS_WAIT إلى المهام التي
تنتظر إشارة أو حدث أو رسالة (المزيد عنها أدناه).
ما الفرق بين
حالات OSTS_STOP و
OSTS_PAUSED ؟
إذا تلقت المهمة حالة
OSTS_STOP لسبب ما ، فسيتم تنفيذ الاستئناف اللاحق للمهمة (عند استلام حالة
OSTS_READY ) من نقطة الدخول الخاصة بها ، أي من البداية. من حالة
OSTS_PAUSE ، ستستمر المهمة في العمل في المكان الذي تم تعليقه فيه.
إدارة حالة المهمة
يستطيع كل من نظام التشغيل نفسه إدارة المهام تلقائيًا وكذلك المستخدم من خلال الاتصال بخدمات نظام التشغيل. هناك العديد من خدمات إدارة المهام (تبدأ أسماء جميع خدمات نظام التشغيل بالبادئة
OS ):
OS_InitTask(task_label, task_prio) OS_Stop() OS_StopTask(task_label) OS_Pause() OS_PauseTask(task_label) OS_Resume() OS_ResumeTask(task_label) OS_Restart()
كل واحد منهم لديه خياران:
OS_service و
OS_serviceTask (باستثناء خدمة
OS_InitTask ، التي لديها خيار واحد فقط ؛ خدمة
OS_Init تهيئة نظام التشغيل نفسه).
ما هو الفرق بين
OS_service و
OS_serviceTask ؟ تعمل الطريقة الأولى على المهمة نفسها التي تسببت فيها ؛ يسمح لك الثاني بتعيين وسيطة مؤشر إلى مهمة أخرى ، وبالتالي ، إدارة أخرى من مهمة واحدة.
حول OS_Resumeجميع خدمات إدارة المهام ، باستثناء OS_Resume و OS_ResumeTask ، تستدعي مدير المهام تلقائيًا بعد المعالجة. في المقابل ، تقوم خدمات OS_Resume * بتعيين حالة المهمة فقط إلى OSTS_READY. ستتم معالجة هذه الحالة فقط عندما يتم استدعاء المرسل بشكل صريح.
قائمة انتظار المهمة والأولوية
كما ذكر أعلاه ، في نظام حقيقي ، قد تكون بعض المهام أكثر أهمية ، في حين أن المهام الأخرى قد تكون ثانوية. لذلك ، تتمثل إحدى الميزات المفيدة لنظام التشغيل في القدرة على تعيين أولوية المهام. في هذه الحالة ، إذا كان هناك العديد
من المهام
الجاهزة في نفس الوقت ، فسيقوم نظام التشغيل أولاً بتحديد المهمة ذات الأولوية العليا. إذا كانت
جميع المهام الجاهزة لها نفس الأولوية ، فسيقوم نظام التشغيل بوضعها في دائرة ، بترتيب يسمى "دائري" أو دائري.
في AQUA RTOS ، يتم تعيين الأولوية لمهمة عندما تتم
تهيئتها من خلال استدعاء خدمة
OS_InitTask ، التي
تتلقى عنوان المهمة كوسيطة أولى ورقم من 1 إلى 15. كوسيطة ثانية ،
والرقم الأدنى يعني أولوية أعلى . أثناء تشغيل نظام التشغيل ، لا يتم توفير تغيير في الأولوية المخصصة للمهمة.
تأخير
في كل مهمة ، تتم معالجة التأخير بشكل مستقل عن المهام الأخرى.
وبالتالي ، بينما يعمل نظام التشغيل على تأجيل مهمة واحدة ، يمكن تنفيذ مهام أخرى.
لتنظيم التأخير في تقديم الخدمات
OS_Delay | OS_DelayTask . الوسيطة هي عدد الميلي ثانية التي تم
تأخير المهمة. نظرًا لأن البعد الخاص
بالوسيطة dword ، فإن الحد الأقصى للتأخير هو 4294967295 مللي ثانية ، أو حوالي 120 ساعة ، وهو ما يبدو كافيًا لمعظم التطبيقات. بعد استدعاء خدمة التأخير ، يتم استدعاء المرسل تلقائيًا ، والذي ينقل التحكم إلى مهام أخرى طوال مدة التأخير.
الإشارات
الإشارات في AQUA RTOS تشبه الأعلام والمتغيرات المتاحة للمهام. هم من نوعين - ثنائي ويمكن عده. الأولى لها دولتان فقط: حرة ومغلقة. والثاني هو عداد البايت (خدمة عد الإشارات في الإصدار الحالي من AQUA RTOS لم يتم تنفيذها (أنا كسول الحمار) ، لذلك كل ما يقال أدناه ينطبق فقط على الإشارات الثنائية).
يتمثل الاختلاف بين الإشارة والإشارة البسيطة في أنه يمكن إجراء المهمة
لانتظار إصدار الإشارة المحددة. في بعض النواحي ، يشبه استخدام الإشارات فعليًا خط السكك الحديدية: عند الوصول إلى الإشارة ، ستتحقق التركيبة (المهمة) من الإشارة ، وإذا لم تكن مفتوحة ، فستنتظر إشارة التمكين لتظهر إلى أبعد من ذلك. في هذا الوقت ، يمكن أن تستمر القطارات (المهام) في التحرك (التشغيل).
في هذه الحالة ، يتم تعيين كل العمل الأسود إلى المرسل. بمجرد إخبار المهمة بانتظار الإشارة ، يتم نقل التحكم تلقائيًا إلى المرسل ، ويمكنه بدء مهام أخرى - تمامًا حتى يتم تحرير الإشارة المحددة. بمجرد أن تتغير حالة الإشارة إلى
مجاني ، يعيّن المرسل جميع المهام التي كانت تنتظر هذا الإشارة
جاهزة للحالة (
OSTS_READY ) ، وسيتم تنفيذها حسب ترتيب الأولوية والأولوية.
في المجموع ، يوفر AQUA RTOS 16 صورة ثنائية ثنائية (يمكن ، من حيث المبدأ ، زيادة هذا الرقم عن طريق تغيير بُعد المتغير في وحدة التحكم في المهمة ، لأنه يتم تطبيقه داخلياً كأعلام بت).
تعمل الإشارات الثنائية من خلال الخدمات التالية:
hBSem OS_CreateBSemaphore() OS_WaitBSemaphore(hBSem) OS_WaitBSemaphoreTask(task_label, hBSem) OS_BusyBSemaphore(hBSem) OS_FreeBSemaphore(hBSem)
قبل استخدام إشارة يجب
إنشاء . يتم ذلك عن طريق استدعاء خدمة
OS_CreateBSemaphore ، التي تُرجع مُعرّف البايت الفريد (مؤشر)
لإشارة hBSem المُنشأة ، أو من خلال المعالج المُعرَّف من قِبَل المستخدم ، يلقي خطأً
OSERR_BSEM_MAX_REACHED ، يشير إلى أنه قد تم الوصول إلى الحد الأقصى المسموح به
للإشارات الثنائية.
يمكنك العمل مع المعرف المستلم بتمريره كوسيطة إلى خدمات إشارة أخرى.
خدمة
OS_WaitBSemaphore | يضع
OS_WaitBSemaphoreTask المهمة (الحالية | المحددة) في حالة
انتظار إصدار إشارة hBSem إذا كانت
إشارة المرور هذه مشغولة ، ثم تنقل التحكم إلى المرسل بحيث يمكنه بدء مهام أخرى. إذا كانت الإشارة خالية ، فلن يحدث نقل التحكم ، وتستمر المهمة ببساطة.
تقوم
خدمات OS_BusyBSemaphore و
OS_FreeBSemaphore بتعيين إشارة
hBSem إلى
مشغول أو
مجاني ، على التوالي.
لم يتم توفير تدمير الإشارات من أجل تبسيط نظام التشغيل وتقليل مقدار الكود. وبالتالي ، فإن جميع الإشارات التي تم إنشاؤها ثابتة.
أحداث
بالإضافة إلى الإشارات ، يمكن أن تكون المهام مدفوعة بالحدث. يمكن توجيه مهمة واحدة
لتوقع حدث معين ، وقد تشير مهمة أخرى (وكذلك رمز الخلفية) إلى هذا الحدث. في الوقت نفسه ، ستتلقى جميع المهام التي كانت تنتظر هذا الحدث الحالة
جاهزة للتنفيذ (
OSTS_READY ) وسيتم تعيينها بواسطة المرسل للتنفيذ وفقًا للأولوية والأولوية.
ما الأحداث التي يمكن أن تستجيب لها المهمة؟ حسنًا ، على سبيل المثال:
- انقطاع؛
- حدوث خطأ.
- إصدار المورد (أحيانًا يكون أكثر ملاءمة لاستخدام إشارة لهذا) ؛
- تغيير حالة خط الإدخال / الإخراج أو الضغط على مفتاح على لوحة المفاتيح ؛
- تلقي أو إرسال شخصية عبر RS-232 ؛
- نقل المعلومات من جزء من التطبيق إلى آخر (انظر أيضا الرسائل).
يتم تطبيق نظام الفعاليات من خلال الخدمات التالية:
hEvent OS_CreateEvent() OS_WaitEvent(hEvent) OS_WaitEventTask(task_label, hEvent) OS_WaitEventTO(hEvent, dwTimeout) OS_SignalEvent(hEvent)
قبل استخدام الحدث ، تحتاج
إلى إنشائه . يتم ذلك عن طريق استدعاء وظيفة
OS_CreateEvent ، التي تُرجع معرف بايت فريد (مقبض) لحدث
hEvent ، أو ترمي خطأ
OSERR_EVENT_MAX_REACHED من خلال معالج المعرفة من قبل المستخدم ، مما يشير إلى أنه تم الوصول إلى الحد الأقصى لعدد الأحداث التي يمكن إنشاؤها في نظام التشغيل (بحد أقصى 255 أحداث مختلفة).
لجعل مهمة تنتظر حدث
hEvent ، اتصل
OS_WaitEvent في التعليمات البرمجية الخاصة به ، وتمرير مؤشر الحدث كوسيطة. بعد الاتصال بهذه الخدمة ، سيتم نقل التحكم تلقائيًا إلى المرسل.
بخلاف خدمة الإشارة ، توفر خدمة الحدث خيارًا لانتظار حدث مع
انتهاء مهلة . للقيام بذلك ، استخدم خدمة
OS_WaitEventTO . الوسيطة الثانية هنا يمكنك تحديد عدد المللي ثانية التي يمكن أن تتوقعها المهمة للحدث. في حالة انتهاء الوقت المحدد ، ستتلقى المهمة الحالة
جاهزة للتنفيذ كما لو كان الحدث قد وقع ، وسيتم تعيينها من قبل المرسل لمواصلة التنفيذ وفقًا للأولوية والأولوية. يمكن أن تكتشف المهمة أنه لم يكن حدثًا ، ولكن مهلة ، يمكن أن تتحقق المهمة عن طريق التحقق من علامة
OS_TIMEOUT العامة .
OS_SignalEvent , . , ,
, .
, : , – .
:
hTopic OS_CreateMessage() OS_WaitMessage(hTopic) OS_WaitMessageTask(task_label, hTopic) OS_WaitMessageTO(hTopic, dwTimeout) OS_SendMessage(hTopic, wMessage) word_ptr OS_GetMessage(hTopic) word_ptr OS_PeekMessage(hTopic) string OS_GetMessageString(hTopic) string OS_PeekMessageString(hTopic)
,
.
OS_CreateMessage ,
hTopic ,
OSERR_TOPIC_MAX_REACHED , , , .
hTopic ,
OS_WaitMessage , . . ,
hTopic .
OS_WaitMessageTO OS_WaitEventTO .
OS_SendMessage . , , –
word . ,
, , , .
, BASCOM
varptr , , :
strMessage = "Hello, world!" OS_SendMessage hTopic, varptr (strMessage)
OS_WaitMessage , , , , — . .
word , , , .
OS_GetMessage ,
OS_PeekMessage .
, ,
OS_GetMessageString OS_PeekMessageString , , , .
AQUA RTOS
TIMER0 . , ( ) . , .. . 1 .
AQUA RTOS
, .
OS_SIM = TRUE | FALSE , .
,
OS_MAX_TASK , . , ( ), . , .
, .AQUA RTOS .
OS_Init . . , – . , , – .
( ) – , . , - .
, AQUA RTOS :
OS_Init my_err_trap
, :
OS_InitTask task_1, 1 OS_InitTask task_2 , 1
, , Arduino Nano V3. - (, test), bas-:
D4 D5 Arduino ( , - ). 100...500
GND . . 2 0,66 .
. , ( , aliases), – , – .
«», « » (, – - , , ; ).
OS_ResumeTask .
, . ? , ! . , , ,
end .
. ,
do – loop . – , , – , .
OS_Delay . , .
OS_SIM = TRUE , , , .
, , , « », . , « », .
, (,
task_1 ), (
end )
task_1 , ,
return , – ,
task_1 (
do task_1 ).
task_1 , ,
OS_delay , , , .
, ,
task_1 ( ,
OS_delay , ..
loop ), , « », ,
task_2 .
task_2 (
do task_2 )
return , – ,
task_2 .
task_2 , ,
OS_delay , , , .
, ,
task_1 ( ,
OS_delay , ..
loop ), , « », ,
task_2 . ,
task_1 , , . (
loop task_1 ), .
task_1 loop , « 1 – – 2 – » .
.
:
task 1
task 2 is waiting messages…
task 1
task 1
task 1
task 1 is sending message to task 2
task 1
message recieved: Hello, task 2!
task 2 is waiting messages…
task 1
task 1
...
, . 1
task 1 , , . 2
task 2 is waiting messages... ,
hTopic , , 1.
task 1 . , , 2 , 1
incr , .
task_1_cnt 1 , , –
loop task 1 . , , 2 , . .
:
AQUA RTOS
, . ; , , . , : , 95…97°; (, GSM-), .
« + + » , . , .
:
- – ControlHeater()
- – ShowGoods()
- / – AcceptMoney()
- – ScanKeys()
- – MakeChange()
- – ReleaseCoffee()
- – Alarm()
.
ControlHeater() , . , , . . 5.
ShowGoods() . , - . 8, .
ScanKeys() , . 3, 40 .
AcceptMoney() . ,
ScanKeys(), 20 .
MakeChange () .
ReleaseCoffee() 10.
ReleaseCoffee() , . 2.
– ,
Alarm() – 1, , .
, . , EEPROM , .
RTOS : ( , ) – .
,
ReleaseCoffee() :
sub ReleaseCoffee() do OS_WaitMessage bCoffeeSelection wItem = OS_GetMessage(bCoffeeSelection) Release wItem loop end sub
ReleaseCoffee bCoffeeSelection , ( , ). ,
ReleaseCoffee() , , ( )
wItem OS_GetMessage .
ReleaseCoffee() , :
dim bCoffeeSelection as byte bCoffeeSelection = OS_CreateMessage()
,
ShowGoods() .
ReleaseCoffee() , . :
dim bGoodsReliased as byte bGoodsReliased = OS_CreateEvent()
ReleaseCoffee() Release wItem bGoodsReliased :
OS_SignalEvent bGoodsReliased
, , , , .
OS_Init :
OS_Init Mailfuncion
– , :
sub Mailfuncion (bCoffeeErr) print "Mailfunction! Error #: "; bCoffeeErr if isErrCritical (bCoffeeErr) = 1 then CallService(bCoffeeErr) end if end sub
( - : , GSM- ..), , , .
, , .. , . ,
OS_InitTask :
OS_InitTask ControlHeater , 5 OS_InitTask ShowGoods , 8 OS_InitTask AcceptMoney , 3 OS_InitTask ScanKeys , 3 OS_InitTask MakeChange, 10 OS_InitTask ReleaseCoffee , 2 OS_InitTask Alarm , 1
, , , , . . ,
OS_ResumeTask « »:
OS_ResumeTask ControlHeater OS_ResumeTask ShowGoods OS_ResumeTask AcceptMoney OS_ResumeTask ScanKeys OS_ResumeTask MakeChange OS_ResumeTask ReleaseCoffee OS_ResumeTask Alarm
, ; «» .
OS_ResumeTask ( ), . , , , .
, . :
OS_Sheduler
end – .
:
, , .
OS_SendMessage() , /. . , , , , .
AQUA RTOS
1.05Q: AQUA?A: , , « », , . , , , , « » WiFi-. , , , EEPROM , , - . . – « », , . , . AQUA.
Q: ?A: . , , , , , . , . , , , , , , -, . , . , - ( ? – ) . .