درود فراوان بر شما. در قسمت قبل، آموزش بوت لودر avr بصورت کامل از لحاظ پیکربندی شرح داده شد و توابع آن در نرم افزار Atmel Studio گفته شد. اما برای کار کردن با بوت لودر در کدویژن کتابخانهای وجود ندارد. لذا بر آن شدم که کتابخانه موجود در Atmel Studio را برای کدویژن بازنویسی کنم. این کتابخانه را میتوانید از این لینک دانلود کنید.
نکته: این آموزش بر مبنای آن است که آموزش قبلی را بصورت کامل فرا گرفته باشید. توضیحات توابع، ساختار حافظه و مفاهیم پایه در قسمت قبل موجود است. به همین خاطر تنها 2 مثال از کار با بوت لودر در کدویژن شرح داده میشوند.
وارد کردن کتابخانه بوت لودر avr در کدویژن
پس از دانلود فایل zip کتابخانه boot، آن را از حالت فشرده خارج کنید. 2 فایل نهایی یکی به نام boot.h و دیگری به نام boot.lib باید در آدرسهای زیر قرار گیرند.
موردی که باید در نظر بگیرید، تنظیم فایل boot.h برای میکروکنترلر مورد نظر است. بعضی از تنظیمات بوت لودر در هر میکروکنترلری متفاوت است که باید اطلاعات زیر را از دیتاشیت میکرو استخراج کرده و در فایل boot.h ویرایش کنید. این پارامترها در فایل boot.h در تصویر زیر مشخص شدهاند.
در شکل فوق 5 پارامتر مربوط به کار با بوت لودر وجود دارند که عبارت اند از: ZPCMSB, ZPAGELSB, ZPAGEMSB, SPM_PAGESIZE و ZPCLSB. این 5 پارامتر را میتوان در شکلهای زیر که از دیتاشیت استخراج شدهاند به دست آورد.
به دست آوردن پارامتر SPM_PAGESIZE
در قسمت قبل آموزش در مورد این پارامتر به طور مفصل بحث شد؛ اما بصورت مختصر، حافظه فلش از قسمتهای بزرگتری به نام page تشکیل شده که در عمل پروگرام کردن با آنها سر و کار داریم. مقدار هر page را با سمبل SPM_PAGESIZE نشان میدهیم و بر حسب بایت بیان میشود. برای به دست آوردن SPM_PAGESIZE ابتدا جدول زیر را در دیتاشیت پیدا میکنیم.
در جدول فوق دو ستون به نامهای Boot Size و Pages وجود دارند که به ترتیب مقدار حافظه بوت و تعداد Page های آن را نشان میدهند. برای به دست آوردن SPM_PAGESIZE، ابتدا یکی از ردیف ها را انتخاب کرده و حاصل تقسیم Boot Size بر Pages را به دست آوردید. دقت شود که واحد Boot Size به word گفته شده است. لذا باید در 2 ضرب شود تا مقدار به بایت به دست آید.
SPM_PAGESIZE = Boot Size / Pages = (128 * 2) / 4 = 64 byte
نکته: کتابخانه فوق در میکروکنترلرهای Atmega8، Atmega16 و Atmega32 تست شده و بدون ایراد است. اما برای میکروکنترلرهایی با حجم حافظه بیشتر از 64 کیلوبایت، نیاز به توسعه دارد.
آموزش بوت لودر avr در کدویژن
پس از وارد کردن کتابخانه در نرم افزار CodeVision، میتوانیم همانند سایر کتابخانهها بصورت زیر آن را به برنامه خود الحاق کنیم.
تنها موردی که باید در آن دقت شود این است که برنامه نوشته شده را برای حافظه بوت لودر تنظیم کنیم. به تب Project رفته و سپس گزینه Configure را بزنید. صفحه زیر باز میشود.
در صفحه فوق، در مسیر C Compiler و Code Generation گزینهای به نام Program Type وجود دارد که شامل 4 حالت بوت لودر و 1 حالت برنامه اصلی است. این 4 حالت اندازه بوت لودر را نشان میدهد و باید دقیقا متناسب با فیوز بیت های BOOTSZ0 و BOOTSZ1 انتخاب شود. در هر دو مثالی که در ادامه گفته خواهند شد، اندازه حافظه بوت را روی 1024w یا همان 2048 بایت تنظیم کردهایم. لذا فیوز بیت های BOOTSZ باید به صورت زیر پروگرام شوند.
مثال اول: برنامه چشمک زن ساده برای حافظه بوت لودر
برنامهای مینویسیم که یک LED متصل به پایه PORTB.0 را به فواصل 1 ثانیه خاموش و روشن کند. میخواهیم این برنامه را از روی حافظه بوت اجرا کنیم. لذا فیوز بیت های BOOTSZ و BOOTRST را همانند تصویر بالا پروگرام کرده و در داخل کدویژن هم از مسیر Project و Configure در داخل تب C Compiler گزینه Program Type را بر روی 1024w قرار میدهیم. برنامه چشمک زن به صورت زیر است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <mega8.h> #include <delay.h> void main(void){ DDRB = 0x01; while(1){ PORTB = 0x01; delay_ms(1000); PORTB = 0x00; delay_ms(1000); } } |
توجه کنید که خروجی برنامه فوق، برای بوت لودر است و فایل هگزی که تولید میشود، پس از پروگرام کردن میکرو، بر روی حافظه بوت قرار خواهد گرفت. چرا؟ چون Program Type بر روی 1024w تنظیم شده است (بر روی Application نیست).
مثال دوم: پروگرام کردن برنامه چشمک زن بر روی حافظه اصلی و اجرای آن
در آموزش قبلی یک برنامه چشمک زن را در دل یه برنامه بوت قرار دادیم و سپس آن را بر روی حافظه اصلی یا همان Application پروگرام کردیم. حالا میخواهیم با استفاده از نرم افزار CodeVision و کتابخانه اختصاصی boot همین کار را انجام دهیم. تنظیمات میکرو و نرم افزار همانند مثال قبل است. برنامه بوت لودر به صورت زیر است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#include <mega8.h> #include <delay.h> #include <boot.h> unsigned char prog[134] = {0x12, 0xC0, 0xFE, 0xCF, 0xFD, 0xCF, 0xFC, 0xCF, 0xFB, 0xCF, 0xFA, 0xCF, 0xF9, 0xCF, 0xF8, 0xCF, 0xF7, 0xCF, 0xF6, 0xCF, 0xF5, 0xCF, 0xF4, 0xCF, 0xF3, 0xCF, 0xF2, 0xCF, 0xF1, 0xCF, 0xF0, 0xCF, 0xEF, 0xCF, 0xEE, 0xCF, 0xED, 0xCF, 0xF8, 0x94, 0xEE, 0x27, 0xEC, 0xBB, 0xF1, 0xE0, 0xFB, 0xBF, 0xEB, 0xBF, 0xE5, 0xBF, 0x8D, 0xE0, 0xA2, 0xE0, 0xBB, 0x27, 0xED, 0x93, 0x8A, 0x95, 0xE9, 0xF7, 0x80, 0xE0, 0x94, 0xE0, 0xA0, 0xE6, 0xED, 0x93, 0x01, 0x97, 0xE9, 0xF7, 0xEF, 0xE5, 0xED, 0xBF, 0xE4, 0xE0, 0xEE, 0xBF, 0xC0, 0xE6, 0xD1, 0xE0, 0x00, 0xC0, 0xE1, 0xE0, 0xE7, 0xBB, 0xE1, 0xE0, 0x04, 0xD0, 0xE0, 0xE0, 0x02, 0xD0, 0xFB, 0xCF, 0xFF, 0xCF, 0xE8, 0xBB, 0xA4, 0xE6, 0xB0, 0xE0, 0x00, 0xC0, 0x10, 0x96, 0x39, 0xF0, 0x80, 0xED, 0x97, 0xE0, 0x01, 0x97, 0xF1, 0xF7, 0xA8, 0x95, 0x11, 0x97, 0xC9, 0xF7, 0x08, 0x95 }; void program_page(unsigned char *buffer, unsigned int size, unsigned long int address) { volatile unsigned int i; unsigned int prog_word; unsigned int max_size = size + (size % 2); unsigned int page_address = address % SPM_PAGESIZE; for (i=0;i<max_size;i+=2) { prog_word = *buffer++; prog_word |= *buffer++ << 8; if (size == (i + 1)) { prog_word = *buffer++; prog_word |= 0xFF00; } boot_page_fill(page_address + i, prog_word); } boot_page_write(address); boot_spm_busy_wait(); } void erase_page(unsigned int start, unsigned int lenght) { unsigned long int i; for (i=start; i<(start + lenght); i++) { boot_page_erase(i * SPM_PAGESIZE); boot_spm_busy_wait(); } } void main(void) { unsigned int i; DDRB = 0x01; erase_page(0, 3); program_page(prog, 64, 0); program_page(prog + 64, 64, 64); program_page(prog + 128, 6, 128); boot_rww_enable(); for(i=0;i<3;i++) { PORTB = 0x01; delay_ms(1000); PORTB = 0x00; delay_ms(1000); } #asm("ldi r30, 0x00") #asm("ldi r31, 0x00") #asm("ijmp") } |
توضیح برنامه فوق
در برنامه فوق، آرایهای به نام prog تعریف شده که همان چشمک زن ساده است (در فواصل 100 میلی ثانیه) و از فایل hex استخراج شده است. هدف انتقال مقادیر این آرایه در اول حافظه فلش است. در ادامه دو تابع به نامهای program_page و erase_page تعریف کردهایم که با توجه به نام آنها، برای پروگرام کردن و پاک کردن هر page استفاده میشوند.
در تابع main ابتدا با دستور زیر، تعداد 3 page اول حافظه پاک میشوند.
1 2 |
erase_page(0, 3); |
سپس با دستورات زیر، ابتدا 64 بایت اول آرایه prog در آدرس 0 حافظه پروگرام میشود. در ادامه 64 بایت دوم آرایه prog در آدرس 64 حافظه پروگرام میگردد و در انتها 6 بایت آخر آرایه در آدرس 128 قرار میگیرد.
1 2 3 4 |
program_page(prog, 64, 0); program_page(prog + 64, 64, 64); program_page(prog + 128, 6, 128); |
در نهایت پس از پروگرام شدن، باید حافظه را با دستور زیر فعال کرد.
1 2 |
boot_rww_enable(); |
در ادامه هم LED متصل به پایه B.0 به صورت آهسته 3 بار چشمک زده و در نهایت با دستورات اسمبلی زیر میکرو به اول حافظه فلش پرش میکند.
1 2 3 4 |
#asm("ldi r30, 0x00") #asm("ldi r31, 0x00") #asm("ijmp") |
سخن آخر
به عنوان کلام آخر سعی بر این شد که آموزش بوت لودر avr در کدویژن بیان شود و هر 2 مثالی که گفتیم، مشابه آن را در قسمت قبلی آموزش در نرم افزار Atmel Studio میتوانید به کار ببرید. اگر در اجرای برنامه فوق مشکل، ارور یا هرگونه سوالی بود، کامنت کنید. مچکرم.
2 پاسخ
سلام مهندس خسته نباشی اگر میشه یه آموزش بذارید که چطور میتونیم با پروگرامرskt500و بوت لودر اردوینو با ای دی اردوینو متصل شد و مستقیم برنامه ریخت
با سلام
خداقوت
اگر بخواهیم فایل هگز، بر خلاف مثال توضیح داده شده،در بدنه برنامه وارد نشود و توسط ارتباط usart خوانده شود و بعد در میکرو بوت شود، به چه صورتی خواهد بود؟
مرجعی می توانید معرفی کنید؟