آموزش برنامه نویسی با رزبری پای بدون سیستم عامل
در مقاله دوم آموزش رزبری پای، به معرفی ساختار CPU نحوه اجرای برنامه در رزبری پای پرداختیم. در این مقاله قصد داریم نحوه نصب و کانفیگ ابزارهای لازم جهت کامپایل کدهای نوشتهشده برای بردهای رزبری پای را آموزش دهیم.
همانطور که قبلا توضیح دادیم، پلتفرم سختافزاری رزبری پای مبتنی بر پردازنده های ARM است و نمیتوان از کامپایلرهای x86 مثل ویژوال استودیو برای کامپایل کدهای زربری استفاده کرد.
برای آشنایی با ابزارهای لازم و نحوه نصب و کانفیگ آنها با ما همراه باشید.
معرفی کامپایلرهای موجود:
واضح است برای تبدیل کدهای نوشتهشده به بیت کدهای قابلفهم توسط پردانده، نیاز به ابزاری است که اصطلاحاً به آن کامپایلر میگویند. کامپایلری که برای تبدیل کدهای رزبری پای موردنیاز است باید قابلیت کامپایل برای پلتفرم ARM را داشته باشد. کمپایلرهای زیادی وجود ندارند که دارای چنین قابلیتی باشند. کامپایلر هایی که قادر به پشتیبانی پلتفرم ARM باشند، (معروفترین آنها) به شرح زیر هستند:
- ARM Keil
- ARM IAR
- GCC
بله، تقریبا همین سه مورد! ممکن است فکر کنید که خب Atmel Studio یا CooCox و خیلی از ایزار های دیگر قابلیت کامپایل برای ARM را دارند ولی باید خاطرنشان کنم که هماکنون در خصوص کامپایلر صحبت میکنیم و موارد ذکرشده فقط ویرایشگر کد هستند و خود دارای کامپایلر نیستند. بهعنوان نمونه SEGGER Embedded Studio و حتی Atmel Studio از GCC استفاده میکنند.
از چه کامپایلری استفاده کنیم؟
تصمیمگیری در خصوص کامپایلر مورداستفاده با توجه به لیست معرفیشده چندان دشوار نیست. کامپایلر Keil و IAR هردو غیر رایگان هستند و برای استفاده از آنها باید لایسنس آنها را خریداری کرد. ما سعی میکنیم که به معرفی و استفاده از ابزارهای متنباز و رایگان بپردازیم. با توجه به پولی بودن کامپایلرهای Keil و IAR از آنها چشمپوشی کرده و آموزشهای خود را بر اساس کامپایلر رایگان GCC ادامه میدهیم.
اما در نظر داشته باشید که انتخاب کامپایلر رایگان GCC از روی ناچاری نیست. یکی از دلایل انتخاب این کامپایلر، انعطافپذیری زیاد و برتری آن نسبت به کامپایلر Keil است. شاید نتوان گفت که از IAR قویتر است اما به جرئت میتوان گفت که چیزی از آن کم ندارد و عملکردی بسیار نزدیک به یکدیگر دارند.
کامپایلر GCC چنان قدرتمند است که حتی ARM Keil امکان استفاده از آن را در محیط خود، به کاربر میدهد و کاربر میتواند بسته به نیاز از ویرایشگر Keil و کامپایلر GCC استفاده کند.
از طرفی رایگان و متنباز بودن کامپایلر GCC، باعث شده است که افراد زیادی در سراسر جهان از آن استفاده کنند و در بهینهسازی این کامپایلر مشارکت داشته باشند. با توجه به طیف وسیع استفادهکنندههای این کامپایلر، اگر احیاناً در قسمتی دچار مشکل شدید بهراحتی با جستجو در اینترنت میتوانید منشأ مشکل را پیدا و آن را حل کنید. از طرفی بیشتر سورسهای منتشرشده، با استفاده از این کامپایلر انجام شدهاند.
چگونگی نصب کامپایلر GCC:
نصب و راهاندازی GCC کار پیچیده ای نیست و بهراحتی قابل انجام است. اگر از لینوکس استفاده میکنید، لبخند بزنید چرا که برای نصب و پیکربندی کافی ست فقط خط زیر را در ترمینال تایپ کنید:
sudo apt–get install gcc–arm–embedded
|
دقت داشته باشید که دستور فوق برای نصب بر روی توزیعهای مبتنی بر دبیان است.
اما کاربران ویندوز نیاز است که یکی دو مرحله بیشتر طی کنند. ولی جای نگرانی نیست. مراحل خیلی ساده هستند و میتوان بهراحتی آنها را انجام داد.
در مرحله اول با مراجعه به سایت GCC ARM Embedded ، آخرین نسخه مبتنی بر ویندوز خود را دریافت کنید.
نکته : دقت کنید که حتما نسخه نصبی را دانلود کنید.
بعد از تمام شدن مراحل نصب، برای بررسی نصب صحیح میتوان دستور زیر را در خط فرمان (Command Prompt ویندوز یا ترمینال لینوکس) وارد کرد:
arm–none–eabi–gcc –v
|
در صورت نصب صحیح برنامههای موردنیاز، با اجرای دستور فوق، خروجی مطابق زیر خواهد بود:
Using built–in specs.
COLLECT_GCC=arm–none–eabi–gcc
COLLECT_LTO_WRAPPER=c:/program\ files\ (x86)/gnu\ tools\ arm\ embedded/4.9\ 2015
q1/bin/../lib/gcc/arm–none–eabi/4.9.3/lto–wrapper.exe
Target: arm–none–eabi
Configured with: /home/build/work/GCC–4–9–build/src/gcc/configure —build=i686–l
inux–gnu —host=i686–w64–mingw32 —target=arm–none–eabi —prefix=/home/build/wor
k/GCC–4–9–build/install–mingw —libexecdir=/home/build/work/GCC–4–9–build/instal
l–mingw/lib —infodir=/home/build/work/GCC–4–9–build/install–mingw/share/doc/gcc
–arm–none–eabi/info —mandir=/home/build/work/GCC–4–9–build/install–mingw/share/
doc/gcc–arm–none–eabi/man —htmldir=/home/build/work/GCC–4–9–build/install–mingw
/share/doc/gcc–arm–none–eabi/html —pdfdir=/home/build/work/GCC–4–9–build/instal
l–mingw/share/doc/gcc–arm–none–eabi/pdf —enable–languages=c,c++ —disable–decim
al–float —disable–libffi —disable–libgomp —disable–libmudflap —disable–libqu
admath —disable–libssp —disable–libstdcxx–pch —disable–nls —disable–shared –
–disable–threads —disable–tls —with–gnu–as —with–gnu–ld —with–headers=yes —
with–newlib —with–python–dir=share/gcc–arm–none–eabi —with–sysroot=/home/build
/work/GCC–4–9–build/install–mingw/arm–none–eabi —with–libiconv–prefix=/home/bui
ld/work/GCC–4–9–build/build–mingw/host–libs/usr —with–gmp=/home/build/work/GCC–
4–9–build/build–mingw/host–libs/usr —with–mpfr=/home/build/work/GCC–4–9–build/b
uild–mingw/host–libs/usr —with–mpc=/home/build/work/GCC–4–9–build/build–mingw/h
ost–libs/usr —with–isl=/home/build/work/GCC–4–9–build/build–mingw/host–libs/usr
—with–cloog=/home/build/work/GCC–4–9–build/build–mingw/host–libs/usr —with–li
belf=/home/build/work/GCC–4–9–build/build–mingw/host–libs/usr —with–host–libstd
cxx=‘-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm’ —with–pkgversion=‘GNU
Tools for ARM Embedded Processors’ —with–multilib–list=armv6–m,armv7–m,armv7e–m
,cortex–m7,armv7–r
Thread model: single
gcc version 4.9.3 20150303 (release) [ARM/embedded–4_9–branch revision 221220] (
GNU Tools for ARM Embedded Processors)
|
این خروجی یعنی تمام کارهای مربوط به نصب و پیکربندی بهدرستی انجام شده است.
نوشتن اولین برنامه
همیشه سختترین قسمت کار، نوشتن اولین برنامه است؛ چرا که پارامترهای زیادی وجود دارد که ممکن است در کار نکردن یک برنامه دخیل باشند و پیدا کردن مشکل را سخت کنند.
برای همین هم است که معمولاً اولین برنامه را در سادهترین حالت ممکن انتخاب میکنند. در دنیای کامپیوتر برنامه شروع را Hello world مینامند و بهسادگی کد زیر است:
main( ) {
printf(“hello, world”);
}
|
اما در دنیای الکترونیک وضع مقداری فرق دارد. پیادهسازی فرمان printf خود مستلزم آگاهی بسیار زیادی از اجزاء سختافزاری و نرمافزاری است. به همین دلیل معمولاً برنامه شروع در دنیای الکترونیک خیلی متفاوت از آن چیزی است که در دنیای کامپیوتر وجود دارد. در دنیای الکترونیک برای شروع با هر سختافزار و یا میکرو کنترلر، ابتدا سعی میشود برنامه یک چشمکزن نوشته شود. یعنی برنامه ای که با صفر و یک کردن یکی از پورت های موجود بر روی سختافزار، بتوان به صحت اجرای برنامه پی برد. در واقع سادهترین برنامهای که میتوان نوشت، برنامه یک چشمکزن است. برای همین است که در اکثر بردهای آموزشی، حداقل یک LED وجود دارد که میتوان وضعیت آن را با استفاده از پردازنده مرکزی کنترل کرد. سختافزار رزبری پای نیز از این قاعده جدا نبوده و خوشبختانه یک LED به نام ACT بر روی آن تعبیه شده است.
برای شروع، باید بدانیم که این LED به کدام پایه از پردازنده متصل شده است. با توجه به سختافزار های متفاوت در ورژن های مختلف برد رزبری، لازم است که یکی را بهعنوان سختافزار پیشفرض در نظر بگیریم و آموزش را بر اساس آن جلو ببریم. با توجه به قدیمی شدن ورژن 1 و کمیاب شدن آن در بازار، سختافزار پیشفرض را Raspberry pi 2 در نظر میگیریم.
قبل از هر چیز برای دانستن وضعیت اتصال ACT LED، باید شماتیک برد را داشته باشیم. خوشبختانه شماتیک آن توسط تیم توسعهی رزبری پای در دسترس قرار گرفته است. برای دانلود شماتیک میتوانید به سایت رزبری پای مراجعه کنید.
همانطور که در تصویر فوق مشاهده میکنید، ACT LED که در شماتیک بهصورت Status LED از آن نام برده شده به GPIO16 از پردازنده متصل شده است. در گام بعدی برای اینکه بتوانیم وضعیت یک GPIO را کنترل کنیم لازم است با ساز و کار مربوط به آن آشنا شویم و در واقع نیاز به دیتاشیت پردازنده داریم که خوشبختانه آن نیز در دسترس قرار گرفته است.
با توجه به اطلاعات بهدستآمده در خصوص سختافزار و همچنین رجیسترهای کنترلی پردازنده، بهراحتی میتوان برنامه موردنظر را نوشت. در این بخش از مقاله بیش از این وارد جزئیات نوشتن و عملکرد برنامه نمیشویم. در مقالات بعدی با توضیحات بیشتر، به نحوه پیادهسازی و کار با رجیستر های پردازنده خواهیم پرداخت.
/* The base address of the GPIO peripheral (ARM Physical Address) */
#define GPIO_BASE 0x3F200000UL
#define LED_GPFSEL GPIO_GPFSEL4
#define LED_GPFBIT 21
#define LED_GPSET GPIO_GPSET1
#define LED_GPCLR GPIO_GPCLR1
#define LED_GPIO_BIT 15
/** GPIO Register set */
volatile unsigned int* gpio;
/** Simple loop variable */
volatile unsigned int tim;
/** Main function – we’ll never return from here */
int main(void) __attribute__((naked));
int main(void)
{
/* Assign the address of the GPIO peripheral (Using ARM Physical Address) */
gpio = (unsigned int*)GPIO_BASE;
/* Write 1 to the GPIO16 init nibble in the Function Select 1 GPIO
peripheral register to enable GPIO16 as an output */
gpio[LED_GPFSEL] |= (1 << LED_GPFBIT);
/* Never exit as there is no OS to exit to! */
while(1)
{
for(tim = 0; tim < 500000; tim++)
;
/* Set the LED GPIO pin low ( Turn OK LED on for original Pi)*/
gpio[LED_GPCLR] = (1 << LED_GPIO_BIT);
for(tim = 0; tim < 500000; tim++)
;
/* Set the LED GPIO pin high ( Turn OK LED off for original Pi)*/
gpio[LED_GPSET] = (1 << LED_GPIO_BIT);
}
}
|
چگونگی کامپایل برنامه
برنامه فوق را با اسم blinkact.c ذخیره میکنیم. برای کامپایل برنامه قبل از هر مسئلهای نیاز است که یک سری تنظیمات را در خصوص پلتفرم مورداستفاده انجام بدهیم که خوشبختانه با توجه به کامند لاین بودن کامپایلر GCC، تمام تنظیمات مربوطه بهصورت پارامترهای ورودی دریافت می کند. برای کامپایل برنامه فقط کافی است که دستور زیر را یا در ترمینال یا کامند پرامپت اجرا کنیم:
arm–none–eabi–gcc –O0 –mfpu=neon–vfpv4 –mfloat–abi=hard –march=armv7–a –mtune=cortex–a7 –nostartfiles –g blinkact.c –o kernel.elf
|
کلید -mtune=cortex-a7 به کامپایلر میگوید که کد موردنظر را برای پردازندههای خانوادهی Cortex-a7 کامپایل کند و کلید -march=armv7-a به نوع معماری این خانواده اشاره دارد. بعد از اجرای دستور فوق، برنامه کامپایل شده و خروجی kernel.elf ایجاد میشود. فایلهای elf، حاوی اطلاعات زیادی در خصوص کتابخانههای مورداستفاده، پارامترهایی جهت خطایابی و همچنین اطلاعات اجرایی هستند. برای استخراج کدهای اجرایی نیاز است که دستور زیر را اجرا کنیم:
arm–none–eabi–objcopy kernel.elf –O binary kernel.img
|
بعد از اجرای دستور فوق، فایل اجرایی kernel.img ایجاد میشود.
هماکنون برنامه آماده اجرا است.
در مقالهی بعد، ابزارهای مورداستفاده را کاملتر خواهیم کرد و نحوه کانفیگ ادیتور Eclipse را نیز توضیح خواهیم داد.