
تم ذكر أجزاء من الذاكرة في وقت سابق في إحدى المقالات السابقة (# 6) ، حيث تم إجراء مقارنة مع الوظيفة القياسية للغة C
malloc () . القسم هو منطقة من الذاكرة تم الحصول عليها من تجمع قسم (تجمع ذاكرة). توفر مشاركة الذاكرة طريقة مرنة لتخصيص وتحرير الذاكرة بشكل موثوق وحتمى.
المقالات السابقة في السلسلة:
المادة رقم 13. هياكل بيانات المهام ومكالمات API غير مدعومةالمادة رقم 12. خدمات للعمل مع المهامالمادة رقم 11. المهام: التكوين والمقدمة لواجهة برمجة التطبيقاتالمادة رقم 10. المجدول: الميزات المتقدمة والحفاظ على السياقالمادة رقم 9. المجدول: التنفيذالمادة رقم 8. Nucleus SE: التصميم الداخلي والنشرالمادة رقم 7. Nucleus SE: مقدمةالمادة رقم 6. خدمات RTOS الأخرىالمادة رقم 5. تفاعل المهام والمزامنةالمادة رقم 4. المهام وتبديل السياق والمقاطعاتالمادة رقم 3. المهام والتخطيطالمادة رقم 2. RTOS: البنية ووضع الوقت الحقيقي
المادة رقم 1. RTOS: مقدمة.
باستخدام الأقسام
في Nucleus SE ، يتم تكوين تجمعات الأقسام في وقت الإنشاء. يمكن أن يحتوي التطبيق الواحد على 16 تجمع أقسام. إذا لم يتم تكوينها ، فلن يتم تضمين هياكل البيانات ومكالمات الخدمة المتعلقة بهذه التجمعات في التطبيق.
تجمع الأقسام هو منطقة ذاكرة مقسمة إلى عدد معين من الكتل ذات الحجم الثابت. المطور يتحكم بشكل كامل في حجم وعدد الأقسام في كل تجمع. يمكن أن تطلب المهام أقسامًا مخصصة من الذاكرة وتتلقى مؤشرًا إلى منطقة التخزين ويجب ألا تكتب البيانات خارج القسم المخصص. يمكن تحرير مقطع بواسطة أي مهمة عند تمرير مؤشر إلى وظيفة API. قد يؤدي طلب تخصيص قسم عندما لا يكون هناك أقسام مجانية إلى حدوث خطأ أو تعليق الطلب ، اعتمادًا على معلمات استدعاء API المحددة وتكوين Nucleus SE.
إنشاء أقسام الذاكرة
عدد تجمعات القسم
كما هو الحال مع معظم كائنات Nucleus SE ، يتم تكوين تجمّع التقسيم بشكل أساسي باستخدام التوجيه
#define في
nuse_config.h . المعلمة الرئيسية هي
NUSE_PARTITION_POOL_NUMBER ، والتي تحدد عدد تجمعات الأقسام التي تم تعريفها في التطبيق. القيمة الافتراضية هي 0 (أي ، لا يتم استخدام تجمعات الأقسام) ، ويمكن للمطور تعيين أي قيمة من 0 إلى 16. ستؤدي القيم الأخرى إلى خطأ في
الترجمة ، تم اكتشافه أثناء التحقق في
nuse_config_check.h (تم تضمينه في
nuse_config.c ، و لذلك ، يتم تجميعها مع هذه الوحدة) ، مما يؤدي إلى تجميع التوجيه #
خطأ .
يعد اختيار قيمة غير صفرية طريقة ذات أولوية لتنشيط تجمعات الأقسام. وهذا يؤدي إلى تعريف هياكل البيانات وتخصيص الحجم المناسب. يجب تهيئة بنيات البيانات في ROM بالقيم المناسبة التي تصف كل تجمع قسم. مزيد من التفاصيل حول هياكل البيانات ستكون في المقالة التالية. يقوم هذا التحديد أيضًا بتنشيط إعدادات API.
تنشيط مكالمات API
يتم تنشيط كل وظيفة API (استدعاء فائدة) في Nucleus SE بواسطة توجيه
#define في
nuse_config.h . بالنسبة إلى تجمعات الأقسام ، تتضمن ما يلي:
NUSE_PARTITION_ALLOCATENUSE_PARTITION_DEALLOCATENUSE_PARTITION_POOL_INFORMATIONNUSE_PARTITION_POOL_COUNTبشكل افتراضي ، يتم
تعيينهم جميعًا على
FALSE ، وبالتالي تعطيل كل استدعاء خدمة ومنع تضمين رمز التنفيذ. لتكوين تجمعات الأقسام في التطبيق ، تحتاج إلى تحديد مكالمات API اللازمة وتعيين التوجيهات المقابلة إلى
TRUE .
ما يلي مقتطف من ملف
nuse_config.h الافتراضي:

إذا تم تنشيط وظيفة API تجمعات التقسيم ، ولكن لم يتم تكوين
التجمعات ، يحدث خطأ في
الترجمة ( باستثناء
NUSE_Partition_Pool_Count () ، الذي يتم تمكينه دائمًا). إذا كان الرمز الخاص بك يستخدم استدعاء API لم يتم تنشيطه ، فسيحدث خطأ تخطيط لأن رمز التنفيذ لم يتم تضمينه في التطبيق.
مكالمات فائدة تجمع التقسيم
يدعم Nucleus RTOS سبعة مكالمات مفيدة تتعلق بمجمعات الأقسام ، والتي توفر الوظائف التالية:
الوصف الوظيفي | Nucleus RTOS | Nucleus SE |
---|
اختيار القسم | NU_Allocate_Partition () | NUSE_Partition_Allocate () |
إصدار القسم | NU_Deallocate_Partition () | NUSE_Partition_Deallocate () |
توفير المعلومات حول تجمع قسم معين | NU_Partition_Pool_Information () | NUSE_Partition_Pool_Information () |
قم بإرجاع قيمة الكمية (الحالية) المكونة تجمعات التطبيقات | NU_Established_Partition_Pools () | NUSE_Partition_Pool_Count () |
إضافة (إنشاء) تجمع أقسام جديد إلى التطبيق | NU_Create_Partition_Pool () | لم ينفذ. |
تغيير (حذف) تجمع أقسام من تطبيق | NU_Delete_Partition_Pool () | لم ينفذ. |
إرجاع المؤشرات إلى كافة تجمعات الأقسام الموجودة حاليًا في التطبيق | NU_Partition_Pool_Pointers () | لم ينفذ. |
سيتم مناقشة تنفيذ كل مكالمة بالتفصيل.
من الجدير بالذكر أنه لا Nucleus RTOS ولا Nucleus SE لديهم وظيفة إعادة التشغيل. يتم ذلك عن قصد. في كثير من الأحيان ، تقوم إحدى المهام بتخصيص قسم وتمرير مؤشر إلى مهمة أخرى (والتي قد تحررها لاحقًا). إذا قمت بإعادة تحميل تجمع الأقسام ، فسيتم وضع علامة على جميع الأقسام على أنها غير مستخدمة ، ومع ذلك ، لا توجد آلية لرصد جميع المهام التي يمكنها استخدام الأقسام وإخطارها.
خدمات التقسيم والإفراج
العمليات الأساسية مع تجمعات الأقسام هي تخصيص الأقسام في التجمع (أي وضع علامة على القسم على أنه مستخدم وإعادة عنوانه) وإطلاق القسم (أي أن القسم مميز على أنه غير مستخدم). يوفر Nucleus RTOS و Nucleus SE مكالمتين أساسيتين لواجهة برمجة التطبيقات لهذه العمليات ، الموضحة أدناه.
اختيار القسم
تعد استدعاء Nucleus RTOS API لتخصيص قسم مرنًا للغاية ، مما يسمح للمطورين بإيقاف المهام مؤقتًا لفترة غير محددة من الوقت أو بدون مهلة إذا تعذر إكمال العملية على الفور ، على سبيل المثال ، عند محاولة تخصيص قسم من التجمع الذي يتم فيه توزيع جميع الأقسام بالفعل. يوفر Nucleus SE نفس الخدمة ، إلا أن إيقاف المهام مؤقتًا فيها اختياري ، ولم يتم تنفيذ المهلة.
استدعاء Nucleus RTOS API إلى القسم
استدعاء النموذج:
STATUS NU_Allocate_Partition (NU_PARTITION_POOL * pool، VOID ** return_pointer، UNSIGNED suspend)؛القيمة المعادة:
NU_SUCCESS - تم إكمال المكالمة بنجاح ؛
NU_NO_PARTITION - لا توجد أقسام متاحة ؛
NU_INVALID_POOL - مؤشر تجمع أقسام غير صالح ؛
NU_INVALID_POINTER - تمرير مؤشر فارغ إلى البيانات التي تم إرجاعها (
NULL ) ؛
NU_INVALID_SUSPEND - تم إجراء محاولة لتعليق مهمة من سلسلة
رسائل غير مرتبطة بالمهمة ؛
NU_TIMEOUT - لا تتوفر أقسام ، حتى بعد التعليق لفترة الانتظار المحددة ؛
NU_POOL_DELETED - تم حذف تجمع الأقسام عندما تم تعليق المهمة.
استدعاء Nucleus SE API لتمييز قسم
يدعم اتصال API هذا الوظائف الأساسية لـ Nucleus RTOS API.
استدعاء النموذج:
STATUS NUSE_Partition_Allocate (تجمع NUSE_PARTITION_POOL ، ADDR * return_pointer ، تعليق U8) ؛معلمات:
pool - فهرس (ID) لتجمع الأقسام المستخدم ؛
return_pointer - المؤشر لمتغير من نوع
ADDR ، الذي يأخذ عنوان القسم المحدد ؛
تعليق - معلمة
لإيقاف المهمة مؤقتًا ؛ يمكن أن تأخذ القيم
NUSE_NO_SUSPEND أو
NUSE_SUSPEND .
القيمة المعادة:
NUSE_SUCCESS - تم إكمال المكالمة بنجاح ؛
NUSE_NO_PARTITION - لا توجد أقسام متاحة ؛
NUSE_INVALID_POOL - فهرس تجمع أقسام غير صالح ؛
NUSE_INVALID_POINTER - تمرير مؤشر فارغ إلى البيانات التي تم إرجاعها (
NULL ) ؛
NUSE_INVALID_SUSPEND - تم إجراء محاولة لتعليق مهمة من سلسلة
رسائل لم تكن مرتبطة بالمهمة أو عندما تم تعطيل واجهات برمجة تطبيقات القفل.
تنفيذ تخصيص القسم في Nucleus SE
تم تحديد رمز وظيفة واجهة برمجة التطبيقات
NUSE_Partition_Allocate باستخدام
الترجمة الشرطية بعد التحقق من المعلمات ، اعتمادًا على ما إذا تم تنشيط استدعاء API
للحظر (تعليق المهام) أم لا. أدناه سننظر بشكل منفصل في هذين الخيارين.
إذا تم إلغاء حظر المكالمات ، فإن استدعاء API بسيط للغاية:

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

يتم تضمين الكود في حلقة
do ... while ، والتي تستمر في العمل طالما أن معلمة الإيقاف المؤقت هي
NUSE_SUSPEND .
في حالة عدم توفر أقسام وكانت المعلمة pause هي
NUSE_NO_SUSPEND ، يتوقف استدعاء API ويعيد
NUSE_NO_PARTITION . إذا تم تعيين معلمة الإيقاف المؤقت على
NUSE_SUSPEND ، تتوقف المهمة مؤقتًا. عند العودة (على سبيل المثال ، عند استئناف مهمة) ، تشير القيمة
المرجعة لـ
NUSE_SUCCESS إلى أنه تم استئناف المهمة لأنه تم تحرير قسم الذاكرة وعودة الرمز إلى بداية الحلقة. نظرًا لعدم وجود وظائف API لإعادة تحميل تجمعات الأقسام ، لا يمكن استئناف المهام لأسباب أخرى ، ولكن من أجل استقرار حظر أنواع أخرى من الكائنات ، يتم حفظ عملية التحقق
NUSE_Task_Blocking_Return [] .
إصدار القسم
إصدار القسم في Nucleus RTOS و Nucleus SE يجعله متاحًا مرة أخرى. قبل الإصدار ، لا يتحقق ما إذا كان هذا القسم يستخدم من قبل أي مهمة أم لا ، مبرمج التطبيق هو المسؤول عن ذلك. مطلوب فقط مؤشر إلى منطقة بيانات لتحرير مقطع.
Nucleus RTOS API Call to Free Partition
استدعاء النموذج:
STATUS NU_Deallocate_Partition (قسم VOID *) ؛معلمات:
التقسيم - مؤشر إلى منطقة البيانات (يتم إرجاعه بواسطة الدالة
NU_Allocate_Partition () ) للقسم المراد تحريره ؛
القيمة المعادة:
NU_SUCCESS - تم إكمال المكالمة بنجاح ؛
NU_INVALID_POINTER - مؤشر المقطع NULL ، أو لا يشير إلى استخدام قسم صالح.
استدعاء Nucleus SE API لتقسيم مجاني
يدعم اتصال API هذا الوظائف الأساسية لـ Nucleus RTOS API.
استدعاء النموذج:
STATUS NUSE_Partition_Deallocate (قسم ADDR) ؛معلمات:
قسم - مؤشر إلى منطقة البيانات (يتم إرجاعه بواسطة الدالة
NUSE_Partition_Allocate () ) للقسم المراد تحريره
القيمة المعادة:
NUSE_SUCCESS - تم إكمال المكالمة بنجاح ؛
NUSE_INVALID_POINTER - مؤشر القسم فارغ (
NULL ) ، أو لا يشير إلى استخدام قسم صالح
التنفيذ
بدلاً من التنفيذ باستخدام وظائف API للحظر وغير الحظر ، تحتوي الدالة
NUSE_Partition_Deallocate () ببساطة على قسم
مترجم بشكل مشروط ومسؤول عن فتح المهام. يطبق هذا الكود تحرير الأقسام:

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

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