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

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

بعنوان

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

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

في البداية أحب ان أوصي ببعض الكتيبات الهامة من شركة أرم حول معالجات ARM Cortex-M4 وهي تعتبر المرجع الرئيسي والمهم لمن أراد التعمق ومعرفة المزيد.

والان نستكمل الشرح مع

أوضاع تشغيل البرنامج

يتم تشغيل وتنفيذ البرنامج بالمعالج Cortex-M4 من خلال وضعين للتشغيل وهما Thread mode أو Handler mode حيث يتم في حالة Thread mode بتنفيذ البرنامج بصورة طبيعة كالمعتاد ويبدأ دائما المعالج في التنفيذ بعد اعادة تشغيلة Reset. أما في الوضع Handler mode فهو الوضع الذى ينتقل له المعالج في حالة الرد على المقاطعات Interrupts وبعد الانتهاء يرجع المعالج مرة اخرى للوضع العادي Thread mode كما هو موضح بالصورة الأتية.

42

صلاحيات البرنامج

هناك نوعين من صلاحيات البرنامج أحدهما Unprivileged وتعني عدم وجود أي امتيازات للبرنامج فقط يتم التشغيل بالصورة العادية ويمنع البرنامج من استخدام الاوامر MSR أو MRS وهي أوامر خاصة للكتابة بمسجلات المعالج كما يمنع البرنامج من من الدخول لتوقيت النظام أو لوحدة المقاطعات NVIC أو لمجموعة التحكم بالنظام system control block، كما يكون له صلاحيات مقيدة للتعامل مع الذاكرة والأجهزة الطرفية peripherals.

أما النوع الأخر من الصلاحيات وهو Privileged حيث يمنح البرنامج جميع الصلاحيات. ويرجى ملاحظة انه دائما عندما يكون المعالج في وضع Handler mode يمنح جميع الصلاحيات أما عندما يكون في الوضع Thread mode يتم التحكم في الصلاحيات من خلال المسجل CONTROL.

أذا كان وضع تشغيل البرنامج Unprivileged فانه من غير الممكن الكتابة بالمسجل CONTROL ولذلك الطريقة الوحيدة للرجوع للوضع Privileged عن طريق عمل supervisor call باستخدام تعليمة SVC ,i وهذه التعليمة تستخدم غالبا في حالة وجود نظام تشغيل لطلب استخدام موارد النظام.

الشكل التالي يوضح أوضاع تشغيل البرنامج والصلاحيات المتاحة بكل وضع

48

المسجلات

نرى في الصورة السابقة مجموعة المسجلات الموجودة بالمعالج Cortex-M4 وهي مجموعة مسجلات عامة R0-R12 ومسجل مؤشر المكدس Stack Pointer ومسجل الربط Link Register وعداد البرنامج Program Counter ومسجل حالة البرنامج PSR Program status register ومجموعة مسجلات للتعامل مع المقاطعات Exception mask registers بالاضافة للمسجل الخاص بالتحكم CONTROL.

الجدول الاتي يحتوي نوع كل مسجل وصلاحية الوصول كذلك قيمته بعد عمل اعادة التشغيل

المسجلات العامة R0-R12

طبعا أى عملية يقوم بها المعالج لابد أن تكون المسجلات العامة طرفا فيها فمثلا عمليه جمع رقمين تتم عن طريق ايجاد الرقمين من مكان تخزينتهم بالمسجلات وليكن مثلا R1 و R2 ثم جمعهم والنتيجة يتم تخزينها في مسجل أخر وليكن مثلا R3.

مؤشر المكدس Stack Pointer

تعتمد معالجات Cortex-M4 على أثنين من المكدسات Stacks أحدهما المكدس الرئيسي main stack والأخر مكدس العملية process stack و المكدس Stack هو مكان محدد في ذاكرة الرام يقوم المعالج فيه بتخزين البيانات الخاصة للدالة في حالة استعداء دالة اخرى لحين الرجوع مرة اخرى لها وبالأضافة لبعض البيانات الأخرى، بالمعالج Cortex-M4 يكون ال Stack تنازلي والمسجل stack pointer يشير دائما لأخر مكان بالذاكرة تمت الكتابة به.

فمثلا لو فرضنا ان مكان المكدس Stack يبدأ من أخر مكان بالذاكرة ومؤشر المكدس Stack Pointer يشير الي هذا العنوان أى انه لا توجد اى بيانات داخل المكدس Stack والأن إذا أراد المعالج الكتابة داخل المكدس stack فسيقوم أولا بتقليل العنوان ليشير الي المكان الجديد الذى ستتم الكتابة فيه وسيكون هو المكان القبل الأخير وبعدها يقوم بعملية الكتابة، وبذلك يشير دائما مؤشر المكدس Stack Pointer للمكان الذي تمت به أخر عملية كتابة، أما اذا أراد المعالج القراءة من المكدس stack فسيقوم بقراءة البيانات اولا وبعدها سيقوم بزيادة العنوان ليشير مرة أخرى لأخر مكان تمت الكتابة به. وللعلم فعملية الكتابة داخل المكدس stack تسمي push وعمليه القراءة تسمي pop.

الجدول الأتي يوضح أوضاع المعالج ومتى يتم استخدامهم للصلاحيات ونوع المكدس stack المستخدم.

01

مسجل الربط Link Register

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

عداد البرنامج Program Counter

يتم فيه حفظ عنوان مكان البرنامج الذى سيتم تنفيذه بعد الأنتهاء من التعليمة الحالية ويستخدم لتحويل مسار البرنامج ولكن غير مستحب عمل ذلك وكبديل يمكن استخدام تعليمة branching، عادة يبدأ المعالج بتنفيذ البرنامج من العنوان 0x00000004 حيث يحتوي على جدول المقاطعات vector table أما العنوان 0x00000000 فيحتوي على stack pointer فاذا كان برنامجنا في عنوان أخر فيجب كتابة هذا المسجل بالعنوان الأخر ليعرف المعالج من أين سيبدأ تنفيذ البرنامج.

مسجل حالة البرنامج PSR Program status register

يحتوي على ٣ طبقات APSR و IPSR و EPSR كما موضح بالصورة الاتية

تحتوي طبقة APSR على حالة تطبيقات البرنامج وخاصة عند استخدام العمليات الحسابية فيمكننا معرفة اذا حدثت عملية قسمة على الصفر أو Overflow لمتغير معين. الطبقة الثانية وهي للمقاطعات IPSR ويكون فيه رقم المقاطعة الحالية. أما الطبقة EPSR فيقوم المعالج فيها بتخزين حالة تنفيذ البرنامج الحالية مثلا هل يقوم بتنفيذ تعليمة يمكن مقاطعتها أم لا.

مجموعة مسجلات التعامل مع المقاطعات Exception mask registers

هذه المسجلات مخصصة للتعامل مع المقاطعات فمثلا المسجل PRIMASK يمكن استخدامه لمنع المقاطعات التي لها اولوية يمكن تعديلها وأقل أولوية يمكن مقاطعتها يتم تحديدها في المسجل BASEPRI أما المقاطعات التي لا يمكن تعديل أولويتها فيمكن ايقافها باستخدام FAULTMASK وللعلم فالمقاطعات الخاصة بالمعالج لا يمكن ايقافها.

المسجل الخاص بالتحكم CONTROL

هذا المسجل يقوم بتحديد نوع المكدس المستخدم وصلاحيات الوصول للبرنامج.

تقسيم الذاكرة

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

05

ونلاحظ بعض العناوين الهامة

  • عنوان البداية لذاكرة الروم الذى يتم تخزين البرنامج بها هو 0x00000000 وأكبر مساحة يمكن استخدامها ٥١٢ ميجا بايت طبعا تختلف على حسب ذاكرة الروم او الفلاش المتاحة في كل متحكم فمثلا بالمتحكم stm32F429 ذاكرة الفلاش ٢ ميجا بايت.

  • يكون دائما مخزن في العنوان 0x00000000 عنوان المكدس بالرام والمكان الذى يليه وهو 0x00000004 يكون مخزن به جدول المقاطعات ويسمى vector table وتقوم شركة ST بتقسيم هذه المساحة لمتحكمات STM32 فمثلا يتم دائما بوضع أكواد البرنامج بداية من العنوان 0x0800 0000 وهو مخصص لذاكرة الفلاش flash memory كما موضح بالصورة الاتية

  • عنوان البداية لذاكرة الرام هو 0x20000000

  • عنوان البداية للنهايات الطرفية مثل UART أو ADC هو 0x40000000

  • عنوان ذاكرة الرام الخارجية مثل الموجودة في لوحة ديسكفري هو 0x60000000 حيث يمكن لمعالجات Cortex-M تنفيذ البرنامج والتعامل مع البيانات الموجودة على ذاكرة خارجية وهذه الذاكرة تكون مفيدة في حالة التعامل مع أنظمة التشغيل او تطبيقات الملتيميديا.

خاصية Bit-Banding

من المميزات الرائعة بمعالجات ARM Cortex-M4 حيث يتم التحكم ببت واحد عن طريق الكتابة لورد كاملة word والورد تعني ٤ بايت. فاذا اردنا مثلا تغيير قيمة بت معين وليكن البت ٢ لمتغير موجود بالذاكرة رام فالمعالج يقوم اولا بعملية قراءة للورد الذى يحتوي عليها هذا المتغير وجلب قيمته ثم تغييرها وبعد ذلك يتم كتابتها مرة اخرى وهذا يستغرق ٣ دورات واذا حدثت مقاطعة اثناء هذه العملية سيكون الوضع غير جيد.

وبفضل خاصية Bit-Banding يمكن اتمام العملية السابقة بخطوة واحدة فقط عن طريق الكتابة مباشرة لورد كاملة بمكان أخر ويتم أوتوماتيكيا تغيير البت الذى أردناه، الفكرة هنا ان المعالج ٣٢ بت يتعامل أسرع مع ورد كلمة وليس بت محدد.

نرى في الصورة الاتية الاماكن المخصصة لعمليات Bit-Banding للرام كما هناك ايضا منطقة Bit-Banding مخصصة للنهايات الطرفية.

07

نرى Bit band region للرام عند العنوان الاتي 0x20000000 ومساحتها ١ ميجا وما يعادلها وهي منطقة Bit band alias عند العنوان 0x22000000 ومساحتها ٣٢ ميجا وذلك لان كل ورد تحتوي على ٣٢ بت. ولحساب عنوان منطقة Bit band alias المقابل لمنطقة Bit band region نستخدم المعادلة الاتية:

bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number x 4)

فمثلا اذا اردنا الوصول للبت رقم ٢ من العنوان 0x20000000 نقوم بحساب عنوانها في منطقة Bit band alias كما يلي:

bit_band_base = 0x22000000
byte_offset = 0x20000000 - 0x20000000 = 0
bit_word_addr = 0x22000000 + 0*32 + (0x2 x 0x4) = 0x22000008

والان نقوم بكتابة الورد الموجودة بالعنوان الاتي 0x22000008 بالقيمة صفر أو واحد فقط طبعا لانها تمثل بت وأوتوماتيكيا سيتم تغيير البت الثاني بالعنوان 0x20000000

bit-band

سنقوم بعمل مثال تطبيقي على Bit-Banding لاحقا عند التعامل مع الهاردوير.

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

الدرس في صورة فيديو

4 إعجابات

لو حضرتك تكتبها انجلش افضل لأنه ممكن تتفهم 512 ميجا bytes !

ما هي هي ؟؟ ٥١٢ ميجا بايت = 512 ميجا bytes
بصراحة مش فاهم قصدك ؟؟

إعجاب واحد (1)

اقصد انها 512 Mbit ميجا بت

هي فعلا بايت وليس بت

512 Mega Bytes

البروسيسور بينظر للذاكرة على انها سلسلة من bytes فأول عنوان هيكون 0x00000000 والعنوان اللي بعده هيكون 0x00000004 لان البروسيسور بتاعنا ٣٢ بت فهيقدر يكتب ٤ بايت في الذاكرة دفعة واحدة لحد ما نوصل لأخر عنوان وهو 0xFFFFFFFF والرقم ده لو حولته للنظام العشري هيكون 4294967295 يعني ٤ جيجا بايت.

عموما لما هنتكلم على الذاكرة يبقي بالبايت اما لو هنتكلم على سرعة نقل البيانات مثلا كسرعة النت بنتستخدم البت

إعجاب واحد (1)

أستأذنك ممكن ايميل حضرتك,
https://goo.gl/49CvkW

إعجاب واحد (1)

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

إعجاب واحد (1)

الفيديو أجاب على تساؤلات كثيره فجزاك الله خير

إعجاب واحد (1)

السلام عليكم ورحمة الله وبركاته
انا قرأت و سمعت الفديوهات الى الدرس الثالث اكثر من مرة لكن تقريبا نسبة فهمي للموضوع الى الان في حدود 30 % كثير من المصطلحات لم افهمها ولم اقدر على تخيل الموضوع وربط الافكار
.انا ادرس بالفرقة الاولى ميكانيكا اريد فهم هذا المعالج لعله ينفعني في مشروع تخرج او يكون اضافة لى , بماذا تنصحني هل اكمل ام اننى لن استطيع تحصيل الفائدة…

إعجابَين (2)

للتوضيح فالدرس الثالث والرابع معا عبارة عن مقدمة عن المعالج وهي ضرورية قبل ان نبدا عملي على الاقل يكون عندنا فكرة بسيطة.

الدرس الرابع سيتم تعديله واضافة بعض الموضوعات رايت انها مهمة للمقدمة وسيتم اعداد الفيديو في خلال الاسبوع القادم ان شاء الله.

وسيكون هناك درس خاص لبعض الموضوعات في الدرس مثلا Interrupts سيكون لها درس خاص كذلك ISA ولغة الاسمبلي سيتم التحدث عنها بالتفصيل في درسين. كذلك سيكون هناك درس للتعامل مع الذاكرة.

ولذلك لا داعي للقلق حول بعض الموضوعات التي لم يتم تغطيتها بصورة كافيه لانه سيتم اعادة شرحها بتفصيل اكثر

إعجاب واحد (1)

اهلا مهندس مصطفي
شكرا على متابعتك والاهتمام بالدروس.

في الحقيقة معالجات ARM Cortex-M وبرمجتها تعتبر نوعا ما متقدمة وصعبة حتى لمن لدية خبرة ببرمجة الميكروكنترولر ولكن الموضوع ليس مستحيل يمكنك المتابعة وفي حالة وجود اي جزء صعب الفهم ممكن اساعدك بتوضيحه اكتر.

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

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

إعجاب واحد (1)

جزاك الله خيرا .
طمأنت قلبي طمأن الله قلبك .
مستمر باذن الله .

إعجاب واحد (1)

احب اضيف كمان انه مهم جدا انك تكون عارف برمجة كويس ودي اهم حاجة ولازم تتعملها وهتفيدك في كل حاجة ولو انت عندك اهتمام بالميكروكنترولر يبقي يفضل انك تتعلم لغة السي وحتى ممكن تبدا بيها وسيكون سهل عليك تتعلم اي لغة تانية لو حبيت

إعجاب واحد (1)

ان شاء الله سيتم العمل على ذلك ,الله المستعان

إعجاب واحد (1)

ربنا يبارك لنا في المهندس أحمد الديب زي ما تفضل بالتأكيد على لغة البرمجة السي، ثم أرشح لك بعض الأساسيات، أول ثماني دروس من هذه القائمة
https://goo.gl/eJQEyj

إعجابَين (2)

جزاك الله خيرا مهندس عبدالله

إعجاب واحد (1)

pc register will be changed every fetch happened its ok then if it find

a function it will make a jump to the new address and pc register will be the

next instruction in the function and the link register will save the return

address which means when the function end pc register will take the value

in link register am i right !! if so then what happened if there is 2

nested function calling how the link register save 2 return addresses?

Yes, you are right, but when you want to call funtion 2 from the current function 1, you will need to store the current link register into the stack before you call function 2, this is the return address of function 1.

Now you go to function 2, the link register will be updated with return address of function 2, after function 2 is finished you return back to function 1. But the link register is now with return address of function 2, so now you will need to load the link register with the value saved in the stack which is the return address of function 2.

إعجابَين (2)

يعطيك الف عافيه

إعجاب واحد (1)

هو الرقم ده 0xFFFFFFFF لو حولته للنظام العشري هيكون 4294967296 يعني ٤ جيجا بايت وليست 4 ميجا بايت

إعجاب واحد (1)