المكتبة Syra uOS للمعالجات التحكمية – SAM 32Bit

في هذه المرحلة سوف نتعرف على كيفية استخدام هذه المكتبة مع معالجات SAM التي هي معالجات 32 بت من نوع ARM Cortex-M0 . من إنتاج شركة Microchip .
تعرفنا في السابق على كيفية إنشاء مشروع جديد باستخدام المكتبة Syra uF  . والتي هي نظام غير متزامن تعتمد على مبدأ الأحداث . وهي مصممة لبناء تطبيقات قابلة للتوسع للمعالجات التحكمية.
سنختار عائلة المعالجات SAMD20 لهذه الدورة . ويمكن تحميل نسخة من هذه المكتبة من الرابط التالي :
Syra uF ARM SAMD20 Release v1.4.0
وللإطلاع على الأجزاء السابقة من هذه الدورة , نجدها في الروابط التالية :
المكتبة Syra uF للمعالجات التحكمية – المقدمة
المكتبة Syra uF للمعالجات التحكمية – الأساسيات

في هذا الجزء سوف نتعلم كيفية كتابة المهام الجديدة . وإضافتها للمشروع . وتسجيلها في النظام .
سنأخذ مثالاً عن كتابة مهمتين لتشغيل أضواء LED موصولة مع أطراف المعالج .
لنفرض الضوء الأخضر موصول مع الطرف الأول PA00 من البوابة A .
والضوء الأحمر موصول مع الطرف الثاني PA01 من البوابة A .

أولا نقوم بإنشاء مشروع جديد في بيئة البرمجة ATMEL Studio . وهذا ما تم شرحه سابقاً في الأجزاء السابقة من هذه الدورة .
ولنفرض أننا اخترنا الاسم SuF_Example للمشروع . وتختار نوع المعالج ATSAMD20E17A على سبيل المثال .

إضافة المهام للمشروع :
أولا نقوم بإضافة  ملف جديد للمشروع  لنكتب فيه الكود الخاص بهذه المهام وذلك كما يلي :

  • من نافذة Solution Explorer   نضع المؤشر على  اسم المشروع  ونضغط بالزر اليمين .
  • تظهر قائمة نختار منها Add   لإضافة عنصر جديد ، فتظهر قائمة جديدة صغيرة .
  • نختار منها New Item   كما في الشكل اتالي :

بعدها تظهر نافذة جديدة  نختار فيها نوع الملف الذي نريد إضافته ،  ونكتب اسم الملف  الذي نريده .
في مثالنا هذا نختار نوع الملف C File   لاننا نريد إضافة ملف لكتابة كود بلغة  C   .
ونكتب اسم الملف tasks.c لأننا سنكتب فيه جميع المهام ، وهذا لسهولة الشرح .
لكن بشكل عام يفضل كتابة كل مهمة في ملف منفصل وذلك لتمييز الملفات في المشروع عن بعضها .
ثم نضغط على Add  لإضافة الملف للمشروع .

  • نعيد الخطوات السابقة وذلك لإضافة  ملف ثاني  من نوع  Include File  ، وهذا من متطلبات لغة البرمجة C  .
    أيضا نختار الاسم نفسه  للملف الجديد tasks.h ، ثم نضغط  Add  .

هكذا يصبح لدينا ملفين جديدين في المشروع كما في الشكل :

في البداية هذه الملفات فارغة ، لذلك نفتح الملف tasks.c   لكتابة المهمة الأولى .
قلنا أن المهمة الأولى وضيفتها تشغيل وإطفاء الضوء الأخضر بشكل متكرر . مرة كل ثانية .
قلنا أن الضوء الذي لونه أخضر موصول مع الطرف الأول PA00 من البوابة A .
أولا  يجب أن نحدد هذا الطرف على أنه خرج ، وهذا يكون مرة واحدة عند بداية البرنامج ، أي في مرحلة الاقلاع .
لذلك  نكتب الأوامر التي نريدها أن تعمل مرة واحدة عند الإقلاع بشكل منفصل ضمن تابع خاص . نعتبره تابع التهيئة للمهمة .
وهنا لدينا مهمتبين . سنكتفي بتابع تهيئة واحد للمهمتين .
مثلا  نكتب التابع التالي ونعطيه اسم اختياري وليكن  tasks_Setup

ونكتب بداخله  أوامر تعريف الطرف المطلوب على انه خرج كما يلي :

void tasks_Setup()
{
    //  تحديد الطرف الموصول مع الضوءالأخضر على أنه خرج
    REG_PORT_DIRSET0 = PORT_PA00;
    //  قد نحتاج تحديد قيمة أولية للطرف
    // هنا مثلا نختار أن يكون الضوء منطفئ
    REG_PORT_OUTCLR0 = PORT_PA00;
	
    //  تحديد الطرف الموصول مع الضوءالأحمر على أنه خرج
    REG_PORT_DIRSET0 = PORT_PA01;
    //  قد نحتاج تحديد قيمة أولية للطرف
    // هنا مثلا نختار أن يكون الضوء منطفئ
    REG_PORT_OUTCLR0 = PORT_PA01;
}

طبعا بالتأكيد يمكن ان نكتب جميع الأوامر التي نريدها أن تنفذ عند الإقلاع ضمن هذا التابع .

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

REG_PORT_OUTTGL0 = PORT_PA00 ;

ثم الانتظار لمدة ثانية او 1000 ميلي ثانية ، من خلال الامر التالي :

TaskWait(1000);

فيصبح التابع بالشكل :

//  مهمة الضوء الأخضر
void Green_Task()
{
	//  هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأخضر
	 REG_PORT_OUTTGL0 = PORT_PA00;
	 
	 //  هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة
	 TaskWait(1000);
}

نكرر نفس العملية السابقة لإضافة مهمة ثانية خاصة بالضوء الأحمر ، مع مراعاة أن الضوء الأحمر موصول مع الطرف الثاني من البوابة PORTA . وأن هذه المهمة سيتم تنفيذها كل 500 ميلي ثانية.
وهنا تصبح المهمة بالشكل التالي :

//  مهمة الضوء الأحمر 
void Red_Task()
{
	//  هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأحمر
	REG_PORT_OUTTGL0 = PORT_PA01;
	
	//  هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة
	TaskWait(500);
}

هكذا نكون قد انتهينا من كتابة توابع المهام المطلوبة ،  وكذلك  تابع التهيئة .

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

تسجيل المهام في النظام :

أولا بحسب قواعد البرمجة بلغة C . يجب إضافة تعريف التوابع التي كتبناها سابقة جميعها في الملف tasks.h , وذلك لتصبح مرئية لباقي أجزاء المشروع.

/*
 * tasks.h  الملف
 */ 

void tasks_Setup();

void Green_Task();
void Red_Task();


ثانيا نضيف تعريف للملف tasks.h في الملف inc.h الذي قلنا أنه وسيلة الربط بين أجزائ المشروع.
فيكون محتوى الملف inc.h كما في الشكل :

/*	
// inc.h	
*/

#include "SMF/core.h"

#include "main.h"

//--------------------------
// في هذا المكان نضيف التعريف
#include "tasks.h"

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

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

/*
// main.c
*/

void OnBoot()
{
	
	// استدعاء تابع التهيئة للمهام
	tasks_Setup();
	
	
	// تسجيل المهمة الأولى في النظام
	Sys_CreateTask(Green_Task);
	
	// تسجيل المهمة الثانية في النظام
	Sys_CreateTask(Red_Task);
	
	// الآن كل شيئ جاهز للعمل
	
}
 

هكذا نكون قد انتهينا من كتابة المهام المطلوبة ، وتابع التهيئة ، وقمنا بتسجيل جميع المهام في النظام بشكل جيد .

نقوم ببناء المشروع من خلال الأمر Build   في  بيئة البرمجة .
وبعدها  ننقل الملف التنفيذي الناتج للمعالج عبر المبرمجة للتجريب العملي .

وهكذا نكون قد انتهينا من كتابة برنامج للمعالج التحكمي يحتوي أكثر من مهمة . بالاعتماد على المكتبة  Syra uF .