الدرس ٤ : تعرف على البنية البرمجية لمعالجات ARM Cortex-M4 ومبدأ عملها (ج٢)


#1

بسم الله الرحمن الرحيم
الحمد لله رب العالمين والصلاة والسلام على أشرف المرسلين، بفضل الله وتوفيقه نقدم لكم الدرس الرابع بسلسلة دروس تعلم برمجة الأنظمة المدمجة والميكروكنترولر STM32 المعتمد على نواة ARM Cortex-M4

بعنوان

تعرف على البنية البرمجية لمعالجات ARM Cortex-M4 ومبدأ عملها ج٢

درس اليوم هو أستكمال لحديثنا عن البنية البرمجية للمعالج ARM Cortex-M4، توقفنا المرة السابقة عند خاصية bit-banding وهي من المميزات الرائعة بمعالجات أرم، نستكمل اليوم مع بعض خصائص الذاكرة وخطوط البيانات وكذلك سنتعرف أكثر عن المقاطعات.

ترتيب المتغيرات بالذاكرة endianness

يتكون أي متغير ٣٢ بت من ٤ بايت مثلا القيمة الاتية 0xFF55AA33 وهي بالنظام السادس عشر يحتوي على البايت الذى قيمته 0x33 ويسمي البايت الأقل أهمية least significant byte والبايت الأخير والذى قيمته 0xFF وهو البايت الأعلى أهمية يسمى most significant byte والأن اذا ارد المعالج وضع هذا المتغير بالذاكرة فيمكن ذلك عن طريق أحدى الطريقيتين وهما:

الترتيب big-endian

ويتم فيها وضع البايت الأعلى أهمية أولا كما في الصورة الاتية

الترتيب Little-endian

ويتم فيه وضع البايت الأقل أهمية أولا كما في الصورة الاتية

أساسيات التزامن Synchronization primitives

في الأنظمة متعددة المهام multitasking operating system وعند تنفيذ البرنامج يجب دائما ضمان دخول وحيد لأي عنوان بالذاكرة حتى لا يحدث تصادم بين العمليات داخل خطوط نقل البيانات والعناوين. بنية التعليمات الخاصة بالمعالج Cortex-M4 توفر نوعين من التعليمات لضمان الدخول الحصري والوحيد لكل عملية وهما:

  • تعليمة قراءة حصرية A Load-Exclusive instruction
  • تعليمة كتابة حصرية A Store-Exclusive instruction

اذا ارد المعالج اتمام عملية read-modify-write فيجب دائما استعمال تعليمة القراءة الحصرية حتي لا يتم كتابة الذاكرة بعد قراءتها. في حالة الرغبة في القراءة فقط فلا داعي لاستخدام تعليمة القراءة الحصرية حيث يسمح بالقراءة مع وجود عملية أخرى تقوم بعملية الكتابة.

خط الأنابيب Pipeline

قبل تنفيذ أي تعليمة من أوامر البرنامج يقوم المعالج بجلب هذه التعليمة من الذاكرة وهذه العملية تسمى FETCH ثم يقوم المعالج بتحديد المسجلات المستخدمة في التعليمة ومن ثم قراءتهم DECODE ثم تتم عملية التنفيذ EXECUTE وهذه العملية موضحة بالصورة الاتية

هذه العملية تستغرق العديد من دورات المعالج على الأقل ٣ دورات ولذلك كان لابد من وجود طريقة تقوم باتمام هذه العمليات بالتوازي لتقليل الوقت اللازم لتنفيذ التعليمة الواحدة. تعتمد معالجات ARM Cortex-M4 على خط أنابيب من ٣ مراحل وتعتمد فكرته على اتمام ٣ عمليات على ٣ تعليمات في نفس الوقت كما في الصورة الاتية.

04

فمثلا اذا كان مطلوب من المعالج تنفيذ ٣ تعليمات ومن المعلوم ان كل تعليمة تتكون من ٣ عمليات وهي الجلب والقراءة والتنفيذ فبدلا من تنتفيذ الثلاث عمليات الخاصة بالتعليمة ١ ثم الثلاث عمليات الخاصة بالتعليمة ٢ وبعدها الثلاث عمليات الخاصة بالتعليمة ٣ على التوالي سيقوم المعالج بالتنفيذ كالأتي سيتم جلب التعليمة ١ في أول خطوة حيث لا يمكن عمل أي شي أخر في هذه الخطوة لانه لا يمكن عمل عمليتان جلب في نفس الوقت كذلك لا يمكن قراءة أي شي لان المعالج لم يتم عملية الجلب وفي الخطوة الثانية سيكون المعالج قد أتم عملية الجلب للتعليمة ١ والان سيتم قراءة المسجلات ونفس الوقت سيقوم بجلب التعليمة ٢ وفي الخطوة الثالثة سيقوم المعالج بنتفيذ التعليمة ١ وقراءة التعليمة ٢ وجلب التعليمة ٣ في نفس الوقت وهكذا حتي يستغرق المعالج ٥ دورات لتنفيذ الثلاث تعليمات أما في حالة عدم وجود خط الأنابيب Pipeline فيستغرق المعالج ٩ دورات لتنفيذ ٣ تعليمات حيث ان كل تعليمة تستغرق ٣ دورات ولا يتم تنفيذهم على التوازي.

النموذج البرمجي للمقاطعات والاستثناءات Exception model

تعرف المقاطعات Interrupts أو الاستثناءات Exceptions على أنها أحداث غير متزامنة قد تحدث في أي وقت وتغير مسار تنفيذ البرنامج الطبيعي. عند حدوث مقاطعة او استثناء فلابد للمعالج أن يستجيب ويعلق تنفيذ المهمة الحالية التي يقوم بها ويحفظ مؤشر المكدس stack pointer الحالي لحين العودة مرة اخرى ثم يقوم بتنفيذ الدالة الخاصة بالمقاطعة أو الاستثناء وتسمى Exception Handler في حالة الاستثناء او Interrupt Service Routine واختصاره (ISR) في حالة المقاطعة.

تمتاز معالجات ARM Cortex-M4 بإمكانيتها للتعامل مع المقاطعات أو الاستثناءات وادارتها، حيث توجد وحدة خاصة داخل المعالج للتعامل مع الأستثناءات وتسمى Nested Vectored Interrupt Controller واختصارا NVIC. كما يمكن أيضا التعامل مع هذه الوحدة من خلال البرنامج نفسه اذا اردنا تشغيل او ايقاف احد الاستثناءات وهذه العملية تسمى Interrupt masking، كما تدعم معالجات Cortex-M4 الأستثناءات المتداخلة حيث يمكن التعامل مع أحد الأستثناءات أثناء تنفيذ الأخر.

الفرق بين المقاطعة Interrupt والاستثناء Exception

ومن المهم معرفة الفرق بين المقاطعة Interrupt والاستثناء Exception حيث تعرف المقاطعات بمعالجات أرم على أنها جزء من الأستثناء التي قد لتحدث لتغيير مسار البرنامج والمقاطعات تنتج فقط من النهايات الطرفية الداخلية الموجودة على الشريحة كالمؤقتات أو من النهايات الطرفية الخارجية مثلا كحساس موصل بدخل رقمي GPIO كما يمكن توليد المقاطعات من خلال البرنامج نفسه. أما الأستثناءات فتكون غالبا الأخطاء التي تنتج أثناء تنفيذ البرنامج ويكون مصدرها من المعالج نفسه.

في الصورتين التاليتين نرى الأستثناءات الخاصة بالمعالج Cortex-M4


رقم الأستثناء Exception number

نرى أن لكل أستثناء رقم خاص به وهذا الرقم يعكس مكان هذا الأستثناء داخل جدول الأستثناءات والذى يسمى دائما vector table.

رقم المقاطعة IRQ number

وهو الرقم خاص بالمقاطعات حيث أن اول مقاطعة يكون رقمها صفر.

الأولوية Priority

لكل أستثناء أولوية خاصة بعضها يمكن تغيره Configurable وهناك ٣ أستثناء لهم أولوية ثابتة لا يمكن تغيرها. والأولوية تحدد أيهما يتم الاستجابة له أولا فاذا كان المعالج الان يقوم بالرد وتنفيذ الدالة الخاصة باستثناء معين وحدث أستثناء أخر له أولوية أعلى فان المعالج يترك تنفيذ الاستثناء الحالي ويقوم بتنفيذ الأستثناء الذى له اولوية أعلى والذى يكون له رقم أولوية أقل مثل أعادة التشغيل Reset لها أعلى أولوية ورقمها أقل رقم وهو ـ٣. كما يمكن أيضا عمل مجموعات للأولوية group priority وأولوية داخل كل مجموعة subpriority.

أنواع الأستثناءات Exception types

  • أستثناء اعادة التشغيل Reset ويحدث عند اعادة تشغيل المعالج او توصيلة بالطاقة الكهربية.
  • المقاطعات التي لا يعمل منعها Non Maskable Interrupt - NMI
  • مجموعة الأستثناءات الخاصة بالتعامل مع الأخطاء HardFault و MemManage و BusFault و UsageFault.
  • مجموعة الأستثناءات الخاصة بحالة وجود نظام تشغيل والمهام المتعددة multi-tasking وهما SVCall لعمل نداء للمشرف و PendSV يستخدم للتحويل بين المهام context switching.
  • مؤقت النظام SysTick وهو مؤقت ٢٤ بت يقوم بتوليد أستثناء عند وصوله للصفر يمكن للبرنامج استخدام هذا الأستثناء لظبط التوقيتات.
  • مقاطعة Interrupt - IRQ وهو الأستثناء الذى يحدث من الأجهزة الطرفية ويكون دائما غير متزامن مع البرنامج.

حالات الأستثناءات Exception states

حالة الأستثناء تكون واحدة من الحالات الاتية

غير فعال Inactive
وهي الحالة العادية ويكون فيها الدالة الخاصة بالتعامل مع الأستثناء ليست في حالة تنفيذ او انتظار.

ينتظر Pending
في هذه الحالة يكون الأستثناء قد حدث بالفعل ولكن دالة الأستثناء تنتظر تفرع المعالج ليتم تنفيذها وغالبا يقوم المعالج بتنفيذ دالة أستثناء أخر له أولوية أعلى.

فعال Active
في هذه الحالة يقوم المعالج بالتعامل مع الأستثناء.

فعال ويتنظر Active and pending
في هذه الحالة يقوم المعالج بالتعامل مع الأستثناء وفي نفس الوقت حدث أستثناء أخر من نفس المصدر فيكون هناك أستثناء يتم تنفيذه واخر مشابه له يتنظر.

الصورة التالية توضح الحالات المختلفة للاستثناءات ومتى يتم الانتقال من حالة لأخرى

بعض خصائص المعالج Cortex-M4 للتعامل مع الأستثناءات

خاصية Tail-chaining

عندما يقوم المعالج بمعالجة أستثناء معين وعند الانتهاء منه وفي حالة وجود أستثناء أخر في وضع انتظار فان المعالج يترك عملية الاسترجاع من المكدس حتى ينتهي من معالجة الاستثناء الجديد كما هو موضح بالصورة الاتية

Tail%20Chaining

خاصية POP pre-emption

يحدث عادة ان يترك المعالج تنفيذ أحد الأستثناءات ويقوم بمعالجة أخر له أولوية أعلى وهذه ما يسمى pre-emption. فاذا كان المعالج قد انتهى من تنفيذ الأستثناء ويقوم باسترجاع البيانات من المكدس وجاء استثناء أخر فيقوم المعالج بسرعة بتوقف عملية الاسترجاع من المكدس ومعالجة الأستثناء الجديد كما موضح بالصورة الأتية وعند الانتهاء يستكمل عملية الاسترجاع.

Pop%20pre-emption

خاصية Late-arriving

قبل البدء في معالجة الأستثناء يقوم المعالج عادة بحفظ بيانات الدالة التي كان ينفذها قبل حدوث الأستثناء بالمكدس وأثناء هذه العملية وفي حالة حدوث أستثناء له أولوية أعلى فان المعالج يترك عملية الكتابة بالمكدس بسرعة ويقوم بمعالجة الأستثناء الجديد كما هو موضح بالصورة الاتية

late%20arrival

التعامل مع الأخطاء Fault handling

تعتبر الأخطاء بالمعالج Cortex-M4 نوعا من انواع الأستثناءات Exception والتي تغيير مسار تنفيذ البرنامج الطبيعي ليقوم المعالج بالتعامل مع هذه الأخطاء ومحاولة تصحيحها أو تصعيد الخطأ ليتوقف المعالج عن تنفيذ البرنامج.

أنواع الأخطاء Fault types

تقسم الأخطاء إلي أربعة أنواع بناء على الدالة الخاصة Exception Handler بالتعامل مع كل نوع وهي

دالة الخطأ حاد HardFault

ويتم أستدعاءها في حالة حدوث الأخطاء الأتية

  • خطأ في خط نقل عند قراءة جدول المقاطعات Bus error on a vector read
  • خطأ تم تصعيده لخطأ حاد escalated to HardFault

دالة خطأ التحكم بالذاكرة MemManage

ويتم أستدعاءها في حالة حدوث الأخطاء الأتية

  • خطأ نتيجة اختلاف بين خريطة الذاكرة ووحدة حماية الذاكرة عند قراءة تعليمة او قراءة او كتابة بيانات أو عملية قراءة او كتابة لبيانات الأستثناءات أو وحدة المعاملات العشرية بالمكدس.

دالة خطأ خط النقل BusFault

ويتم أستدعاءها في حالة حدوث الأخطاء الأتية

  • خطأ في خط النقل عند عملية جلب تعليمة أو قراءة او كتابة لبيانات الأستثناءات أو وحدة المعاملات العشرية بالمكدس.
  • خطأ محدد في خط نقل البيانات Precise data bus error وهنا يمكننا معرفة التعليمة الذى سببت هذا الخطأ.
  • خطأ غير محدد في خط نقل البيانات Imprecise data bus error وهذا خطأ غير متزامن ولا يمكننا تحديد أى تعليمة سببت هذا الخطأ.

دالة خطأ الأستخدام UsageFault

ويتم أستدعاءها في حالة حدوث الأخطاء الأتية

  • خطأ عند استخدام تعليمة غير معروفة Undefined instruction
  • خطأ نتيجة القسمة على صفر
  • خطأ نتيجة عنوان رجوع غير صالح لأستثناء Invalid EXC_RETURN value

تصعيد الأخطاء Fault escalation

يمكن تغيير الأولوية لكل أستثناء من الأسثنئات الخاصة بالتعامل مع الأخطاء ما عدا استثناء الخطأ الحاد HardFault، كذلك يمكن للبرنامج منع تنفيذ الدوال الخاصة للتعامل مع هذه الأخطاء.

والأولوية يمكن تحديدها بواسطة exception mask registers حيث يتم تحديد ما ان كان المعالج سيدخل في حالة الخطأ الحاد أم لا. وفي بعض الأحيان يتم تصعيد الأخطاء التي تحدث إلي أخطاء حادة escalated to HardFault ويكون في الحالات الأتية:

  • عندما تسبب دالة الخطأ التي يقوم المعالج بتنفيذها نفس الخطأ أو خطأ أخر له أولوية مشابه أو أقل من أولوية الخطأ الحالي. والسبب في ذلك ان المعالج لن يكون قادرا على معالجة دالة الخطأ الجديد ولذلك يتم التصعيد لخطأ حاد.

  • عندما تسبب دالة أستثناء خطأ ويكون لها أولوية مساوية أو أعلى من دالة الخطأ والسبب هنا أيضا ان المعالج لن يكون قادرا على تنفيذ دالة الخطأ ولذلك يتم التصعيد.

  • أو عندما تكون دالة الخطأ غير فعالة ولا يمكن تنفيذها.

الفكرة العامة في تصعيد الأخطاء أن المعالج يقوم بصعيد الخطأ كخطأ حاد ان لم يكون قادرا على تنفيذ دالة الخطأ الذى يتم حدوثه.

فعل سبيل المثال في البرنامج كان هناك عملية قسمة على صفر مما نتج عنه خطأ UsageFault وأثناء تنفيذ الدالة الخاصة بهذا الخطأ وجد المعالج نفس الخطأ داخل هذه الدالة أيضا وهو القسمة على صفر وبناء عليه فسيتم التصعيد لخطأ حاد وسيقوم المعالج بتنفيذ الدالة الخاصة بالخطأ الحاد HardFault.

حالة Lockup

والأن السؤال الذى يطرح نفسه ماذا يحدث اذا حدث خطأ داخل دالة معالجة الخطأ الحاد HardFault.

والاجابة هي ان المعالج لن يستطيع ترك دالة HardFault الا في حالة حدوث مقاطعة لها أولوية لا يمكن تغييرها NMI أو في حالة حدوث اعادة تشغيل. فاذا كان المعالج يقوم بتنفيذ دالة الخطأ الحاد أو دالة مقاطعة لها أولوية لا يمكن تغييرها NMI فإن المعالج يدخل حالة تسمى Lockup وفيها يمتنع عند تنفيذ البرنامج حتى تتم اعادة التشغيل.

توضح الصورة الاتية دخول المعالج لحالة Lockup

التحكم بالطاقة Power management

تمتاز معالجات Cortex-M4 بقدرتها على توفير الطاقة وذلك عن طريق الدخول لأحد أوضاع السكون sleep mode وهما

وضع السكون العادي sleep mode
في هذا الوضع يتم ايقاف توقيت المعالج.

وضع السكون العميق deep sleep mode
في هذا الوضع يتم ايقاف توقيت النظام وتوقيت PLL وذاكرة الفلاش.

الدخول لوضعية السكون Entering sleep mode

يتم دخول المعالج لوضعية السكون عن طريق التالي:

  • تعليمة Wait for interrupt
  • تعليمة Wait for event
  • عن طريق Sleep-on-exit وعادة يستخدم عندما يتم التعامل فقط مع المقاطعات وفي حالة عدم وجود برنامج لتنفيذه فيدخل المعالج وضع السكون بعد الانتهاء من تنفيذ المقاطعات.

إيقاظ المعالج من وضع السكون Wakeup from sleep mode

تعتمد عملية إيقاظ المعالج من وضع السكون على الكيفية التي داخل بيها وضع السكون فاذا كان السبب تعليمة Wait for interrupt فإن المعالج يخرج من وضع السكون في حالة حدوث المقاطعة التي ينتظرها أما اذا دخل المعالج وضع السكون عن طريق Wait for event فإن المعالج يغادر وضع السكون عندما حدوث الحدث الذى يتنظره.

في حالة وجود أكثر من معالج فيمكن لأي معالج إيقاظ الأخر من وضعية السكون.

يرجى ملاحظة عندما يكون بوضعية السكون العميق deep sleep mode فسيكون غير قادرا على أستقبال المقاطعات أو الأحداث الخارجية ولذلك هناك وحدة أخرى خارج النواة Wakeup Interrupt Controller وهي المسئولة عن أستقبال المقاطعات والأحداث الخارجية لإيقاظ المعالج من وضعية السكون العميق.

الأضافات البرمجية CMSIS

من اهم مميزات معالجات أرم هو وجود مكتبة برمجية Cortex Microcontroller Software Interface Standard واختصارا CMSIS موحدة لجميع المتحكمات المعتمدة على نواة Cortex حيث يمكن استخدامها للتعامل مع المعالج بعض النظر عن المتحكم المستخدم وتحتوي هذه المكتبة على CMSIS-CORE وهي مجموعة جاهزة من الدوال للتعامل مع المعالج، CMSIS-Driver وهي مجموعة من الدوال للتعامل مع الأجهزة الملحقة والنهايات الطرفية، و CMSIS-DSP للتعامل مع الأشارات الرقمية ومعالجتها كما يمكن استخدامها للتعامل مع الأعداد العشرية floating-point. هناك أيضا CMSIS-RTOS API للتعامل مع أنظمة التشغيل بالزمن الحقيقي Real-Time Operating Systems واختصارا RTOS كما يوجد أيضا CMSIS-Pack و CMSIS-SVD و CMSIS-DAP.

يوضح الشكل الأتي الهيكل العام لمكتبات CMSIS

وإلي هنا أنتهى حديثنا عن معالجات ARM Cortex-M4 ونستكمل المرة القادمة الحديث عن متحكمات STM32 ان شاء الله والي اللقاء.

فيديو شرج الدرس


تعلم برمجة الأنظمة المدمجة والمتحكم الدقيق STM32 المعتمد على نواة ARM Cortex-M4
الدرس ٢ : مقدمة عن معالجات أرم ARM Cortex وبنية المعالج Cortex-M4
#2

تم تعديل الدرس وأضافة بعض النقاط الهامة مثل
أنواع وحالات الأستثناءات وبعض خصائص المعالج Cortex-M4 للتعامل مع الأستثناءات مثل Tail-chaining و POP pre-emption و Late-arriving كذلك تم أضافة جزء عن التعامل مع الأخطاء والتحكم بالطاقة


#3

تم اضافة فيديو الدرس الرابع