برنامهنویسی حرفهای میکروکنترلر درواقع مجموعه مقالاتی است که در آن سعی میکنیم ترفندهای کاربردی برنامه نویسی را با مثالهای عملی اندازهگیری کنیم و پرفومنس برنامه را بالا ببریم، پیش از این دو مقالهی دیگر با این مضمون منتشر کردهایم، مقاله اول تحتعنوان میکروکنترلر مقصر نیست مقصر برنامهنویسی است به اهمیت سبک برنامهنویسی و تاثیر آن در خروجینهایی سیستم میپرداخت، و در مقاله دوم که باعنوان برنامهنویسی میکروکنترلر را بهصورت حرفهای بیاموزیم منتشر شد، به اهمیت یادگیری برنامهنویسی حرفهای برای میکروکنترلرها پرداختیم و با یک مثالعملی تفاوت برنامه نوشتهشده توسط یک متخصص صرفا کامپیوتر و یک متخصص آشنا به سختافزار را بررسیکردیم و نشاندادیم که آشنایی با سختافزار و تسلط کامل به آن تا چهاندازه میتواند باعث تغییرات چشمگیر در عملکرد برنامهشود. در این مقاله قصد داریم که با طرح یک مثال عملی و کاربردی به تاثیر آشنایی با مفهوم حافظه جهت بهبود برنامه بپردازیم، پس برای حرفهایشدن با ما همراه باشد.
برنامه نویسی حرفه ای میکروکنترلر و طرح مساله
فرضکنید که ۴بایت دادهای موجود است که برای ذخیرهسازی یا انتقال نیاز است که این ۴بایت را درون یک متغیر ۴بایتی (uint32_t) ذخیرهکنیم؛ اتفاقا این تبدیل کاربرد زیادی در برنامهنویسی میکروکنترلر دارد و زیاد مورداستفاده قرار میگیرد، اما واقعا چندروش برای نوشتن چنین برنامهای وجود دارد؟ در ادامه روشهای مختلف را باهم بررسی میکنیم. این کار را به شیوههای مختلفی میتوان انجامداد که در این مقاله بررسی خواهیمکرد که سبکهای متفاوت با رویکردهای مختلف چه تاثیری در نتیجهنهایی خواهدداشت. در این آموزش از میکروکنترلر AVR با فرکانس ۱۶مگاهرتز و کامپایلر GCC با اپتیمایز حجم (-Os) استفاده خواهیمکرد.
برنامه ای که همه مینویسند
برنامه از این قراره که ۴بایت رو به یک متغیر ۳۲بیتی تبدیل کنیم، برای سنجش سرعت هم درنظرگرفتیم که با هر ۲۵۶سیکل اجرای تبدیل پایهای از میکروکنترلر تغییروضعیت دهد، هرچه فرکانس ایجادشده بالاتر باشد درنتیجه برنامهای بهتر نوشتهشدهاست. فرکانس ایجادشده را هم بااستفادهاز لاجیک آنالایزر اندازهگیری میکنیم. اما چطور اینکار را انجامدهیم؛ تعدادزیادی از برنامهنویسها به زبان آدمها اینکار را انجام میدهند نه زبان ماشین! اما منظوراز زبان آدمها چیست؟ بهتر است گریزی بزنم به دوران ابتدایی و ریاضیات آن دوره و مفاهیم یکان و دهگان و صدگان و هزارگان و. را زندهکنیم، فرضکنید میخواهیم عدد ۱۲۳ را ایجاد کنیم، عدد ۱ باید در جایگاه صدگان قرارگیرد آنرا در عدد صد ضرب میکنیم و عدد ۲ که باید در جایگاه دهگان قرارگیرد را در ۱۰ ضرب میکنیم و عدد ۳ را هم که در جایگاه یکان قرار دارد قائدتا در یک ضرب میکنیم، و مجموع حاصل سه عملیات را باهم جمع میکنیم که میشود ۱۲۳ حالا بهجای عدد ده و صد و هزار… از معادل کامپیوتری آن استفاده میشود یعنی ۲۵۶ و ۴۰۹۶ و ۶۵۵۳۶ و… که برنامه برهمین پایه و اصول نوشته میشود.
counter = (uint32_t)Byte[0] * 0x1; counter += (uint32_t)Byte[1] * 0x100; counter += (uint32_t)Byte[2] * 0x10000; counter += (uint32_t)Byte[3] * 0x1000000;
همانطورکه میبینید بایتهای ۰ تا ۳ در اعداد 0x1 تا 0x1000000 ضرب شدهاند و حاصل هر محاسبه با مقدارنهایی جمع شدهاست. برنامهنهایی به شکلزیر خواهدبود:
int main(void) { DDRB |= (1<<4) | (1<<3); uint32_t counter = 0; uint8_t Byte[4] = {0}; while(1) { Byte[0]+=1; Byte[1]+=2; Byte[2]+=3; Byte[3]+=4; counter = (uint32_t)Byte[0] * 0x1; counter += (uint32_t)Byte[1] * 0x100; counter += (uint32_t)Byte[2] * 0x10000; counter += (uint32_t)Byte[3] * 0x1000000; if(counter == 0x00) { PORTB ^= (1<<3); } } }
و نتیجه خروجی به شکلزیر خواهد بود:
همانطورکه در تصویر مشاهده میکنید این فرایند با فرکانس کاری ۱۶مگاهرتزی میکروکنترلر تنها ۶۳۸بار در ثانیه اجرا میشود!
برنامه را به زبان ماشین نزدیک کنیم
افردای که کمی باتجربهتر باشند و دید درستی نسبتبه پردازشهای صورتگرفته درون پردازنده داشتهباشند آنهم برروی یک پردازنده ۸بیتی که ضرب اعداد ۳۲بیتی برایش کاردشواری است، سعی میکنند که برنامه را منطقیتر و نزدیکتر به زبان ماشین بنویسند و قسمت تبدیل را بهشکلزیر بازنویسی میکنند:
counter = (uint32_t)Byte[0]; counter |= (uint32_t)Byte[1]<<8; counter |= (uint32_t)Byte[2]<<16; counter |= (uint32_t)Byte[3]<<24;
و نتیجه خروجی به شکلزیر خواهدبود:
همانطورکه در عکس مشخصاست با چند تغییرساده سرعت اجرای برنامه حدود ۳برابر بهتر شد، و هر ۱۷۳۵تبدیل در ۱ ثانیه انجام میشود. اما تغییرات چه بوده که اینچنین در خروجی تاثیر گذاشتهاست؟ اولین قدم حذف عملیات ضرب است و جایگزینی آن با عملیات شیف درغالب پردازندهها عملیاتمنطقی از عملیاتریاضی سریعتر انجام میشود و سیکل ماشین کمتری نیاز دارد بهطبع جایگزینی عملیات جمع با Or منطقی هم تاثیر بسزایی در فرایند داشتهاست. اما سوالیکه مطرح میشود این است که آیا بازهم بهتر میشود اینکار را انجامداد؟
برنامهنویس حرفهای به زبان مسلط است
قائدتا هر زبان برنامهنویسی دارای نکات و ریزهکاریهایی است که گاهی خیلی به فرایند برنامهنویسی و بهبود برنامه کمک میکند، زبان c هم از این قائده جدا نیست. بهعنواننمونه union یکیاز قابلیتهایی است که حدس میزنم بیشتر افراد حتی فراموشش کردهاند. یا اصلا کاربرد آنرا درست نمیداند و همین باعث میشود که برنامهها گاهی کند و سنگین نوشتهشوند. در این مثال دقیقا union به بهبود برنامه کمک میکند، قبلاز اینکه نمونهکد را ارائهکنیم بگذارید یک یادآوری درخصوص unionها داشتهباشیم؛ unionها دقیقا مشابه با Struct ها تعریف میشوند. تنها تفاوتشون اینهکه بهجای واژه struct باید از واژه union استفادهکرد. union ساختاریه که برای استفادهی بهینه از حافظه ساختهشده و بهشما اجازهمیده که چندتا متغیر رو داخل یک بلاک از حافظه ذخیرهکنید. برای روشنترشدن قضیه به عکسزیر دقتکنید.
همانطورکه در عکس فوق میبینید، union تعریف شده ۴بایت از حافظه رو اشغالکرده و هرکدام از اعضای ch به یکیاز این بایتها اشاره میکنند؛ یعنی دقیقا همون چیزیکه برای تبدیل لازم داریم. هر تغییر در [2]ch باعث میشه بیتهای ۱۶تا ۲۳ از متغیر val هم که یک متغییر ۳۲بیتی است نیز تغییر کند؛ بااستفادهاز همین قابلیت برنامه رو بازنویسی میکنیم.
union uconv { uint8_t B[4]; uint32_t W; }; union uconv conv; conv.B[0] = Byte[0]; conv.B[1] = Byte[1]; conv.B[2] = Byte[2]; conv.B[3] = Byte[3]; counter = conv.W;
و اما نتیجه:
همانطورکه در تصویر مشاهده میکنید استفادهاز union تاثیر مثبت در اجرای برنامه داشتهاست و سرعت آن را بهبود بخشیده است و تا ۱۹۵۲ تبدیل در ثانیه بالا بردهاست. ممکه با خودتون بگید این همه دردسر برای یه بهبود جزئی! باید اضافهکنم که همین بهبودهای جزیی تفاوت یک برنامهنویس حرفهای با برنامهنویس معمولی است.
چالش آخر برنامه نویسی حرفه ای میکروکنترلر
باهمهوجود توضیحات و راه کارهایی که ارائه کردیم، بازهم میشود برنامه را بهبود بخشید و سرعت آن را نزدیکبه دوبرابر بهتر کرد، اما فکر میکنید چطور این امکان وجود دارد؟ بااستفادهاز چه روشی چنین بهبودی امکانپذیر است؟ برای اینکه زیاد به بیراهه کشیده نشوید تکنیک مورداستفاده درخصوص نحوه دسترسیبه حافظه است.
همانطورکه ملاحظه میکنید دانش و تجربهکاری درخصوص سختافزار و برنامهنویسی میتواند کمک شایانی به بهبود برنامهنویسی حرفهای میکروکنترلر کند. برای آموزشهای بیشتر با ما همراهباشید.
منبع: سیسوگ