در بخش قبل مبانی کلی سیستم عاملهای بلادرنگ به طور مفصل شرح داده شد. در این بخش و چهار بخش بعدی به معرفی و چگونگی استفاده از سیستم عامل FreeRTOS با چند مثال عملی پرداخته شده است. FreeRTOS یک سیستم عامل رایگان و متن باز است که برای میکروکنترلرها و پردازندههای کوچک طراحی شده است. این سیستم به گونه ای بهینه شده است تا حد امکان ساده و کوچک باشد. همچنین استفاده از آن نیز بسیار ساده است. FreeRTOS به زبان C گسترش داده شده است و به گونه توسعه داده شده است تا بسیار Portable باشد. در FreeRTOS دارای اکثر ویژگیهای سیستم عامل بلادرنگ از جمله سمافور و Queue و … است. این سیستم عامل از بیش از 27 پلتفرم مختلف ازجمله AVR، ARM و … پشتیبانی میکند.
سیستم عامل FreeRTOS دارای یک شبیه ساز بسیار دقیق است است که با استفاده از آن میتوان رفتار سیستم عامل در آن شبیهسازی نمود و بینش بیشتری نسبت به آن بدست آورد.
در این پروژه از نرم افزار STM32CubeMX برای مدیریت سیستم عامل نظیر ایجاد تسک، سمافور و … بصورت گرافیکی استفاده شده است. لازم به ذکر است که میتوان بدون استفاده از نرم افزار STM32CumeMX نیز سیستم عامل FreeRTOS را به نرم افزار اضافه نمود. برای این منظور باید فایلهای موردنیاز را بصورت دستی اضافه و تنظیمات آن را در برنامه تنظیم کرد.
سخت افزار مورد نیاز
هر یک از میکروکنترلرهای 32 بیتی شرکت ST. در این پروژه از بورد STM32F4DISCOVERY استفاده شده است.
نرم افزار مورد نیاز
stm32cubemx
یک نرم افزار برای کامپایل و پروگرم کردن میکروکنترلر. در این پروژه از بورد IAR استفاده شده است.
نحوه فعال نمودن FreeRTOS در نرم افزار STM32CubeMX
برای اضافه نمودن FreeRTOS به نرم افزار ابتدا در نرم افزار STM32CubeMX از قسمت Middleware بر روی گزینه FreeRTOS کلیک کنید (شکل 1) تا پنجره FREERTOS Mode and Configuration که در شکل 2 نشان داده شده است، باز شود. سپس از قسمت Interface گزینه CMSIS_V1 را انتخاب کنید. در اینجا از ورژن یک CMSIS استفاده شده است. ولی میتوان از ورژن دوم آن نیز استفاده نمود.
با فعال نمودن FreeRTOS صفحه Configuration باز میشود. در این قسمت میتوان کلیه تنظیمات لازم را بصورت گرافیکی انجام داد. در سربرگ Config parameters تنظیمات و کانفیگهای FreeRTOS تنظیم میشوند.
برای ایجاد تسک به سربرگ Tasks and Queues که در شکل 3 نشان داده شده است، بروید.
برای ایجاد تسک بر روی دکمه Add کلیک کنید تا پنجره New Task باز شود. فیلدهای این پنجره عبارتند از:
Task Name: نام تسک را مشخص میکند. نام تسک فقط برای دیباگ کاربر قرار داده شده است.
Priority: اولویت تسک است. تعداد سطوح اولویت در سربرگ Config parameters فیلد MAX_PRIORITY تنظیم میشود.
Stack Size: اندازه حافظه Stack تسک را مشخص میکند.
Entry Function: نام تابع مرتبط با تسک است. هنگام شروع تسک این تابع فراخوانی میشود.
Code Generation Option: چگونگی ایجاد Entry Function را مشخص میکند.
Parameter: آرگومان پاس داده شده به تسک است.
Allocation: چگونگی اختصاص حافظه مورد نیاز تسک را مشخص میکند که میتواند بصورت Static و Dynamic باشد. در صورتیکی Static باشد از حافظه Stack و اگر Dynamic انتخاب شود از حافظه Heap استفاده میشود.
در این پروژه دو تسک با اولویت یکسان درست شده است. در شکل 4 نحوه تنظیم تسکها نشان داده شده است.
با توجه به اینکه همواره باید یک تسک برای اجرا وجود داشته باشد، نرم افزار STM32cumeMX بصورت پیشفرض یک تسک به نام defaultTask ایجاد میکند. برای تغییر مشخصههای آن بر روی دو بار کلیک کنید تا پنجره Edit task باز شود.
FreeRTOS نیازمند واحد یک تایمر سخت افزاری برای Scheduling و … استفاده میکند. در نرم افزار STM32CubeMX تایمر systick به سیستم عامل اختصاص میدهد. لذا برای انجام تنظیمات سیستم و کتابخانه HAL از یک تایمر دیگر باید استفاده نمود. در این پروژه از تایمر یک , پورت USART3 برای ارسال داده به کامپیوتر استفاده شده است.
پس از انجام تنظیمات فوق به سربرگ Project Manager رفته و پس از وارد کردن نام، مسیر ذخیره آن و انتخاب نرم افزار دیباگر بر روی گزینه Generate Code کلیک کرده تا کد نرم افزار اولیه ایجاد شود. در این پروژه از نرم افزار IAR Embedded Workbench برای کامپایل و پروگرم استفاده شده است.
پس از باز نمودن پروژه ایجاد شده میتوانید ملاحظه کنید که نرم افزار STM32CubeMX برای ایجاد تسک برنامه زیر را به نرم افزار اضافه کرده است:
همچنین برای توابع funcTask1 و funcTask2 را به برنامه اضافه کرده است.
لازم به ذکر است که علاوه بر تسکهایی که کاربر مشخص کرده است، تسکهای دیگری از جمله تسک IDLE را سیستم عامل ایجاد می کند تا هنگامی که هیچ تسکی برای اجرا وجود نداشت، اجرا شود. در بخشهای بعدی چگونگی و اهمیت استفاده از تسک idle بیان خواهد شد.
بررسی برنامه ایجاد شده
همانطور که ملاحظه میکنید نرم افزار STM32CubeMX دو تسک با نامهای Task1 و Task2 ایجاد نموده است. ماکروی osThreadDef بصورت زیر تعریف شده است.
این ماکرو یک structure از جنس osThreadDef با نام os_thread_def_##name ایجاد می¬کند. عملوند ## یک عملوند Preprocessor است که دو رشته کاراکتری را در به هم می¬چسباند. تابع osThreadCreate با استفاده از تابع xTaskCreate تسک جدید ایجاد می کند. الگوی تابع xTaskCreate بصورت زیر است:
لذا برای ایجاد تسک میتوان مستقیما تابع xTaskCreate را فراخوانی نمود.
مثال اول: اجرای دو تسک
هدف از این مثال مشاهده اجرای همزمان و مستقل دو تسک است. لذا دو تسک مستقل ایجاد نموده و هر تسک بصورت متناوب داده ای را از پورت سریال ارسال میکنند. توابع funcTask1 و funcTask2 بصورت زیر نوشته شده است.
مثال دوم: حذف تسک
در مثال اول هر دو تسک در تابع main ایجاد شدند. در این مثال نحوه ایجاد یک تسک توسط تسک دیگر و چگونگی حذف تسک آن بررسی شده است. لازم به ذکر است که هیچ تسکی نباید به پایان برسد. در صورتیکه دیگر نیازی به تسک موردنظر نباشد باید صریحا با استفاده از تابع vTaskDelete حذف شود.
در این مثال ابتدا فقط Task1 وجود دارد. بعد از مدتی Task1، Task2 را ایجاد کرده و بعد از مدتی Task1 را متوقف کرده است.
کد این برنامه بصورت زیر است:
مثال سوم: پاس دادن آرگومان به تسک
برای این منظور تنها کافیست تا آدرس یا اشاره گر داده موردنظر را هنگام ایجاد تسک به آن بدهیم. با توجه به اینکه تنها میتوان یه پارامتر به تسک داد، برای ارسال پارمترهای بیشتر میتوان یک struct تعریف نمود و کلیه پارمترهای مورد نیاز را در آن قرار داد.