المكتبة Syra uOS للمعالجات التحكمية – الأساسيات

المكتبة Syra uOS  هي نظام غير متزامن تعتمد على مبدأ الأحداث . وهي مصممة لبناء تطبيقات قابلة للتوسع للمعالجات التحكمية.
تكلمنا في المرحلة السابقة عن سبب تصميم هذه المكتبة . وما تقدمه من حلول وتسهيلات في بناء تطبيقات المعالجات التحكمية .
ويمكن الاطلاع على الجزء السابق من الرابط التالي :
المكتبة Syra uOS للمعالجات التحكمية – المقدمة

في البداية نذكر لمحة بسيطة عن مكونات المكتبة وكيفية استخدامها.
يمكن تحميل نسخة من هذه المكتبة للمعالج المطلوب التعامل معه من الرابط التالي :
Syra_uOS_Downloads

تتكون هذه المكتبة من مجموعة من الملفات المتوافقة مع بعضها والموزعة بالشكل التالي :

  • مجموعة من الملفات الرئيسية هي  inc.h, main.c, config.h   تم تجهيزها لتكون وسيلة الربط بين المبرمج والمكتبة .
  • ومجلد إسمه SMF ، يحتوي باقي أجزاء المكتبة . وتمثل نواة النظام . لا تحتاج تعديل من المبرمج ، أو لا يجب ان يتم التعديل بها ، لأنها تعمل بشكل متوافق مع بعضها .
  • الملف  main.c  : في هذا الملف يتم تسجيل المهام  ليقوم النظام بتنفيذها ، ويتضمن هذا الملف ثلاثة أقسام أساسية :
  • – التابع onReset . في هذا التابع نكتب ما نريد من المعالج أن ينفذه في بداية التشغيل . أي بعد توصيل الكهرباء مباشرة .
    – التابع onBoot . وفيه يتم كتابة  الجزء الذي يريد المبرمج ان يتم تنفيذه عند مرحلة الاقلاع BOOT . أو بعد الخروج من وضع الاستعداد أو وضع توفير الطاقة .
    – التابع onSleep . ويمثل مرحلة ماقبل الدخول في وضع توفير الطاقة . حيث يمكن كتابة الأوامر التي نريد تنفيذها قبل أن يتوقف المعالج عن العمل والدخول في وضع الاستعداد .
  • – التابع Main_Task . وهو المهمة الافتراضية , التي تم إنشائها لتكون المهمة الأولى في النظام وهي مسجلة مسبقا ولا تحتاج تعريف أو تسجيل . ويتم تنفيذ هذه المهمة بشكل متكرر طوال فترة عمل المعالج ضمن نواة النظام .
    ويمكن الاكتفاء بها إذا كان المشروع لا يحتاج الكثير من المهام .
  • الملف config.h  : يستخدم لكتابة معلومات الإعدادات للمشروع ، مثل تحديد عدد المهام وغيرها من الاعدادات لكامل المشروع.
  • الملف inc.h : هذا الملف هو وسيلة الربط بين أجزاء المكتبة وباقي الملفات في المشروع ، وفيه يتم تعريف كل الملفات التي نضيفها في المشروع . فإذا قمنا بإنشاء ملف جديد في المشروع , نقوم بإضافته لهذا الملف.

والشكل التالي يوضح مخطط عمل النظام في المكتبة :


حيث عند توصيل الكهرباء Power ON يبدأ المعالج بالعمل . وهنا يتم تنفيذ التابع onReset .
ثم ينتقل التنفيذ لنواة النظام . حيث يبدأ في تهيئة النظام للعمل والدخول في مرحلة الإقلاع . وهنا يتم تنفيذ التابع onBoot .
وبعدها ينتقل النظام لتنفيذ المهام المكتوبة واحدة تلو الأخرى . وذلك ضمن ما نسميه بحلقة المهام . وفي البداية لدينا المهمة الافتراضية المتمثلة بالتابع Main_Task .
ويستمر النظام بتنفيذ هذه المهام واحدة تلو الأخرى بشكل متكرر . حتى يتم الطلب بالدخول في وضع الاستعداد أو توفير الطاقة .
فإذا تم طلب الدخول في وضع توفير الطاقة يتم تنفيذ التابع OnSleep . ثم يتوقف المعالج عن العمل .
ويبقى المعالج في وضع توفير الطاقة ينتظر الأمر بالعودة لمرحلة الإقلاع من جديد وإعادة المراحل السابقة .
أما عن كيفية الطلب من النظام الإنتقال من وضع العمل إلى وضع الاستعداد وتوفير الطاقة . فسيتم شرحه بالتفصيل لاحقاً.

إنشاء مشروع في بيئة البرمجة Microchip Studio :

لنقوم الآن بالتطبيق العملي . حيث نحتاج بيئة البرمجة ATMEL Studio , وهي من تصميم شركة ATMEL التي أصبحت ملكاً لشركة Microchip . وهي مجانية ومتاحة للجميع . ولكن تم تغيير إسم البرنامج ليصبح Microchip Studio .
يمكن تحميل بيئة البرمجة هذه من الرابط التالي:
Microchip Studio for AVR® and SAM Devices

لنبدأ بإنشاء مشروع جديد في بيئة العمل  Microchip Studio . وذلك من القائمة File , نختار New , ثم Project . كما في الشكل :

ثم تظهر لنا نافذة الإعداد . نكتب فيها إسم المشروع وليكن SuF_Example . ونحدد مكان حفظ المشروع وكذلك نوع المشروع .
كما في الشكل التالي :

بعدها تظهر شاشة جديدة نختار منها المعالج الذي نريد كتابة البرنامج من أجله , وليكن مثلا ATxmega16A4U .

ثم بالضغط على OK يتم إنشاء المشروع . والذي في البداية يتضمن فقط ملف واحد إسمه main.c . وفيه مكتوب برنامج إفتراضي بسيط .
وما علينا الآن هو أن نقوم بإضافة المكتبة Syra uOS إلى هذا المشروع وذلك كما يلي .
أولا بشكل عام . من شريط الأدوات نقوم بتغيير وضعية العمل من Debug إلى Release .
ثانيا نقوم بحذف الملف main.c الذي تم إنشائه تلقائيا .

نقوم بتحميل المكتبة . والتي متوفرة على الرابط التالي : Syra_uOS_XMEGA_R1.4.0
هذا الرابط خاص بالمعالجات XMEGA , ويمكن تحميل النسخة التي تتوافق مع أي معالج أخر مدعوم من صفحة التحميل
Syra_uOS_Download
تكون ملفات المكتبة مضغوطة في ملف zip . نفك ضغط هذا الملف في مجلد المشروع .

ثم نذهب إلى بيئة البرمجة Microchip Studio . ونقوم بإضافة ملفات المكتبة للمشروع وذلك كما يلي :
– من النافذة Solution Explorer  نحدد المشروع . ثم نضغط على زر إظهار جميع الملفات كما في الشكل :

فتظهر جميع الملفات التي تم نسخها إلى مجلد المشروع . ثم نقوم بتحديد ملفات المكتبة جميعها .
ونضغط نقرة باليمين على الملفات المحددة ، فتظهر قائمة نختار منها Include in Project :

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

طريقة استخدام المكتبة

بشكل افتراضي كل شيء جاهز ولا يحتاج تعديل . ويمكن البدء مباشرة بكتابة أول مهمة . وبما أنه يوجد مهمة افتراضية تم إنشائها مسبقا . سوف نستخدمها في هذه المرحلة .
كل ما علينا فعله هو فتح الملف main.c والنظر في داخله فنجد التوابع التالية .

/*
// main.c الملف
*/

//-------------------
// هنا هذا السطر هو تعريف ملف الربط
#include "inc.h"

//-------------------
// هذا التابع يتم تنفيذه مرة واحدةعند تشغيل المعالج مباشرة
void OnReset()
{
}

//-------------------
// هذا التابع يتم تنفيذه في مرحلة الاقلاع
void OnBoot()
{
} 

//-------------------
// هذا التابع يتم تنفيذه قبل الدخول في وضع الاستعداد
void OnSleep()
{
}

//-------------------
// هذا التابع هو المهمة الافتراضية
void Main_Task()
{
}

كتابة التعليمات لتشغيل ضوء متقطع

لنفرض نريد استخدام المهمة الإفتراضية لتقوم بتشغيل ضوء LED بشكل متقطع . وليكن مرة كل ثانية .
كما بدأنا الشرح بإنشاء مشروع لكتابة برنامج لمعالج من نوع XMEGA . سوف نكمل المثال هذا لنفس المعالج .
ولكن هذه الطريقة يمكن تطبيقها للعمل مع أي نوع من المعالجات التي تدعمها هذه المكتبة .

لنفرض الضوء موصول مع المعالج على الطرف الأول PIN0 المرتبطة بالبوابة A .
وبالتالي الخطوات المطلوبة هي التالي :
– أولا أن نحدد إتجاه هذا الطرف . وهنا نحتاج أن يكون هذا الطرف عبارة عن خرج . وهذا يجب أن يتم في مرحلة الإقلاع قبل تنفيذ المهمة . لذلك نكتب التعليمة الخاصة بذلك في التابع OnBoot .
– ثانياً نكتب تعليمات تشغيل و إطفاء الضوء في التابع Main_Task . لأنه هو تابع المهمة الذي يعمل خلال فترة التفيذ المستمر .
فيصبح البرنامج بالشكل التالي :

// تابع الإقلاع
void OnBoot()
{
   // تحديد إتجاه الطرف
   PORTA_DIRSET = PIN0_bm ;

} 

// تابع المهمة
void Main_Task()
{
  // تعليمة تغيير حالة الطرف
  PORTA_OUTTGL = PIN0_bm ;
  
  // تعليمة الانتظار
  TaskWait(500); 
}

البرنامج السابق واضح وبسيط ولكن سنشرح التعليمات .
التعليمة PORTA_DIRSET = PIN0_bm مهماتها تحديد إتجاه الطرف الأول من البوابة A على أنها خرج .

التعليمة PORTA_OUTTGL = PIN0_bm مهمتها تغيير أو قلب حالة الطرف . فإذا كان 1 منطقي يصبح 0 . والعكس بالعكس . وبذلك يتغير الجهد الكهربائي المطبق على الضوء ويتغير بين حالة إضائة و عدم إضائة .

الجديد هنا هو التعليمة TaskWait . وهي من أوامر المكتبة . حيث من خلالها يتم الطلب من النظام أن ينتظر لمدة زمنية تقدر بواحدة الميلي ثانية قبل إعادة تنفيذ هذه المهمة من جديد . وهنا في حالتنا الفترة اخترناها 500 ميلي ثانية .
وبذلك يمكن أن نتخيل أن هذه المهمة ستتكرر بعد نصف ثانية . ويتكرر معها تنفيذ تعليمة تغيير إضائة الضوء .
وبذلك لا نحتاج أن نستخدم أي نوع من توابع التأخير delay أو أي حلقة متكررة تستهلك من طاقة المعالج .
وإنما ينتقل المعالج لتنفيذ باقي العمليات . بينما هذه المهمة في حالة انتظار .

قواعد هامة

نلاحظ أننا استخدمنا تعليمة جديدة للتعامل مع الزمن وهي TaskWait . ولم نستخدم حلقات التأخير .
يجب أن يتم الانتباه بعدم استخدام الحلقات الغير منتهية . وعدم استخدام توابع التأخير الزمني delay إلا عند الضرورة .
وإذا اضطر الأمر لاستخدامها يجب الأخذ بعين الاعتبار أن جميع المهام متوقفة بانتظار هذه الحلقة حتى تنتهي .

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

المثال التالي هو استخدام خاطئ ويستهلك طاقة المعالج بدون فائدة . ويبطل عمل النظام :

void Main_Task()
{
  // هذا استخدام خاطئ
  // وفيه ضياع للطاقة
  while(1)
  {
     PORTA_OUTTGL = PIN0_bm ;
     _delay_ms(1000);
  }
}

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

وهكذا نكون قد انتهينا من التعريف بالمكتبة Syra uF و كتابة أول برنامج بسيط  بالاعتماد عليها.
في المرحلة القادمة سوف نتعرف على كيفية كتابة مهام إضافية غير المهمة الأساسية Main_Task . وسنتعرف على كيفية تسجيل هذه المهام في النظام ليتمكن من تنفيذها حسب المطلوب .