الحقيقة الكاملة عن RTOS. المادة رقم 19. الإشارات: المقدمة والخدمات الأساسية



تم ذكر الإشارات في إحدى المقالات السابقة (رقم 5). مهمتهم الرئيسية هي التحكم في الوصول إلى الموارد.

المقالات السابقة في السلسلة:
المادة رقم 18. مجموعات علامات الأحداث: خدمات المساعدة وهياكل البيانات
المادة رقم 17. مجموعات علامة الحدث: المقدمة والخدمات الأساسية
المادة رقم 16. الإشارات
المادة رقم 15. أقسام الذاكرة: الخدمات وهياكل البيانات
المادة رقم 14. أقسام الذاكرة: المقدمة والخدمات الأساسية
المادة رقم 13. هياكل بيانات المهام ومكالمات API غير مدعومة
المادة رقم 12. خدمات للعمل مع المهام
المادة رقم 11. المهام: التكوين والمقدمة لواجهة برمجة التطبيقات
المادة رقم 10. المجدول: الميزات المتقدمة والحفاظ على السياق
المادة رقم 9. المجدول: التنفيذ
المادة رقم 8. Nucleus SE: التصميم الداخلي والنشر
المادة رقم 7. Nucleus SE: مقدمة
المادة رقم 6. خدمات RTOS الأخرى
المادة رقم 5. تفاعل المهام والمزامنة
المادة رقم 4. المهام وتبديل السياق والمقاطعات
المادة رقم 3. المهام والتخطيط
المادة رقم 2. RTOS: البنية ووضع الوقت الحقيقي
المادة رقم 1. RTOS: مقدمة.

باستخدام الإشارات


في Nucleus SE ، يتم تحديد الإشارات في مرحلة التجميع. يمكن أن يحتوي التطبيق على ما يصل إلى 16 إشارة. إذا لم يتم تحديد الإشارات ، لا يتم تضمين رمز مكالمات الخدمة وهياكل البيانات في التطبيق.

الإشارة عبارة عن عداد من النوع U8 ، يتم التحكم في الوصول إليه بطريقة يمكن استخدامها في العديد من المهام. يمكن أن تقلل المهمة من قيمة عداد الإشارة (الالتقاط) أو زيادتها (الإصدار). قد تؤدي محاولة التقاط إشارة مع قيمة صفر إلى حدوث خطأ أو تعليق مهمة ، اعتمادًا على معلمات استدعاء API المحددة وتكوين Nucleus SE.

إنشاء الإشارات


عدد الاشارة


كما هو الحال مع معظم كائنات Nucleus SE ، يتم تحديد إعداد الإشارات بواسطة توجيهات #define في nuse_config.h . المعلمة الرئيسية هي NUSE_SEMAPHORE_NUMBER ، والتي تحدد عدد الإشارات في التطبيق. بشكل افتراضي ، يتم تعيين المعلمة على 0 (لا تستخدم الإشارات في التطبيق) ويمكن أن تأخذ أي قيم حتى 16. ستؤدي القيمة غير الصحيحة إلى خطأ في الترجمة ، والذي سيتم إنشاؤه عن طريق التحقق في nuse_config_check.h (هذا الملف مضمن في nuse_config.c ، مما يعني أنه يجمع جنبا إلى جنب مع هذه الوحدة) ، ونتيجة لذلك ، سيتم توجيه # خطأ.

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

تنشيط مكالمات API


يتم تنشيط كل وظيفة API (استدعاء فائدة) في Nucleus SE بواسطة توجيه #define في nuse_config.h . بالنسبة إلى الإشارة ، تتضمن:

NUSE_SEMAPHORE_OBTAIN
NUSE_SEMAPHORE_RELEASE
NUSE_SEMAPHORE_RESET
NUSE_SEMAPHORE_INFORMATION
NUSE_SEMAPHORE_COUNT


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

ما يلي مقتطف من ملف nuse_config.h الافتراضي.

 #define NUSE_SEMAPHORE_NUMBER 0 /* Number of semaphores in the system - 0-16 */ #define NUSE_SEMAPHORE_OBTAIN FALSE /* Service call enabler */ #define NUSE_SEMAPHORE_RELEASE FALSE /* Service call enabler */ #define NUSE_SEMAPHORE_RESET FALSE /* Service call enabler */ #define NUSE_SEMAPHORE_INFORMATION FALSE /* Service call enabler */ #define NUSE_SEMAPHORE_COUNT FALSE /* Service call enabler */ 

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

مكالمات إشارة فائدة


يدعم Nucleus RTOS ثماني مكالمات خدمة توفر الوظائف التالية:

  • التقاط الإشارة. يتم تنفيذ Nucleus SE في دالة NUSE_Semaphore_Obtain () .
  • تحرير إشارة. في Nucleus SE ، يتم تنفيذه في دالة NUSE_Semaphore_Release () .
  • إعادة الإشارة إلى حالة غير مستخدمة مع تحرير جميع المهام المتوقفة مؤقتًا (إعادة التشغيل). يتم تنفيذ Nucleus SE في NUSE_Semaphore_Reset () .
  • توفير معلومات حول إشارة معينة. يتم تنفيذ Nucleus SE في NUSE_Semaphore_Information () .
  • إرجاع عدد الإشارات التي تم تكوينها في التطبيق. تم تنفيذ Nucleus SE في NUSE_Semaphore_Count () .
  • إضافة إشارة جديدة إلى التطبيق. لم يتم تنفيذ Nucleus SE.
  • إزالة الإشارة من التطبيق. لم يتم تنفيذ Nucleus SE.
  • إرجاع المؤشرات إلى كافة الإشارات. لم يتم تنفيذ Nucleus SE.

يتم وصف تنفيذ كل مكالمة خدمة بالتفصيل أدناه.

مكالمات المساعدة لالتقاط وإصدار الإشارات


العمليات الأساسية التي يمكن إجراؤها على الإشارات هي التقاط وإطلاق (انخفاض وزيادة القيمة). يوفر Nucleus RTOS و Nucleus SE مكالمتين أساسيتين لواجهة برمجة التطبيقات لهذه العمليات.

التقاط الإشارة


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

تحدي التقاط الإشارة في Nucleus RTOS
النموذج الأولي لمكالمة الخدمة:
STATUS NU_Obtain_Semaphore (إشارة NU_SEMAPHORE * ، غير معلقة) ؛

معلمات:

إشارة الإشارة - مؤشر إلى كتلة تحكم الإشارة التي يوفرها المستخدم ؛
الإيقاف - معلمة تعليق المهمة ، يمكن أن تأخذ القيم NU_NO_SUSPEND أو NU_SUSPEND ، بالإضافة إلى قيمة المهلة.

القيمة المعادة:

NU_SUCCESS - تم إكمال المكالمة بنجاح ؛
NU_UNAVAILABLE - الإشارة لها قيمة خالية ؛
NU_INVALID_SEMAPHORE - مؤشر غير صالح إلى إشارة ؛
NU_INVALID_SUSPEND - محاولة الإيقاف المؤقت من سلسلة محادثات لا تتعلق بالمهمة ؛
NU_SEMAPHORE_WAS_RESET - تم إعادة ضبط الإشارة بينما تم تعليق المهمة.

تحدي التقاط الإشارة في Nucleus SE
يدعم اتصال API هذا الوظائف الأساسية لـ Nucleus RTOS API.

النموذج الأولي لمكالمة الخدمة:

STATUS NUSE_Semaphore_Obtain (إشارة NUSE_SEMAPHORE ، تعليق U8) ؛

معلمات:

إشارة - فهرس (معرف) الإشارة المستخدمة ؛
الإيقاف - معلمة تعليق المهمة ، يمكن أن تكون NUSE_NO_SUSPEND أو NUSE_SUSPEND .

القيمة المعادة:

NUSE_SUCCESS - تم إكمال المكالمة بنجاح ؛
NUSE_UNAVAILABLE - الإشارة لها قيمة خالية ؛
NUSE_INVALID_SEMAPHORE - فهرس إشارة غير صالح ؛
NUSE_INVALID_SUSPEND - محاولة للتوقف مؤقتًا من سلسلة محادثات لا تتعلق بالمهمة أو عند تعطيل وظيفة حظر واجهة برمجة التطبيقات ؛
NUSE_SEMAPHORE_WAS_RESET - تم إعادة ضبط الإشارة بينما تم تعليق المهمة ؛

تنفيذ التقاط الإشارة في Nucleus SE
يتم تحديد إصدار رمز الوظيفة NUSE_Semaphore_Obtain () (بعد التحقق من المعلمات) باستخدام الترجمة الشرطية اعتمادًا على ما إذا كان دعم مهام الحظر (الإيقاف المؤقت) نشطًا أم لا. فكر في كلا الخيارين.

إذا لم يتم تنشيط القفل ، فإن منطق استدعاء API هذا بسيط جدًا:

 if (NUSE_Semaphore_Counter[semaphore] != 0) /* semaphore available */ { NUSE_Semaphore_Counter[semaphore]--; return_value = NUSE_SUCCESS; } else /* semaphore unavailable */ { return_value = NUSE_UNAVAILABLE; } 

يتم التحقق من قيمة عداد الإشارة ، وإذا لم تكن تساوي الصفر ، تنخفض.

إذا تم تنشيط تأمين المهام ، يصبح المنطق أكثر تعقيدًا:

 do { if (NUSE_Semaphore_Counter[semaphore] != 0) /* semaphore available */ { NUSE_Semaphore_Counter[semaphore]--; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } else /* semaphore unavailable */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_UNAVAILABLE; } else { /* block task */ NUSE_Semaphore_Blocking_Count[semaphore]++; NUSE_Suspend_Task(NUSE_Task_Active, semaphore << 4) | NUSE_SEMAPHORE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } } while (suspend == NUSE_SUSPEND); 

قد تكون بعض التوضيحات مفيدة.

يتم وضع الكود في حلقة do ... while ، والتي تعمل في حين أن معلمة الإيقاف المؤقت هي NUSE_SUSPEND .

إذا كانت الإشارة إشارة غير صفرية ، تنخفض. يتم تعيين متغير التوقف المرحلي إلى NUSE_NO_SUSPEND ، ويتم إنهاء استدعاء API وإرجاع NUSE_SUCESS .

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

الافراج سيمافور


استدعاء الأداة المساعدة لـ Nucleus RTOS API لتحرير إشارة المرور بسيط للغاية: تزداد قيمة عداد الإشارة وتعاد رسالة النجاح. يوفر Nucleus SE نفس الميزات ، ولكن مع فحص إضافي للتدفق.

تحدي لإطلاق الإشارات في Nucleus RTOS
النموذج الأولي لمكالمة الخدمة:

STATUS NU_Release_Semaphore (NU_SEMAPHORE * semaphore) ،

معلمات:

إشارة - إشارة إلى كتلة تحكم إشارة يوفرها المستخدم.

القيمة المعادة:

NU_SUCCESS - تم إكمال المكالمة بنجاح ؛
NU_INVALID_SEMAPHORE - مؤشر إشارة غير صالح .

تحدي لإطلاق إشارة في Nucleus SE
يدعم اتصال API هذا الوظائف الأساسية لـ Nucleus RTOS API.

النموذج الأولي لمكالمة الخدمة:

STATUS NUSE_Semaphore_Release (إشارة NUSE_SEMAPHORE) ؛

معلمات:

إشارة - فهرس (إشارة) الإشارة المحررة.

القيمة المعادة:

NUSE_SUCCESS - تم إكمال المكالمة بنجاح ؛
NUSE_INVALID_SEMAPHORE - فهرس إشارة غير صالح ؛
NUSE_UNAVAILABLE - إشارة الإشارة لها قيمة 255 ولا يمكن زيادتها.

تنفيذ إطلاق إشارة في Nucleus SE
رمز الوظيفة NUSE_Semaphore_Release () (بعد التحقق من المعلمات) شائع ، بغض النظر عما إذا كان قفل المهمة نشطًا أم لا. يتم التحقق من قيمة عداد الإشارة ، وإذا كانت أقل من 255 ، فإنها تزداد.

يتم تحديد رمز إضافي باستخدام الترجمة الشرطية إذا تم تنشيط دعم مكالمات حظر API (تعليق المهمة):

 NUSE_CS_Enter(); if (NUSE_Semaphore_Counter[semaphore] < 255) { NUSE_Semaphore_Counter[semaphore]++; return_value = NUSE_SUCCESS; #if NUSE_BLOCKING_ENABLE if (NUSE_Semaphore_Blocking_Count[semaphore] != 0) { U8 index; /* check whether a task is blocked */ /* on this semaphore */ NUSE_Semaphore_Blocking_Count[semaphore]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_SEMAPHORE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == semaphore)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } #endif } else { return_value = NUSE_UNAVAILABLE; } NUSE_CS_Exit(); return return_value; 

إذا تم تعليق أي مهام في هذه الإشارة ، يتم استئناف أولها.

تصف المقالة التالية مكالمات API الإضافية المرتبطة بالأشكال وبنى البيانات الخاصة بها.

نبذة عن الكاتب: يعمل Colin Walls في صناعة الإلكترونيات لأكثر من ثلاثين عامًا ، ويكرس معظم وقته للبرامج الثابتة. وهو الآن مهندس برامج ثابتة في Mentor Embedded (قسم من Mentor Graphics). غالبًا ما يتحدث كولين وولز في المؤتمرات والندوات ، مؤلف العديد من المقالات الفنية وكتابين عن البرامج الثابتة. يعيش في المملكة المتحدة. مدونة كولين المهنية ، البريد الإلكتروني: colin_walls@mentor.com.

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


All Articles