مهندس موفق الکترونیک

اصول توسعه Bootloader برای آردوینو

مقدمه

بوت لودر (Bootloader)، اصولاً یک تکه کد آغازین است که هر میکروکنترلری هنگام روشن شدن یا راه‌اندازی مجدد آن را اجرا می‌کند. این کد مشابه مفهوم BIOS است که هر PC هنگام روشن شدن آن را اجرا می‌کند. در مورد PC ،BIOS منتظر ورودی از طرف کاربر برای تغییر گزینه‌ها/تنظیمات BOOT می‌ماند. اگر هیچ ورودی دریافت نکند، تنظیمات سیستم عامل از پیش نصب شده را پیش می‌گیرد.

چیزی مشابه همین در بوت لودر آردوینو نیز رخ می‌دهد. هر زمان که آردوینو روشن شده یا ریست گردد، برای  ورودی‌های خارجی (منظور آپلود یک برنامه جدید است) جستجو می‌کند. اگر هیچ ورودی دریافت نکند، برنامه‌ای که آخرین بار آپلود شده را اجرا می‌کند.

اصول توسعه Bootloader برای آردوینو

آردوینو از میکروکنترلر avr برای پلتفرم خود استفاده می‌کند که دارای بخش‌های مختلف حافظه برنامه است که در شکل بالا نشان داده شده است. بخش بوت لودر در پایین حافظه فلش قرار دارد.

برنامه بوت لودر در بخش bootloader نوشته می‌شود، و برنامه‌های کاربردی در بخش application نوشته می‌شوند.

بوت لودر چگونه شروع به کار می‌کند؟

همان طور که می‌دانیم هر زمان که میکروکنترلر ریست شده و یا راه‌اندازی مجدد می‌گردد، عموماً اجرای برنامه را از بردار ریست، یعنی از ادرس حافظه برنامه (0x0000 (program memory شروع می‌کند.

در صورتی که از بوت لودر روی میکروکنترلر استفاده می‌کنیم، می‌توانیم آدرس این بردار ریست (0x0000) را به بخش bootloader تغییر دهیم. یعنی، هر زمان که میکروکنترلر ریست/روشن شود، اجرای برنامه را از بخش لوت لودر آغاز کند.

بوت لودر آردوینو همان کار را انجام داده و هنگام ریست/روشن شدن میکروکنترلر (آردوینو) برنامه بوت لودر اجرا می‌شود، یعنی میکروکنترلر اجرای برنامه را از آدرس شروع بخش bootloader اجرا می‌کند.

اگر به دیتاشیت میکروکنترلرهای AVR رجوع کنیم (که آردوینو از آن استفاده می‌کند)، خواهیم دید که می‌توان فیوز Boot Reset را همانند شکل زیر به گونه‌ای برنامه‌ریزی کرد که بردار ریست به آدرس آغازین Boot Flash اشاره کند.

اصول توسعه Bootloader برای آردوینو

بنابراین، می‌توان بردار ریست را به شروع بخش bootloader تنظیم کرد.

نیاز به بوت لودر

بیشتر اوقات، بوت لودرها به سادگی تنها برای آپلود کردن برنامه به میکروکنترلر استفاده می‌گردند. می‌توان از آنها برای مقداردهی اولیه دستگاه‌های ورودی خروجی متصل به میکروکنترلر پیش از شروع به کار برنامه اصلی استفاده کرد.

بوت لودرهای آردوینو از ارتباط سریال ساده (UART) برای دانلود فایل hex برنامه و نوشتن آن در بخش application استفاده می‌کنند.

اصول توسعه Bootloader برای آردوینو

درون بوت لودر

حال اجازه دهید به صورت خلاصه ملاحظه کنیم که بوت لودر آردوینو چگونه نوشته می‌شود و هنگام آپلود کردن برنامه‌ها چگونه با IDE آردوینو ارتباط برقرار می‌کند.

همانند شکل زیر می‌توان برنامه‌ی بوت لودر آردوینو را در مسیر زیر پیدا کرد.

arduino-version\hardware\arduino\bootloaders\optiboot

اصول توسعه Bootloader برای آردوینو

هدر فایل بوت (boot.h) از avr toolchain ضمیمه می‌گردد. این یک نسخه ویرایش شده/بهبودیافته از هدر فایل (<avr/boot.h>) avr toolchain boot می‌باشد. می‌توان هدر فایل avr boot را در مسیر زیر پیدا کرد.

arduino-version\arduino-1.0.5-r2\hardware\tools\avr\avr\include\avr

هدر فایل avr boot ازدستور sts (که به دو سیکل ماشین نیاز دارد) برای دسترسی به رجیستر SPM استفاده می‌کند درحالی که هدر فایل boot مورد استفاده در آردوینو از دستور out (که به یک سیکل ماشین نیاز دارد) برای دسترسی به رجیستر SPM استفاده می‌کند. این بهینه‌سازی مهم تا بدین لحظه در هدر فایل avr toolchain boot دستگاه‌های کوچکتر نیز اعمال شده است.

هدر فایل Boot شامل توابعی برای نوشتن/خواندن حافظه فلش (در حالت صفحه به صفحه) می‌باشد. همچنین شامل توابعی برای نوشتن/خواندن بیت‌های fuse ،lock و signature می‌باشد.

هدر فایل stk500.h) stk500) شامل دستورات STK500 است که برای برقراری ارتباط handshaking پایدار، بین آردوینو و برنامه avrdude هنگام آپلود فایل hex به کار می‌روند.

هدر فایل تعریف پین‌ها (pin_defs.h) شامل تعریف پورت برای LED (LED روی بورد آردوینو) است که هنگام فلش کردن آردوینو به عنوان نشانگر وضعیت چشمک می‌زند.

فایل optiboot.c شامل برنامه اصلی بوت لودر (یعنی دریافت فایل hex به صورت سریال و نوشتن آن در حافظه program) است. فایل‌های دیگر (boot.h ،pin_defs.h ،stk500.h) در فایل optiboot.c ضمیمه می‌شوند.

برنامه optiboot با رجیستر وضعیت MCU Status Register) MCUSR) شروع می‌شود که اطلاعات لازم درباره منبع ریست را فراهم می‌کند. اگر منبع ریست خارجی (یعنی با پایین کردن پین ریست انجام شده باشد) نباشد، آنگاه مستقیماً برنامه کاربردی شروع می‌شود. همانند شکل زیر، تابع ()appStart را از جایی که مستقیما به آدرس ریست 0x0000 پرش می‌کند فراخوانی خواهد کرد.

مطلب پیشنهادی:  پروتکل CAN Bus در آردوینو با آی‌سی MCP2515

اصول توسعه Bootloader برای آردوینو

توجه کنید که MCUSR پس از استفاده خالی می‌شود بنابراین در صورت نیاز نمی‌توان مجدداً از آن برای گرفتن منبع ریست در برنامه‌ی خود استفاده کنیم. این به خودی خود مشکل‌ساز نیست زیرا می‌توانیم  بوت لودر را مطابق با نیازمان ویرایش کنیم.

اگر منبع ریست خارجی باشد (با پایین بردن پین ریست)، آنگاه از پرش مستقیم به کد اپلیکیشن اجتناب شده و آماده‌سازی برای ارتباط سریال با avrudue انجام می‌شود. avrdude هم اکنون روی PC/لپ‌تاپ برای خواندن فایل hex و نوشتن آن در حافظه برنامه در حال اجرا می‌باشد.

سگ نگهبان برای زمان یک ثانیه در برنامه آماده می‌شود تا در صورت بروز هرگونه خطایی حین آپلود کد برنامه ریست انجام شود و یا پس از تکمیل نوشتن برنامه در حافظه ریست انجام شود.

اصول توسعه Bootloader برای آردوینو

سپس ارتباط سریال (UART) را برای برقراری ارتباط با IDE آردوینو روی PC/لپ‌تاپ آغاز می‌کند.

اصول توسعه Bootloader برای آردوینو

پس از آن، حلقه بی‌نهایت را برای خواندن بایت‌ها (بایت‌های داده/دستور) با استفاده از پروتکل به کار رفته توسط STK500 شروع می‌کند.

اصول توسعه Bootloader برای آردوینو

حافظه‌ی برنامه به صورت صفحه به صفحه نوشته/آپدیت می‌شود. اندازه‌ی صفحه بر حسب میکروکنترلر متفاوت است. برای مثال، Atmega328P دارای اندازه صفحه ۶۴ کلمه‌ای (یعنی ۱۲۸ بایتی) است درحالی که Atmega88A/88PA دارای اندازه صفحه ۳۲ کلمه‌ای (۶۴ بایتی) می‌باشد.

فرآیند نوشتن در حافظه برنامه به صورت صفحه به صفحه به ترتیب زیر انجام می‌گیرد.

  • در حلقه بی‌نهایت مذکور، بایت‌های hex سریالی ورودی از آپلود کننده آردوینو روی PC/لپ‌تاپ، ابتدا در حافظه موقت داده (بخوانید SRAM) کپی می‌شوند.
  • پس از کپی کردن بایت‌های hex به اندازه یک صفحه در حافظه داده موقت، پاک کردن صفحه اول حافظه برنامه انجام می‌شود.
  • پس از پاک کردم صفحه، حافظه برنامه ابتدا با بایت‌های hex ذخیره شده در حافظه داده موقت پر (فقط پر می‌شود، نوشته نمی‌شود) می‌شود.
  • سپس با استفاده از دستور SPM page write، نوشتن/آپدیت کردن صفحه با موفقیت انجام می‌شود.
  • فرآیند بالا، یعنی خواندن به صورت سریال و نوشتن آن در حافظه برنامه به صورت صفحه به صفحه، تا تکمیل بایت‌های hex در حافظه برنامه ادامه می‌یابد.
  • پس از پایان عملیات نوشتن فایل hex، پروسه مخالف آن انجام ‌می‌شود، بدین ترتیب که به منظور اطمینان از آپدیت/نوشتن موفقیت‌آمیز فایل hex در حافظه برنامه، از حافظه برنامه داده خوانده شده و به صورت صفحه به صفحه و سریالی PC/لپ‌تاپ ارسال می‌شود.

یک تابع ساده page write که در هدر فایل boot از پیش موجود است در زیر آورده شده است.

#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
void boot_program_page (uint32_t page, uint8_t *buf)
{
         uint16_t i;
         uint8_t sreg;
         // Disable interrupts.
         sreg = SREG;
         cli();
         eeprom_busy_wait ();
         boot_page_erase (page);  //erase page
         boot_spm_busy_wait ();      // Wait until the memory is erased.

         for (i=0; i<SPM_PAGESIZE; i+=2)
         {
                  // Set up word from temp buffer.
                  uint16_t w = *buf++;
                  w += (*buf++) << 8;
                  boot_page_fill (page + i, w);  //fill (page + i ) address with word
         }
         boot_page_write (page);     // Store/write buffer in flash page.
         boot_spm_busy_wait();       // Wait until the memory is written.
         // Reenable RWW-section again. We need this if we want to jump back
         // to the application after bootloading.
         boot_rww_enable ();
         // Re-enable interrupts (if they were ever enabled).
         SREG = sreg;
}

تمام موارد بالا ایده‌ی ابتدایی نوشتن فایل hex در حافظه برنامه است. توابع به کار رفته در برنامه بالا، یعنی:

boot_page_fill(page address, word data)

boot_page_write(page address)

boot_spm_busy_wait()

و … در هدر فایل boot.h) boot) موجود هستند که با استفاده از دستورات اسمبلی درون خطی نوشته شده‌اند.

چگونه یک برنامه که خود در پایین حافظه برنامه قرار گرفته است فرآیند نوشتن در حافظه برنامه را مدیریت می‌کند؟ یعنی چگونه یک برنامه در بخش boot، در بخش application عمل نوشتن را انجام می‌دهد. این مسئله با استفاده از مکانیزم خود برنامه‌ریزی self-programmin mechanis یا به اختصار SPM میروکنترلر avr، که برای دانلود و آپلود کد توسط خود میکروکنترلر فراهم شده، امکان‌پذیر است.

مطلب پیشنهادی:  پین‌های GPIO دیجتیال آردوینو

خود برنامه‌ریزی توانایی استفاده از هر رابط داده موجود و پروتکل مرتبط با آن برای خواندن کد و نوشتن (برنامه) آن در حافظه برنامه را دارد.

آردوینو چگونه با IDE خودش پروگرم می‌شود؟

بوت لودر آردوینو از پروتکل سریال (UART) برای دانلود فایل hex برنامه از PC/لپ‌تاپ استفاده می‌کند. در سمت PC /لپ‌تاپ IDE آردوینو اجرا می‌شود و برنامه‌ی کاربردی را کامپایل کرده و کد hex کامپایل شده را از طریق کابل USB و به صورت سریال به بورد آردوینو ارسال می‌کند.

IDE آردوینو از ابزار avrdude که برای آپلود/دانلود محتویات کد/داده از/به ROM/EEPROM میکروکنترلر AVR به کار می‌رود استفاده می‌کند.

مقاله مرتبط مفید: انواع حافظه های پرکاربرد ( SRAM – DRAM – NAND Flash – NOR Flash )

AVR Downloader Uploader) AVRDUDE) برنامه‌ای برای دانلود و آپلود حافظه روی چیپ میکروکنترلرهای Atmel AVR می‌باشد. این برنامه می‌تواند FLASH و EEPROM را برنامه‌ریزی کند و از پروتکل‌های برنامه‌ریزی نیز پشتیبانی می‌کند، همچنین از این برنامه برای پروگرم کردن بیت‌های fuse و lock نیز استفاده می‌شود.

AVRDUDE پروتکل ارتباطی STK500 را برای آپلود سریالی فایل hex کامپایل شده روی آردوینو به کار می‌گیرد. به این دلیل بود که هدر فایل دستورات STK500 را در برنامه بوت لودر ضمیمه کردیم.

ارتباط STK500 بین avrdude (در حال اجرا در سمت PC/لپ‌تاپ) و بوت لودر (در حال اجرا) برای خواندن/نوشتن فایل hex برقرار می‌شود.

حال اجازه دهید ابتدا نحوه‌ی آپلود کردن برنامه بوت لودر در بخش boot را ملاحظه کنیم.

برای استفاده از بوت لودر، ابتدا نیاز داریم که بوت لودر را درون بخش bootloader حافظه برنامه نصب کنیم.

عموما همه ICها را پیش از لحیم کردن آنها روی PCB پروگرم می‌کنند. بیشتر تولیدکنندگان میکروکنترلرها (مانند Atmel ،Microchip) از روش برنامه‌ریزی درون سیستمی ‌(In System programming) یا ISP مخصوصی به نام برنامه‌ریزی سریالی درون مداری (In-Circuit Serial Programming) یا ICSP استفاده می‌کنند. در چنین روش‌هایی، هدر ISP برای فلش کردن با پروگرمر خارجی روی بورد تعبیه شده است.

آردوینو یک هدر ICSP روی بوردی، همانند شکل زیر، برای برنامه‌ریزی تدارک دیده است.

اصول توسعه Bootloader برای آردوینو

همان طور که در شکل بالا قابل مشاهده است، آردوینو UNO دارای دو هدر ICSP می‌باشد. یکی برای ATmega16U2 و دیگری برای ATmega328. برای فلش کردن بوت لودر، باید از هدر ICSP مربوط به ATmega328 استفاده کنیم.

می‌توان بوت لودر آردوینو را با استفاده از Atmel Studio و USBasp (برنامه‌ریز درون مداری) ساخته و آن را فلش کنیم. برای اطلاع از نحوه‌ی ساخت و فلش کردن فایل hex درون میکروکنترلرهای avr، به بخش شروع به کار با Atmel Studio رجوع کنید.

همچنین، می‌توان با استفاده از یک آردوینو دیگر (اگر یک آردوینو دیگر داشته باشیم، می‌توانیم از آن به عنوان پروگرمر ISP استفاده کنیم) نیز بوت لودر را فلش کرد. IDE آردوینو را باز کرده و مثال ArduinoISP را از منوی مثال‌ها همانند شکل زیر انتخاب کنید.

اصول توسعه Bootloader برای آردوینو

برنامه‌ی ArduinoISP را روی بورد آردوینویی که قرار است نقش پروگرمر ISP را بازی کند آپلود کنید. اکنون این آردوینو را (همانند شکل زیر) به بورد آردوینویی که می‌خواهید پروگرم کنید وصل کنید.

اصول توسعه Bootloader برای آردوینو

گزینه‌ی ISP Programmer) Arduinoboard) را از بخش پورت و پروگرمر را با انتخاب «Arduion as ISP» از گزینه‌ی tools همانند شکل زیر انتخاب کنید.

اصول توسعه Bootloader برای آردوینو

سپس روی گزینه «Burn Bootloader» از منوی tools (شکل بالا) کلیک کنید. منتظر بمانید تا فرآیند نوشتن بوت لودر تمام شود. می‌توان مشاهده کرد که در حین فرآیند نوشتن بوت لودر، LED چشمک می‌زند.

با پایان موفقیت آمیز فرآیند، بورد آردوینو (که بوت لودر روی آن نوشته شده) آماده پروگرم است.

نحوه ویرایش بوت لودر آردوینو

نسخه‌ی ویرایش شده بوت لودر آردوینو نیز در دسترس است که حاوی توابع مناسب و یک تغییر اساسی می‌باشد. تغییر این است که علت ریست (رجیستر وضعیت MCUSR) از برنامه‌ی بوت لودر به برنامه‌ی کاربردی از طریق رجیستر r2 ارسال می‌گردد. این کار با استفاده از تابع ()app_start که در شکل زیر قابل مشاهده است صورت می‌گیرد.

اصول توسعه Bootloader برای آردوینو

این نسخه‌ی ویرایش شده بوت لودر آردوینو (ATmega328P) فایل پروژه Atmel Studio 7 را در بخش ضمیمه‌ها (در انتهای این مطلب) قرار داده‌ایم. آن را به همان صورت یا به شیوه خودتان تست کنید.

مطلب پیشنهادی:  ارسال آرایه ها به توابع

گزینه‌های مختلفی وجود دارد که به وسیله‌ی آنها می‌توان برنامه بوت لودر را مطابق با نیاز ویرایش کرد. برای مثال، بوت لودر آردوینو از ارتباط سریال UART برای خواندن فایل hex از PC/لپ‌تاپ استفاده می‌کند. می‌توان دیگر ارتباطات سریال موجود مانند SPI و I2C را نیز به کار بست. با استفاده از این ارتباطات، می‌توان فایل hex را از منابع خارجی (مثل کارت حافظه، eeprom) خواند.

اندازه بخش Bootloader

نکته بسیار مهم دیگر در مورد بوت لودر، مقدار فضایی است که برای بخش bootloader در میکروکنترلر موجود است.

اگر به مثال آردوینو توجه کنیم، می‌توان ملاحظه کرد که اندازه‌ی بوت لودر توسط کاربر قابل انتخاب است. مثلا آردوینو UNO که از میکروکنترلر ATmega328P استفاده می‌کند، بوت لودری دارد که اندازه آن مطابق دیتاشیت قابل انتخاب است.

اصول توسعه Bootloader برای آردوینو

همان طور که در شکل بالا مشاهده می‌شود، اندازه بخش boot قابل تغییر است. اندازه Boot در واحد کلمه داده می‌شود که نصف اندازه آن در واحد بایت است. مثلاً ۲۵۶ کلمه به معنی ۵۱۲ بایت است.

آدرس شروع Boot reset را نیز می‌توان مطابق با پیکربندی اندازه boot انتخاب کرد. مثلا اگر برای بخش boot اندازه ۲۵۶ کلمه در نظربگیریم آنگاه باید برنامه بوت لودر را به گونه‌ای بنویسیم که در همین ۲۵۶ کلمه (۵۱۲ بایت) حافظه جا بگیرد و آدرس شروع آن 0x3F00 (0xE00 در واحد بایت) باشد. بنابراین برنامه بوت لودر باید بین 0x3F00 تا 0x3FFF (۵۱۲ بایت) باشد.

تنظیمات پروژه Atmel Studio هنگام طراحی بوت لودر

هنگام ایجاد پروژه‌ی جدید در Atmel Studio برای بوت لودر آردوینو، با هدف بهبود برنامه باید تغییرات مهمی ‌را در properties ایجاد کنید. همانند شکل زیر، ابتدا پنجره‌ی project properties را از منوی project باز کنید.

اصول توسعه Bootloader برای آردوینو

پنجره‌ی project properties نمایان می‌شود. حال به Toolchain -> Symbols رفته و در بخش AVR/GNU Compiler، در صورت داشتن symbol آنها را تعریف کنید. در اینجا باودریت را ۱۱۵۲۰۰ و فرکانس را ۱۶۰۰۰۰۰۰ هرتز تعریف می‌کنیم.

اصول توسعه Bootloader برای آردوینو

حال به گزینه‌ی optimization، درست بعد از گزینه‌ی Symbols رفته و optimization level را به «(Optimize for size(-Os» تغییر دهید، که کد را برای کمترین اندازه بهینه می‌کند.

اصول توسعه Bootloader برای آردوینو

حال به گزینه‌ی general در بخش AVR/GNU Linker رفته و سه گزینه‌ی اول را تیک بزنید زیرا از آنها در بوت لودر استفاده نخواهیم کرد. این گزینه‌ها عبارتند از:

  • Do not use standard start files (-nostartfiles)
  • Do not use default libraries (-nodefaultlibs)
  • No startup or default libs (-nostdlib)

اصول توسعه Bootloader برای آردوینو

حال نکته مهم memory setting (در AVR/GNU Linker) می‌باشد که در آن می‌توان آدرس شروع بخش‌های حافظه فلش، بخش‌های SRAM، بخش‌های eeprom و آدرس پشته‌ی آغازین را تعریف کرد.

برای بوت لودر آردوینو اندازه boot configuration را ۲۵۶ کلمه (۵۱۲ بایت) انتخاب می‌کنیم. بعد از هر بار ریست/روشن شدن، کنترلر خطا ابتدا باید به بخش بوت لودر پرش کند. بنابراین، باید آدرس شروع بخش فلش را برابر با آدرس شروع بوت لودر تعریف کنیم. پس همانند شکل زیر، تنها بخش فلش را با آدرس text=0x3F00. تعریف کنید.

اصول توسعه Bootloader برای آردوینو

علاوه بر این، ما در حال اضافه کردن linker flag‌ها هستیم که برای شل کردن شاخه‌ها (relaxation of branches) استفاده می‌شوند، یعنی توابع مجاور (بگویید در محدوده 2k+ تا 2k- از آدرس حافظه برنامه‌ی کنونی) به جای استفاده از دستور CALL از دستور RCALL فراخوانی می‌شوند، بدین ترتیب یک سیکل اضافی در روتین فراخوانی صرفه‌جویی می‌باشد.

اصول توسعه Bootloader برای آردوینو

فایل‌های ضمیمه

منبع: ترجمه از سایت electronicwings.com

اگر آموزش اصول توسعه Bootloader برای آردوینو براتون مفید واقع شده ما را نیز دعا کنید و اگر خواستین می‌توانید از محتوا‌ی رایگان آموزشی حمایت مالی کنید. همچنین نظرات، پیشنهادات و درخواست‌های خود را در کامنت‌ها ⇓ بنویسید.

اگر این نوشته‌ برایتان مفید بود لطفا کامنت بنویسید.

مطالعه دیگر جلسات این آموزش<< جلسه قبلی                    جلسه بعدی >>

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

یک دیدگاه

  1. سلام من یک usbasp و اردوینو مگا 2560 دارم که بوت لودر 16u2اردینو مگا خراب شده و به عنوان کیبورد شناسایی می شود

    چطور میتونم درستش کنم که به عنوان اردوینو مگا 2560 شناخته بشه؟

    3