با توجه به زمان زیادی که از انتشار دو قسمت قبل آموزش RTOS گذشته است، توصیه میکنم قسمت های قبل مقاله رو بخوانید حتی به شکل مرور تیتروار ( آشنایی با مفهوم چندوظیفهگی)! در قسمت قبلی همونطور که از عنوان نوشته بر میآید، توضیح دادیم که چند وظیفهگی چطور میتواند توی خرد کردن یک پروژه بزرگ به بخشهای کوچک به ما کمک کنه و چطور میتواند با مدیریت منابع باعث سادگی در ساختار کد شود، اما سوال اساسی که مطرح میشود این است که چطور باید چند وظیفه مختلف را به یک پردازنده (CPU) بسپاریم؟ مگر این نیست که تمام پردازندهها تنها یک نقطه شروع بعد از ریست دارند پس چطور میتوان چند کار مختلف را به یک پردازنده سپرد! در این قسمت مقاله سعی میکنیم به این سوال کلیدی پاسخ بدهیم، با سیسوگ همراه باشید.
آشنایی با ساختار CPU
برای این که بتوانیم یک سیستم عامل را پیاده سازی کنیم، لازم است وارد جزییات سخت افزاری شویم، جزییاتی در حد رجیسترهای cpu و ساختار و نحوه عملکرد آن! در واقع تا مادامی که نتوانیم درک کنیم cpu برای اجرای برنامه از چه الگویی پیروی میکند نخواهیم توانست عملکرد سیستم عامل را درک کنیم.
همانطور که احتمالا میدانید cpu برای این که بتواند دستورات را اجرا کند لازم است آنها را از محلی بخواند، بسته به ساختار سختافزار این محل میتواند حافطه RAM یا flash یا دیسک یا هر نوع حافظه دیگری باشد اما نکتهای که در این گفتمان وجود دارد این که است که cpu چگونه میتواند بفهمد تا کجای برنامه را خوانده است؟
رجیستر PC
برای این کار رجیستر منحصر بفردی در cpu وجود دارد که وظیفه آن شمارش دستورات خوانده شده است یا به صورت دقیقتر وظیفه آن نگهداری آدرسی است که قرار است دستور بعدی از آنجا خوانده شود. احتمالا شنیده باشید که فلان cpu قادر به آدرسدهی فلان مقدار حافظه است، این گفته دقیقا اشاره به تعداد بیتهای در نظر گرفته شده برای این رجیستر دارد. برای مثال وقتی میگوییم که میکروکنترلر AVR قادر به آدرس دهی ۶۴ کیلو بایت حافظه است یعنی رجیستر شمارنده برنامه ۱۶ بیت است و یا وقتی میگوییم که میکروکنترلر ARM قادر به آدرسدهی ۴ گیگابایت حافظه است یعنی طول این رجیستر در این مدل میکروکنترلر ۳۲ بیت است (البته با ملاحظاتی که بعدا به آن اشاره خواهیم کرد).
احتمالا حدس زدهاید که اسم اختصاری این رجیستر PC است به معنی program counter و احتمالا به وفور با آن در عکسها و شماتیکالهای CPU برخورد کرده باشید.
بعد از ریست، این رجیستر با مقدار صفر بارگذاری میشود و پردازنده با مراجعه به آدرس صفر حافظه (دقت داشته باشید این آدرس میتواند مقدار دیگری هم باشد) سعی در واکشی و اجرای دستورات اسمبلی دارد. بعد از واکشی و اجرای اولین دستور مقدار این رجیستر اضافه میشود تا دستور بعد را اجرا کند این روند تا وقتی که رجیستر سرریز کند ادامه پیدا میکند.
اما چرا برنامههای کوچکتر از مقدار آدرسدهی PC میتوانند به خوبی و بدون مشکل اجرا شوند؟ بگذارید کمی واضحتر سوال را مطرح کنیم. فرض کنید برنامه چشمکزن در میکروکنترلر AVR نیاز به ۲۰ دستور اسمبلی دارد در حالی که PC برای سرریز شدن باید ۶۴ هزار دستور را اجرا کند! پس چه میشود که برنامههای کوچک بدون مشکل اجرا میشوند؟
جواب سوال ساده است ، دستوراتی وجود دارند که میتوانند مقدار PC را برنامهریزی و طی برقرار بودن یا نبودن شرایط خاصی، آدرس دلخواهی را در آن بارگذاری کنند. این دقیقا همان اتفاقی است که در هنگام استفاده از شرط ها در برنامه نویسی میافتد یا هنگام صدا زدن یک فانکشن خاص.
رجیستر Link
همانطور که در بخش قبل گفتیم دستوراتی وجود دارند که قادر هستند کنترل برنامه (PC) رو به آدرس دیگری منتقل کنند، وجود این دستورات برای پیاده سازی ساختار های شرطی، اساسی و لازم هستند اما فکر کنید قصد داشته باشیم در برنامه یک تابع را فراخوانی کنیم! اکنون چکار باید کرد؟
اگر از دستورات شرطی معمولی استفاده کنیم کنترل برنامه به محل تابع منتقل میشود و بعد از این که دستورات تابع اجرا شد باید به آدرس قبلی برگردد اما چطور این اتفاق میافتد؟ در استفاده از دستورات پرش شرطی این اتفاق نمی افتد! چرا که آدرس جاری برنامه در جایی ذخیره نمیشود. اما دستورهایی وجود دارند که هنگام پرش، آدرس جاری را در رجیستری تحت عنوان رجیستر LINK ذخیره میکنند تا بعد از اتمام کار تابع این آدرس در رجیستر PC قرار بگیرد و کنترل برنامه به محل قبل باز گردانده شود (منظور یک دستور بعد از آدرس پرش است).
رجیستر لینک بعد از رجیستر PC یکی از کلیدیترین رجیسترهای هر پردازندهای است چرا که برنامهنویسی به شکل زیر برنامه را در اختیار ما قرار میدهد و همه خوب میدانیم که این شکل از برنامه نویسی چقدر میتواند برنامه نویسی را ساده کند.
رجیستر SP
بعد از رجیسترهای PC و Link یکی دیگر از رجیسترهای مهم CPU رجیستر SP که مخفف stack pointer است. کار این رجیستر در واقع نگهداری آدرس stack است. اما استک چیست و به چه دردی میخورد ؟ استک داخل ram پردازنده تعریف میشود و کار آن این است که متغییرهای محلی را در خودش ذخیره کند! خوب این یعنی چی! وقتی شما تابعی مینویسید و داخل تابع یک متغییر ایجاد میکنید، چون متغییر قرار نیست در دسترس همه قرار بگیرد و احتمالا چون بعد از اتمام تابع باید ازبین برود! به جای این که داخل رم اصلی قرار بگیرد، داخل استک قرار میگیرد! یا فرض کنید وقتی تابعی را داخل تایع دیگری صدا میزنیم چطور باید آدرس برگشت را ذخیره کنیم؟ مگر نه این که تنها یک رجیستر LINK وجود دارد؟! قبل از صدا زدن تابع جدید میتوانیم مقدار رجیستر لینک را داخل استک ذخیره کنیم! و به این شکل موقع برگشت از تابعی که صدا زده ایم مقدار رجیستر LINK را بازیابی کنیم.
تمام توضیحات بالا مربوط به استک بود، و اما رجیستر sp رجیستری است داخل cpu که به محل استک اشاره میکند. تنها نکته ای که باید به آن توجه داشت این است که با اضافه شدن مقدار استک مقدار sp کاهش پیدا میکند 🙂
چرا که همیشه استک از انتهای رم شروع به پرشدن میکند. برای همین آدرس آن باید با ذخیره متغییر داخل آن کاهش پیدا کند. در مورد استک احتمالا در قسمتهای آینده بیشتر صحبت خواهیم کرد چرا که یکی از مفاهیم مهم برنامهنویسی است و البته برای مدیریت وظیفهها در سیستم عامل زیاد با آن سر و کار پیدا خواهیم کرد.
رجیستر وضعیت
این رجیسترها معمولا برای انجام پرشهای شرطی و پردازش حالتهای خاص مورد استفاده قرار میگیرند! و با استفاده از آنها قادر به پیادهسازی انواع شرطهای پیچیده هستیم البته در محاسبات ریاضی نیز میتوانند کاربرد داشته باشند که زیاد مورد بحث ما نیست.
رجیسترهای عمومی
این رجیسترها که معمولا تعداد زیادی هم دارند میتوانند برای انجام انواع عملیات مورد استفاده قرار بگیرند و دقیقا همانند اسم خود کاربرد عمومی دارند.
با توجه به اینکه رجیستر های موجود در میکروکنترلر های ARM و البته مدیریت آنها در مقایسه با پردازنده های جنرال متفاوت است در قسمت بعد به بررسی رجیسترهای Cortex-M3 و حالتهای خاص آنها خواهیم پرداخت.
سلام قسمت چهارم رو پیدا نمیکنم
کاش لینک قسمت بعدی هر اموزش رو در پایین صفحه قرار بدید (بعد از انتشار)
ممنون برای پیشنهادتون
اما در مورد این مقاله خاص – متاسفانه نوشته نشده است
سلام بسیار عالی بود لذت بردم
واقعا مطالب در سیسوگ بسیار عالیه هم برای افراد مبتدی هم برای افراد حرفه ای ، عالی عالی 💕😁
مشتاقانه منتظر قسمت بعدی اموزش هستیم
یادتون نره سیسوگ رو به دوستانتون معرفی کنید.
ممنون که مارو حمایت می کنید
درود، من بتازگی وارد این جمع شدم. ولی واقعا از نوشته ها لذت بردم. واقعا دمتون گرم!!!
برای ما هم خبر خیلی خوبیه
سلام ، زئوس عزیز . مطالبتون بسیار کاربردی و عالین. با اینکه تجربه های زیادی در خصوص embedded دارم اما هر دفعه که به مطالب شما میرسم به چیزای جدید برمیخورم . برعکس اکثر مقالات فارسی زبانی که پیدا میکنی و همه از رو هم به شکل ساده لوحانه ای کپی زدن و مطالب آموزشی سبکی مخصوص beginner ها هستن مطالب شما پر از بار علمی و بسیار کاربردی هستن . همین که تئوری مطلب هم میپردازین درک خیلی خوبی به خواننده میده که کدی که داره میزنه دقیقا اون پشت تو بکند سخت افزاری چه کاری انجام میده ، در حالی اکثریت آموزش ها سعی میکنن صرفا با مثال و اینکه چطوری از فلان ابزار استفاده کنم ( نه اینکه اون ابزار خودش چطوری اون کارو انجام میده ) آموزش بدن که خوب قاعدتا اون خواننده رو یک User فرض میکنند نه Developer یا حتی Programmer ، که خوب برای پژوهشگر هایی که میخوان عمق مطلب رو درک کنن اصن مناسب و کافی نیست.
پیگیر مباحث RTOS بودم ولی قسمت چهارمی تو سایت پیدا نکردم.
درک میکنم چقدر احتمالا سرتون شلوغه و پر مشغله هستین. با این حال اگه وقتی بود بسیار ممنون میشیم که ادامه بدید یا رفرنس در اختیارمون بذارید…
با تشکر
سلام دوست عزیز
متشکرم برای این همه انرژی مثبت 🙂 – واقعا دارم زمان بندی میکنم که آموزش ها رو پیش ببرم ولی همیشه یه چیزی مانع میشه
دارم سعی میکنم که آموزش rtos رو پیش ببرم – امیدوارم که به زودی این روند اتفاق بیفته 🙂
سلام،
شرح پروژه:
من تو یه پروژه دارم از FreeRTOS استفاده میکنم، در این پروژه منبع تغذیه هم برق شهری استفاده میشه و هم از باتری و وقتی برق شهری قطع میشه باید میکرو توی حالت LOW Power باشه، میکرو استفاده شده STM32L072RB هست
سوال:
چطور می تونم در حالت Low power FreeRTOS غیر فعال کنم؟
منظورتون واقعا اینه که چطور غیرفعال کنید؟ یا این که فعال کنید ؟
منظورم غیر فعال کردن سیستم عامل هست (وقتی که برق هست فعال باشه و وقتی که روی باتری هست غیر فعال شه)
سلام – فرض میکنیم شما به طریقی قادر هستید قطع برق را تشخص دهید. در هر تسک دلخواه این سطر رو بذارید و وارد یه حلقه شوید و سیستم عامل رو قبلش قفل کنید که سوییچ نکنه روی دیگر تسک ها با دستور vTaskSuspendAll و برای خارج شدن xTaskResumeAll رو بزنید تا دوباره سیستم عامل فعال بشه 🙂
سلام !
بعضی آموزشها وقتی میرسی قسمت آخرش مشتاق تر از وقتی هستی که قسمت اول رو شروع به خوندن کردی 🙂
و قطعا این آموزش برای من همینطور بود.
ادامه نمیدینش؟
حیفه واقعا تو این مرحله متوقف شه
این هفته از سر گرفته میشه – امیداورم
سلام . بسیار ممنونم که اینقدر وقت میذارین واسه آموزش های تخصصی ای که شما رایگان در اختیار عموم قرار میدین.
میشه لطف کنین بگین قسمت بعدی رو کی تهیه میکنین ؟
به شدت به این اموزش علاقه مند شدم
در حال برنامه ریزی برای ایجاد تغییرات زیر ساختی هستیم برای همین این فرایند طولانی میشه
متاسفانه زمان محدودی در اختیار دارم و همین شده که روال کار اینطور طولانی شده.
سلام خسته نباشید
ممنونم بابات آموزش تون
مرجع انگلیسی خوبی برای همین rtos سراغ دارین؟
یکم تندتر میخوام برم جلو D:
بازم ممنونم.
هم کتاب freertos خیلی خوبه و هم کتاب uc/OS
اول از همه سال نو رو به همه سیسوگی ها تبریک میگم
و جا داره یه خسته نباشید بگم بابت مطالب خوبتون
خواهش میکنم دوست عزیر
ما هم سال نو رو به همه همراهان سیسوگ و شما تبریک میگیم
سلام استاد
با توجه به مزیت های برنامه نویسی به شیوه REAL TIME OS ایا میشه این سبک رو بر روی همه میکروکنترلر های موجود اعم از ATMEGA ها
پیاده سازی کرد چون شما به بررسی CORTEX-M3 پرداختی پرسیدم؟؟
سلام
با توجه به حافظه محدود توی خانواده های avr البته فارغ از مدل هایی که حافظه خارجی رو پشتیبانی میکنند استفاده از سیستم عامل که نیاز به رم داره زیاد توجیه نداره
البته هست سیستم عامل هایی که رم خیلی کمی مصرف میکنند و خاص avr برنامه نویسی شدن مثل femtoos
سعی کردم با دقت کل سری مقاله رو بخونم ولی هنوز متوجه تفاوتش با interrupt نشدم.
یعنی معتقدین هر تست یه اینتراپت باشه ؟
خوب به هنوز به جایی از مقاله نرسیدیم که متوجه تفاوتش بشد
در مقاله دوم گفتین که RTOS برا چند وظیفه گی نسبی استفاده میشه و مثالی که زدین برای چک کردن پایه کلید نیاز به صبر کردن برای تموم شدن کار های دیگه میکرو نداره و چک میکنه کی پایه 1 میشه
یا اینتراپت هم همین کار رو میکردیم,یه تابع callback داشتیم که اگه مثلا یه پایه تغییر کرد ,میکرو کار خودشو ول میکرد, میومد تو تابع, بعد دوباره برمیگشت سر جای قبلیش . مشابه RTOS (البته با سواد فعلی من!)
خوب کلید یه مثال خیلی خیلی ساده است به مفاهیم پیچیده تر فکر کنید
البته برداشت شما به صورت کلی کاملا درسته 🙂
توی اینتراپت هم مشابه همین اتفاقی که توی سوییچ تسک می افته می افته ولی مقداری متفاوت تر قضیه هندل میشه 🙂
احیانا یه پیام جدید اینجا نگذاشتم؟ (این پیام منتشر نشود)
مطمپن نیستم – یه کامنت بود که امروز جواب دادم 🙂
سلام خیلی خیلی عالیه و تشکر از اشتراک گذاریه دانشتون. لطفا لطفا لطفا دگ تئوری بسه بریم سراغ عملی یا حداقل عملیو تئوری باهم. لاقل یک مثال کامل با سورس کدها رو بزارین اگر برای کد ویژن باشه که عالی اگر نه لاقل با اتمل استدیو. جون برای آرم و آردوینو که زیاده توو نت ولی برای avr به شدت کمه برا همینم مطلبتون با ارزشه
سلام
خواهش میکنم انشالله اگر فرصت بشه بنویسم حتما
سلام این مبحثو دوست دارم امیدوارم زودتر وارد گود کد زنی بشیم
با تشکر!!!!
سلام به زودی قسمت چهارم آماده میشه دوست عزیز
متشکر
خیلی ممنونم از شما و سایت خوب سیسوگ
خواهش میکنم دوست عزیز 🙂
.thank you keep up the great work
ممنونم
سلام الان که اینترنت بین الملل قطعه ، بیشتر از قبل آدم به ارزش مقالات وسایت های این چنینی پی میبره ..ممنون ازتون
انشالا بقیه قسمت هارو هم سریع آماده کنید که خیلی مشتاقیم
خواهش میکنم دوست عزیز
بله حتما در حال آماده سازی هستم که بی نت نمیشه تکون خورد این روزا 😐
یکم ساده تر و اضحتر با مثال بیان کنید متشکرم
تا جای ممکن سعی میکنم ساده بگم
الان تو فاز تئوری هستیم – وارد فاز عملی که بشیم بهتر این موارد درک خواهند شد.
ممنون!
لطفا سریعتر وارد قسمت rtos بشید
ساختار cpu رو اجمالی تر توضیح بدین بهتره
ممنون از آموزش این بخش و مطالب جالبی که در اختیارمون میذارید
سلام و درود دوست عزیز
در واقع توی این مقالات ما قصد داریم که یک RTOS از صفر برنامه نویسی کنیم برای این که قادر باشیم چنین کاری رو انجام بدیم لازم داریم که عملکرد CPU رو با جزییاتش بدونیم.
سلام ممنون از زحماتتون بابت مطرح کردن چنین مباحثی.
بی صبرانه منتظر قسمت های بعدی هستم.
ازتون خواهش دارم که سریعتر قسمت های بعدی رو هم بنویسید و ما رو خیلی چشم انتظار نگه ندارید . بازم ممنون.
سلام دوست عزیز – خواهش میکنم
انشالله سعی میکنم زودتر منتشر کنم.
سلام جناب مهندس
خیلی عالی است. امیدوارم که این مبحث پیوسته ادامه داشته باشد.
سلام و درود خدمت شما دوست عزیز
انتشالله سعی میکنیم که آموزش رو به جای مناسب برسانیم.
واقعا هیجان دارم ببینم که در قسمت ها بعد چه اتفاقی می افته
متشکر از لطف شما 🙂
بسیار عالی
مشتاقانه منتظر قسمت های بعدی هستم?
سلام و درود
خواهش میکنم دوست عزیز انشالله بتونم منظم تر ادامه بدم این آموزش رو
…Finally
بله واقعا بعد از مدت ها …
جای خالی این چنین بحث ها در سایت های داخلی خیلی احساس میشه. امیدوارم همینطور با قدرت ادامه بدید.
ممنون از وقتی که میذارید و این مقالات رو تهیه می کنید.
سلام و درود دوست عزیز
واقعا ما هم هدفمون اینه که جاهای خالی رو توی آموزش الکترونیک پوشش بدم.
متشکر برای همراهی شما
مهندس جان قسمت های بعدی رو کی منتشر میکیند؟خیلی ممنون از لطف شما
به زودی 🙂
خيلي ممنون مهندس جان،من برا يه پروژه اي ميخاستم از اين مدل برنامه نويسي استفاده كنم چون چندين عملكرد وجود داره داخل كار برا همون توي مد معمولي يه جور آشفتگي خاصي بوجود مياد كه نمتونم زمانبندي رو خوب مديريت كنم برا همون واقعا نياز دارم به اصول اين مدل سيستم عامل كه داخل task ها انجام ميشه،من زياد مطالعه كردم ولي درست نمدونم انجام task ها و همچنين وقفه هارو بايستي چه جوري مديريت كنم
پیشنهاد میکنم کتاب freertos رو مطالعه کنید این کتاب دید خوبی به شما میده و فکر میکنم بعد از مطالعه کتاب از این دست مشکلات نخواهید داشت.