احتمالاً درباره مفاهیم پایه و اصولی سیستمعاملها اطلاعاتی داشتهباشید. سیستمعامل یا همان Operating System(OS) نرمافزار سیستمی ایست که رایانه را تحت کنترل دارد و بستری فراهم میسازد تا کاربر بتواند نرمافزار را اجرا کرده و از خدمات آن استفاده کند.
به طورکلی نحوه کارکرد یک سیستمعامل به صورت زیر است:
اگر با میکروکنترلرها آشنا باشید، میدانید که برخی از میکروکنترلرها مجهز به یک سیستمعامل هستند که یکی از معروفترین این سیستمعاملها freeRTOS(free Real-Time Operating System) هست که در حوزههای مختلف به خصوص اینترنت اشیاء (IoT) کاربرد فراوانی دارد. برای آشنایی بیشتر با این سیستمعامل از این پست آموزشی دیدن کنید.
در این پست قصد داریم حالتهای مختلف Sleep را به کمک کتابخانه freeRTOS فعال کنیم. همچنین برای آشنایی با الگوهای مختلف خواب و نحوه عملکردشان در برد ESP32 میتوانید به صفحه الگوهای خواب در ESP32 مراجعه کنید.
الگوی خواب در کتابخانه freeRTOS :
همانطور که اشاره شد سیستمعامل freeRTOS کاربردهای فراوانی دارد و امکانات زیادی را در اختیار کاربران قرار میدهد. یکی از ویژگیهای پرکاربرد این سیستمعامل، توانایی فعالسازی حالت Low-Power میباشد که به کمک حالت Tickless Idle کنترل میشود.
اما حالت Tickless Idle چیست؟
قبل از پاسخ به این سوال به بررسی مفاهیم پایه Tick و Idle میپردازیم.
- Tick: واحدی از زمان است که در RTOS ها جهت اندازهگیری زمان و برنامهریزی تسکهای CPU استفاده میشود و در فواصل زمانی یکسان، سیستم را جهت انجام تسکهای برنامهریزی شده فراخوانی میکند.
- Idle: درواقع نوعی تسک است و زمانی که هیچ تسک مهم دیگری آماده انجام نیست، اجرا میشود. در حقیقت این حالت جهت جلوگیری از بیکار(idle) بودن CPU صورت میگیرد.
حال، با این تعاریف، حالت Tickless Idle به حالتی گفته میشود که در آن سیستم به صورت خودکار و با تنظیم فواصل Tick وارد حالت Low-Power میشود. به طورکلی در این حالت، freeRTOS بجای اینکه در فراصل زمانی متناوب از Tick استفاده کند و دستگاه را از حالت Low-Power خارج کند، با توجه به زمان انجام تسک بعدی وقوع آن را تعدیل میکند.
همانطور که پیشتر گفتهشد، در این بخش قصد داریم حالتهای مختلف Sleep را به کمک کتابخانه freeRTOS فعال کنیم. از آنجایی که سیستمعامل freeRTOS به صورت مستقیم توانایی مدیریت الگوهای خواب را ندارد، برای فعالسازیشان در میکروکنترلر، ابتدا باید دید که آیا برد بکاررفته از این ویژگی پشتیبانی میکند یا خیر. برد موردنظر ما در این پست ESP32 است.
در کد بالا configUSE_TICKLESS_IDLE
برای فعالسازی حالت Tickless Idle به کار رفته که مقادیر زیر را میتواند دریافت کند:
- 0 : در صورت دریافت این مقدار، Tickless Idle غیرفعال میشود.
- 1 : این مقدار، Tickless Idle را فعال کرده و روی حالت خودکار قرار میدهد.
- 2 : مقادیر 1 به بالا بسته به ورژن مورد استفاده، شرایط متفاوتی را اعمال میکنند.
همچنین در مثال بالا با استفاده از تابع ()esp_deep_sleep_start
برد ESP32 وارد خواب عمیق (Deep Sleep Mode) شده. به Header فایلهایی که برای بکارگرفتن freeRTOS استفاده شده نیز دقت کنید.
در مجموع، همانطور که اشاره کردیم، استفاده از الگوهای خواب بستگی به قابلیتهای برد و موارد قابل پشتیبانی توسط آن دارد. در این لینک پست آموزشی به چگونگی فعالکردن این الگو ها اشاره کردهایم.
فعالسازی حالت خواب در هستههای ESP32:
ESP32 یک میکروکنترلر دوهسته ایست که این هستهها به این برد قابلیت انجام چند تسک در لحظه را میدهند. در این بخش قصد داریم بررسی کنیم که آیا فعالسازی حالت خواب برای هستههای ESP32 به صورت جداگانه امکانپذیر است یا نه؟
در پاسخ به پرسش بالا، باید گفت بله اینکار امکانپذیر است. هریک از هستههای ESP32 این قابلیت را دارند تا جداگانه به خواب بروند و در زمانهای متناوب بیدار شوند. تسکهای هریک از این هستهها را میتوان به کمک توابعی از کتابخانه freeRTOS کنترل و برنامهریزی کرد و در زمان مشخص آنها را به اجرا درآورد. حال با یک مثال به بررسی بیشتر این قابلیت میپردازیم.
کد بالا از سه بخش تشکیلشده که هرکدام از بخشها را جداگانه بررسی میکنیم:
- تابع taskCore0 : وظیفه این تابع کنترل خواب هسته اصلی است. در این تابع برای بیدارکردن دستگاه از
()esp_sleep_enable_timer_wakeup
استفادهشدهاست و پس از آن هسته اصلی به کمک()esp_deep_sleep_start
وارد خواب عمیق میشود. - تابع taskCore1 : کارکرد این تابع همانند قبلی هست با این تفاوت که این تابع حالت خواب هسته دوم را کنترل میکند. در این تابع نیز برای خروج دستگاه از خواب، مکانیزم تایمر با تابع
()esp_sleep_enable_timer_wakeup
بکار رفتهاست و سپس دستگاه به واسطه تابع()esp_light_sleep_start
وارد حالت Light Sleep شده. - تابع xTaskCreatePinnedToCore : این بخش با استفاده از کتابخانه freeRTOS، تسکهایی را بوجودآورده و آنها را به هستهها واگذار میکند. پارامترهای مهمی که این تابع در این مثال میگیرد به صورت زیر است:
- taskCore0 : این پارامتر به نام تابعی که در آن تسک تعریف شده اشاره میکند.
- 10000 : سایزstack ستشده برای تسک (taskCore0)
- NULL : پارامتر لازمه برای تسک که در این مثال روی NULL ست شده و به این معناست که هیچ پارامتری به تابع تسک (taskCore0) داده نمیشود.
- 0 : شماره هستهای که تسک بر آن اعمال میشود را نشان میدهد.
به طور کلی میتوان با توجه به نیاز و قابلیت دستگاه، حالتهای مختلف خواب را به کمک freeRTOS روی هستهها فعال کرد.
راهکارهایی برای فعال نگه داشتن ماژول WiFi:
در بسیاری از پروژهها، در حین خواببودن، نیاز هست که دستگاه دادههایی را به کمک WiFi دریافت و پردازش کند. در حالتهای خواب مختلف ماژولهای میکروکنترلر کارایی متفاوتی دارند. در حالتهای Deep Sleep, Light Sleep و Hibernation ماژول WiFi به طور کل غیرفعال میشود و نمیتوان از آن استفاده کرد و همچنین در حین غیرفعال بودن CPU فعال نگه داشتن این ماژول امکانپذیر نیست؛ اما میتوان از روشهای دیگری برای دریافت متناوب اطلاعات به کمک WiFi استفاده کرد که به صورت زیر هستند:
- میتوان از حالت خواب Modem Sleep برای دریافت اطلاعات از WiFi استفاده کرد. این الگو با استفاده از یک فناوری خاص امکان دریافت داده از طریق WiFi را در زمانهای متناوب امکانپذیر میکند. درباره این الگو خواب و نحوه فعالسازی آن در پست آموزشی قبلی صحبت شده.
- میتوان به صورت متناوب میکروکنترلر را، با روشهایی که در ادامه همین پست به آنها اشاره میکنیم، از حالت خواب خارج کرد و از ماژول WiFi برای دریافت اطلاعات استفاده کرد.
روشهای غیرفعال کردن حالت خواب:
بیدارکردن دستگاه از حالت خواب به روشهای مختلفی صورت میپذیرد که در این پست آموزشی و تا به اینجا ما صرفا از روش تایمر برای پایاندادن به حالت خواب استفادهکردیم. بسته به اینکه میکروکنترلر استفادهشده از چه روشهایی پشتیبانی میکند، مکانیزمهای مختلفی میتوان پیاده کرد که به چند مورد آن برای برد ESP32 اشاره میکنیم.
- منابع خارجی: پینهای GPIO، تجهیزات RTC و سنسورهای لمسی منابع خوبی برای بیدارکردن دستگاه هستند که هرکدام با توجه به نیاز از توابع خاصی برای اجراشدن استفاده میکنند که به چند مورد آن اشاره میکنیم:
- تایمر: میکروکنترلر را بعد از گذشت تایم مشخص شده بیدار میکند. از تابع
esp_sleep_enable_timer_wakeup()
برای فعالسازی آن استفاده میشود. - سنسور Touchpad: با کمک سنسور لمسی و متصل کردن آن به برد میتوان میکروکنترلر را بیدار کرد. از تابع
esp_sleep_enable_touchpad_wakeup()
برای فعال کردن آن استفاده میشود. - منبع خارجی Ex0: مرتبط به منابع خارجیای مانند سنسورها و یا بردهای دیگریست که به پین GPIO0 متصل میشوند. نحوه فعالسازی آن به صورت
esp_sleep_enable_ext0_wakeup()
میباشد.
- تایمر: میکروکنترلر را بعد از گذشت تایم مشخص شده بیدار میکند. از تابع
- مکانیزم ULP: برد ESP32 دارای ULP یا همان پردازنده کمکیست. این پردازنده وظیفه انجام تسکهای کوچک و ساده را در هنگام غیرفعال بودن پردازنده اصلی دارد و همچنین میتواند پردازنده اصلی را در صورت نیاز به انجام تسکهای مهم فعال و دستگاه را بیدار کند.
هر کدام از این مکانیزمها و روشها که برای فعالسازی دستگاه بکار میروند، توابع خاص خود را دارند که با توجه به مکانیزم موردنظر باید این توابع را در کد استفاده کرد.
منابع
(1) Feilipu. Arduino FreeRTOS. feilipu. Weblog. Available from: https://feilipu.me/2015/11/24/arduino_freertos [accessed 21st February 2024]
(2) Reducing power consumption using FreeRTOS sleep mode in a dual-threaded system. freertos. Available from: https://forums.freertos.org/t/reducing-power-consumption-using-freertos-sleep-mode-in-a-dual-threaded-system/17589 [accessed 21st February 2024]
(3) Low Power Support. freertos. Weblog. Available from: https://www.freertos.org/low-power-tickless-rtos.html [accessed 21st February 2024]
(4) Tasks. freertos. Weblog. Available from: https://www.freertos.org/RTOS-idle-task.html [accessed 21st February 2024]
(5) Espressif Systems. FreeRTOS Overview. docs espressif . Weblog. Available from: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/freertos.html [accessed 20th February 2024]
(6) Espressif Systems. FreeRTOS(IDF). docs espressif. Weblog. Available from: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/freertos_idf.html [accessed 20th February 2024]
(7) Moein Saaberi. getting started with freertos in esp32 part one: RTOS introduction. digispark. Weblog. Available from: https://digispark.ir/getting-started-with-free-rtos-in-esp32-part-one-introduce [accessed 20th February 2024]