الحقيقة الكاملة عن RTOS. المادة رقم 15. أقسام الذاكرة: الخدمات وهياكل البيانات



في هذه المقالة ، نستمر في مراجعة أقسام الذاكرة في RTOS.

يحتوي Nucleus RTOS على ثلاث مكالمات API توفر وظائف الأداة المساعدة المتعلقة بتجمعات أقسام التخزين: إرجاع معلومات حول تجمعات الأقسام ، وإرجاع عدد تجمعات الأقسام في تطبيق ، وإرجاع المؤشرات إلى جميع تجمعات الأقسام في أي تطبيق. يتم تنفيذ أول تحديين في Nucleus SE.

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

استرداد معلومات تجمّع التقسيم


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

استدعاء معلومات تجمع الأقسام في Nucleus RTOS


استدعاء النموذج:

STATUS NU_Partition_Pool_Information (NU_PARTITION_POOL * pool ، CHAR * name ، VOID ** start_address ، UNSIGNED * pool_size ، UNSIGNED * قسم_حجم ، غير موقوف * متاح ، غير موقّع * مخصص ، OPTION * suspend_type ، غير موقّع أولاً * المهمة_الانتظار أولاً ؛

معلمات:

تجمع - مؤشر إلى تجمع القسم حول المعلومات المطلوبة ؛
الاسم - المؤشر إلى منطقة الوجهة المكونة من 8 أحرف لاسم تجمع الأقسام ؛ يتضمن مكانًا لإنهاء الصفر ؛
start_address - مؤشر إلى متغير يتلقى مؤشرًا إلى بداية منطقة البيانات الخاصة بتجمع الأقسام ؛
pool_size - مؤشر إلى متغير يتلقى حجم تجمع الأقسام (بالبايت) ؛
division_size - مؤشر إلى متغير يحصل على حجم الأقسام في تجمع معين ؛
متاح - مؤشر لمتغير يتلقى عدد الأقسام المتاحة حاليًا في هذا التجمع ؛
مخصصة - مؤشر لمتغير يتلقى عدد الأقسام المستخدمة حاليًا في تجمع معين ؛
suspend_type - المؤشر إلى متغير للحصول على نوع تعليق المهمة ؛ أنواع تعليق صالحة: NU_FIFO و NU_PRIORITY ؛
task_waiting - مؤشر لمتغير يتلقى عدد المهام المعلقة في تجمع قسم معين ؛
first_task - مؤشر لمؤشر المهمة الذي يوجد فيه مؤشر المهمة المعلقة الأولى.

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

NU_SUCCESS - تم إكمال المكالمة بنجاح ؛
NU_INVALID_POOL - مؤشر غير صالح لتجمع الأقسام.

استدعاء معلومات تجمع الأقسام في Nucleus SE


استدعاء النموذج:

STATUS NUSE_Partition_Pool_Information (NUSE_PARTITION_POOL pool، ADDR * start_address، U32 * pool_size، U16 * قسم_حجم، U8 * متوفر، U8 * مخصص، U8 * المهام_الانتظار، NUSE_TASK * first_task)

معلمات:

التجمع - فهرس تجمع الأقسام الذي يتم طلب المعلومات حوله ؛
start_address - مؤشر إلى متغير يتلقى مؤشرًا إلى بداية منطقة البيانات الخاصة بتجمع الأقسام ؛
pool_size - مؤشر إلى متغير يتلقى حجم تجمع الأقسام (بالبايت) ؛
division_size - مؤشر إلى متغير يحصل على حجم الأقسام في تجمع معين ؛
متاح - مؤشر لمتغير يتلقى عدد الأقسام المتاحة حاليًا في هذا التجمع ؛
مخصصة - مؤشر لمتغير يتلقى عدد الأقسام المستخدمة حاليًا في تجمع معين ؛
task_waiting - مؤشر إلى متغير يتلقى عدد المهام المعلقة في تجمع الأقسام هذا (إذا تم تعطيل تعليق المهمة ، يتم إرجاع 0) ؛
first_task - مؤشر إلى متغير من النوع NUSE_TASK ، الذي يتلقى فهرس المهمة المعلقة الأولى (إذا تم تعطيل تعليق المهمة ، يتم إرجاع 0).

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

NUSE_SUCCESS - تم إكمال المكالمة بنجاح ؛
NUSE_INVALID_POOL - فهرس تجمع أقسام غير صالح ؛
NUSE_INVALID_POINTER - واحدة أو أكثر من المؤشرات التي تم تمريرها غير صالحة.

تنفيذ استرجاع المعلومات وتجميع التقسيم في Nucleus SE


تنفيذ مثل هذه المكالمة API سهل التنفيذ:



تقوم الدالة بإرجاع حالة تجمع الأقسام. بعد ذلك ، إذا تم تنشيط حظر استدعاء API ، فسيتم إرجاع عدد المهام المعلقة وفهرس أولها (وإلا ، يتم تعيين هذه المعلمات إلى 0).

الحصول على عدد تجمعات الأقسام


تقوم هذه المكالمة بإرجاع معلومات حول عدد تجمعات الأقسام التي تم تكوينها في التطبيق. بينما في Nucleus RTOS يتغير هذا الرقم بمرور الوقت وستمثل القيمة المرتجعة العدد الحالي للمجمعات ، في Nucleus SE يتم تعيين القيمة المرتجعة أثناء التجميع وتبقى دون تغيير.

التحدي المتمثل في الحصول على عدد تجمعات الأقسام في Nucleus RTOS


تدعم المكالمة الوظائف الأساسية لـ Nucleus RTOS API.

استدعاء النموذج:

NU_Eststited_Partition_Pools (VOID) غير الموقعة ؛

معلمات:

غائبون.

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

عدد تجمعات الأقسام التي تم إنشاؤها في التطبيق.

التحدي المتمثل في الحصول على عدد تجمعات الأقسام في Nucleus SE


يدعم استدعاء الأداة المساعدة الوظائف الأساسية لـ Nucleus RTOS API.

استدعاء النموذج:

U8 NUSE_Partition_Pool_Count (باطل) ؛

معلمات:

غائبون

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

عدد تجمعات الأقسام التي تم إنشاؤها في التطبيق.

التنفيذ


تنفيذ استدعاء API هذا بسيط للغاية: تم إرجاع القيمة #define للرمز NUSE_PARTITION_POOL_NUMBER .

هياكل البيانات


مثل جميع كائنات Nucleus SE الأخرى ، تستخدم تجمعات الأقسام صفائف هيكلية في كل من ROM وذاكرة الوصول العشوائي ، ويعتمد عددها على عدد التجمعات المحددة في الإعدادات.

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

هيكل بيانات النواة الموضوعة في ذاكرة الوصول العشوائي


تتضمن هياكل البيانات هذه:

NUSE_Partition_Pool_Partition_Used [] - صفيف من النوع U8 ، به إدخال واحد لكل تجمع أقسام تم تكوينه ، يحتوي على عداد التجمعات المستخدمة حاليًا ؛
NUSE_Partition_Pool_Blocking_Count [] - صفيف من النوع U8 يحتوي على عداد المهام المحظورة في كل تجمع قسم. هذا الصفيف موجود إذا كان حظر استدعاء API ممكنًا.

تتم تهيئة هياكل البيانات هذه على الأصفار باستخدام NUSE_Init_ Partition_Pool () عند بدء Nucleus SE. هذا منطقي لأنه يجعل كل قسم في كل تجمع غير مستخدم (مجاني). ستقدم المقالة التالية وصفًا كاملاً لإجراءات بدء التشغيل في Nucleus SE.

فيما يلي وصف لبنى البيانات في ملف nuse_init.c .



بيانات مستخدم ذاكرة الوصول العشوائي


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

بيانات ROM


وتشمل هذه:

NUSE_Partition_Pool_Data_Address [] - صفيف من نوع ADDR ، مع إدخال واحد لكل تجمع أقسام تم تكوينه ، يحتوي على عنوان بداية منطقة تخزين البيانات ؛
NUSE_Partition_Pool_Partition_Number [] - صفيف من النوع U8 مع إدخال واحد لكل تجمع أقسام تم تكوينه يحتوي على معلومات حول عدد الأقسام في التجمع ؛
NUSE_Partition_Pool_Partition_Size [] - صفيف من النوع U16 مع إدخال واحد لكل تجمع أقسام تم تكوينه ، يحتوي على حجم أقسام التجمعات.

يتم الإعلان عن هياكل البيانات هذه وتهيئتها (بشكل ثابت) في nuse_config.c :



أثر البيانات لتجمع القسم


كما هو الحال مع جميع العناصر الأساسية في Nucleus SE ، يمكن توقع مقدار الذاكرة المطلوبة لمجمعات الأقسام.

يمكن حساب حجم ROM (بالبايت) لكافة تجمعات أقسام التطبيق على النحو التالي:

NUSE_PARTITION_POOL_NUMBER * (حجم (ADDR) + 2)

حجم بيانات kernel في ذاكرة الوصول العشوائي لجميع تجمعات تجمعات التطبيقات عند تنشيط حظر استدعاء واجهة برمجة التطبيقات لا يستغرق سوى 2 بايت لكل تجمع أقسام ، وعندما لا يتم تنشيط الحظر ، يستغرق 1 بايت.

يختلف مقدار الذاكرة لتخزين بيانات المستخدم في ذاكرة الوصول العشوائي (RAM) لكل تجمع أقسام ، على الرغم من أنه ، كما ذكرنا سابقًا ، يمكن حساب تجمع مع فهرس n على النحو التالي:

NUSE_Partition_Pool_Partition_Number [n] *
(NUSE_Partition_Pool_Partition_Size [n] + 1)

مكالمات API غير محققة


لا يتم دعم ثلاث مكالمات API لمجمعات الأقسام التي تم تنفيذها في Nucleus RTOS في Nucleus SE.

إنشاء تجمع أقسام


ينشئ استدعاء API تجمع أقسام. لا تحتاج Nucleus SE إليها لأنه يتم إنشاء المهام بشكل ثابت.

استدعاء النموذج:

STATUS NU_Create_Partition_Pool (NU_PARTITION_POOL * pool ، CHAR * name ، VOID * start_address ، UNSIGNED pool_size ، UNSIGNED division_size ، OPTION suspend_type) ؛

معلمات:

تجمع - مؤشر إلى وحدة تحكم تجمع التقسيم المعرفة من قبل المستخدم ؛ تُستخدم كمقبض لتجمع الأقسام في مكالمات API الأخرى ؛
name - مؤشر لاسم تجمع الأقسام ، سلسلة من 7 أحرف بصفر تنتهي ؛
start_address - تعيين عنوان البدء لمنطقة الذاكرة الخاصة بتجمع الأقسام ؛
pool_size - إجمالي حجم الذاكرة بالبايت ؛
section_size - مقدار الذاكرة بالبايت لكل قسم في التجمع. علاوة على ذلك ، يتم تخصيص كمية صغيرة إضافية من الذاكرة مرتبطة بكل قسم ، والتي تتحقق بفضل مؤشرين من البيانات المستخدمة.
suspend_type - يحدد كيفية تعليق المهام في تجمع الأقسام ؛ خيارات المعلمات الصالحة هي NU_FIFO و NU_PRIORITY .

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

NU_SUCCESS - يشير إلى إتمام المكالمة بنجاح ؛
NU_INVALID_POOL - يشير إلى القيمة الصفرية لوحدة التحكم في تجمع الأقسام ( NULL ) ؛
NU_INVALID_MEMORY - تشير إلى القيمة الصفرية لمنطقة الذاكرة المحددة بواسطة عنوان_البدء ( NULL ) ؛
NU_INVALID_SIZE - يشير إلى أن حجم القسم إما 0 أو أكبر من الذاكرة المخصصة للقسم ؛
NU_INVALID_SUSPEND - قيمة نوع الإيقاف المرحلي غير صالحة.

حذف تجمع القسم


تحذف استدعاء API تجمع أقسام تم إنشاؤه مسبقًا. لا يحتاج Nucleus SE إلى ذلك لأنه يتم إنشاء الكائنات بشكل ثابت ولا يمكن حذفها.

استدعاء النموذج:

STATUS NU_Delete_Partition_Pool (NU_PARTITION_POOL * pool) ؛

معلمات:

تجمع - مؤشر إلى وحدة تحكم تجمع التقسيم ؛

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

NU_SUCCESS - يشير إلى إتمام المكالمة بنجاح ؛
NU_INVALID_POOL - يشير إلى قيمة غير صالحة لمؤشر تجمع الأقسام ؛

مؤشرات تجمع التقسيم


ينشئ استدعاء API هذا قائمة متسلسلة من المؤشرات لجميع تجمعات الأقسام في النظام. لا يحتاج Nucleus SE إلى ذلك لأنه يتم تحديد الكائنات بواسطة الفهرس وليس المؤشر.

استدعاء النموذج:

UNSIGNED NU_Partition_Pool_Pointers (NU_PARTITION_POOL ** pointer_list و unsIGNED max_pointers) ؛

معلمات:

pointer_list - المؤشر على مجموعة من المؤشرات NU_PARTITION_POOL ؛ المصفوفة مليئة بمؤشرات على التجمعات المكونة في النظام ؛
max_pointers - الحد الأقصى لعدد المؤشرات التي يمكن وضعها في المصفوفة.

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

عدد مؤشرات NU_PARTITION_POOL الموضوعة في الصفيف.

متوافق مع Nucleus RTOS


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

معرفات الكائن


في Nucleus RTOS ، يتم وصف جميع الكائنات من خلال هياكل البيانات (وحدات التحكم) من نوع معين. يتم استخدام مؤشر كتلة التحكم هذه كمعرف لتجمع الأقسام. قررت أن Nucleus SE يتطلب منهجًا مختلفًا لاستخدام أكثر كفاءة للذاكرة. يتم وصف جميع كائنات kernel بواسطة عدة جداول في ذاكرة الوصول العشوائي و / أو ROM. يتم تحديد أحجام هذه الجداول من خلال عدد الأنواع القابلة للتكوين من جميع الكائنات. معرف كائن معين هو الفهرس في هذه الجداول. لذلك ، قررت أن NUSE_PARTITION_POOL مكافئ لـ U8 ، وبعد ذلك يعمل متغير (ليس مؤشرًا) من هذا النوع كمعرف للمهمة. من السهل معرفة عدم التوافق البسيط هذا إذا تم نقل الرمز من Nucleus RTOS أو إليه. عادة ما يتم تخزين معرفات الكائن ونقلها دون تغيير.

يدعم Nucleus RTOS أيضًا تجمعات أقسام التسمية. يتم استخدام هذه الأسماء فقط لتصحيح الأخطاء. لقد استبعدتهم من Nucleus SE لتوفير الذاكرة.

عدد الأقسام وحجمها


في Nucleus RTOS ، يتم تكوين تجمع الأقسام استنادًا إلى إجمالي حجم التجمع وحجم الأقسام (التي تحمل مؤشرين آخرين). وتُعرَّف هذه المعلمات بأنها غير موقعة (حوالي 32 بتة). في Nucleus SE ، يتم تكوين تجمع الأقسام بناءً على حجم القسم (الذي تمت إضافة بايت إضافي له) وإجمالي عدد الأقسام. يتم تعريف هذه المعلمات على أنها U16 و U8 ، على التوالي.

مكالمات API غير محققة


يدعم Nucleus RTOS 7 مكالمات للعمل مع تجمعات الأقسام ، لم يتم تنفيذ 3 منها في Nucleus SE. مزيد من التفاصيل حول هذه التحديات وأسباب استبعادها موضحة أعلاه.

ستتمحور المقالة التالية حول الإشارات.

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

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


All Articles