وضعیت اعتبارسنجی: پروژهٔ واقعی با CubeMX 6.14.0 و CubeF3 1.11.6 تولید و با GCC 13.2.1 در هر دو حالت Debug و Release به صورت ساخت پاک با -Wall -Werror بدون خطا و هشدار ساخته شد. ELF، HEX، BIN و MAP واقعاً تولید شدهاند. محاسبات همراه با Python اجرا شدهاند. اجرای CubeIDE، پروگرام، تغییر Option Bytes و آزمون روی برد انجام نشدهاند؛ مراحل پروگرام، راهنمای انجام کار توسط خوانندهاند.
در این درس از مجموعه آموزشهای کاربردی، به مرحلهٔ کامپایل پروژه، شناخت فایلهای خروجی و انتقال برنامه به حافظه فلش میکروکنترلر STM32F303CBT6 میپردازیم. پیش از ورود به این بخش، لازم است پیکربندی اولیه سختافزار و تولید فایلهای پروژه را مطابق با راهنمای راهاندازی پروژه STM32F303 در درس پنجم تکمیل کرده باشید. در این درس ساختار خروجیهای کامپایلر، سیمبندی اصولی رابط برنامهریزی SWD با پروگرامر ST-LINK، هشدارهای امنیتی حافظه فلش و روشهای خطایابی اتصال روی برد GebraBit STM32F303 (GB100ST V2.0) به شکل دقیق بررسی میشود. کلاک کاری سیستم در این مرحله بدون تغییر و مبتنی بر نوسانساز داخلی HSI با فرکانس 8 MHz باقی میماند و پیکربندی فرکانس بیشینه 72 MHz تا درس نهم اجرا نخواهد شد.
پیکربندی ساخت و مشخصات مرجع پروژه
برای دستیابی به فرآیند ساخت پایدار و تکرارپذیر، مشخصات فنی محیط توسعه و ابزارهای مورد استفاده در جدول مرجع زیر تثبیت شدهاند. حداقل سطح انطباق کدهای این دوره، کامپایل با پرچمهای -Wall -Werror و دستیابی به ساخت پاک بدون خطا و هشدار است.
نسخهٔ بستهٔ F3 با شناسهٔ 663d2baae3604244f90ed80d0d757df17e36ada9 و پایگاه CubeMX برابر DB.6.0.140 است. منابع و .ioc همین پروژه همراه فایل دانلود قرار دارند. HSI با 8 MHz منبع SYSCLK است؛ HSE و LSE در .ioc پایهٔ رزروشده دارند و در مقداردهی فعلی روشن نشدهاند.
| ساخت واقعی | گزینههای واقعی | Flash در لینک، بایت | RAM در لینک، بایت | اندازهٔ فایل ELF، بایت |
|---|---|---|---|---|
| Debug | -O0 -g3 | 8112 | 1584 | 850060 |
| Release | -Os -g0 | 3688 | 1584 | 19320 |
اندازهٔ ELF روی دیسک با بایتهای بارگذاریشده در Flash فرق دارد؛ اطلاعات دیباگ یکی از علتهای بزرگی ELF حالت Debug است. رقم RAM شامل 12 بایت .data، مقدار 36 بایت اشیای .bss و رزرو حداقل heap برابر 512 و stack برابر 1024 بایت است، نه مصرف واقعی هنگام اجرا. خروجی HEX و BIN با objcopy از همان ELF ساخته شدهاند؛ اندازه و هش هر 8 خروجی در بسته موجود است.
در سامانههای بیلد امبدد مانند CMake و محیطهای توسعه، دو پیکربندی استاندارد تحت عناوین Debug و Release تعریف میشوند. این دو عنوان صرفاً نامهای قراردادی هستند و به صورت ذاتی معادل سطح بهینهسازی ثابتی نظیر -O0 یا -O3 محسوب نمیشوند؛ بلکه این پرچمهای پیکربندیشده درون زنجیره ابزار (Toolchain) هستند که میزان بهینهسازی و درج اطلاعات خطایابی را معین میکنند. در پیکربندی خطایابی، سطح بهینهسازی -Og گزینهای مناسب برای ترکیب بهینهسازی و اطلاعات دیباگ است؛ با این حال، حذف یا جابهجایی بعضی متغیرها همچنان ممکن است رخ دهد که مبنای بررسی جامع در درس هفتم خواهد بود.
کالبدشکافی فایلهای خروجی کامپایل و نقشه حافظه
فرآیند بیلد کدهای منبع C توسط کامپایلر و لینکر، مجموعهای از فایلهای باینری و گزارشهای متنی را تولید میکند. شناخت ماهیت فنی هر فرمت برای جلوگیری از خطا هنگام پروگرامکردن ضروری است:
- فرمت .elf (Executable and Linkable Format): فایل ساختاریافتهٔ خروجی لینک شامل بخشهای برنامه و آدرسهای آنها؛ جدول نماد و اطلاعات DWARF به گزینههای ساخت و حذفنشدن این اطلاعات وابستهاند. ELF حالت Debug همراه مقاله اطلاعات دیباگ دارد، اما وجود DWARF را برای هر ELF فرض نکنید.
- فرمت .hex (Intel HEX): فایل متنی شامل دادههای هگزادسیمال کدگذاریشده بر پایه ASCII که آدرس دقیق مقصد هر بایت و کدهای کنترلی (Checksum) را در هر خط تعریف میکند.
- فرمت .bin (Raw Binary): تصویر باینری خالص که فاقد هرگونه سربرگ، متادیتا یا نشانی بارگذاری در حافظه است. به همین علت هنگام استفاده از فایل .bin، کاربر موظف است آدرس پایه مبدا در حافظه فلش را به صورت دستی وارد کند.
- فایل گزارش .map: گزارش متنی ساختار حافظه که توسط لینکر تولید میشود و چیدمان بخشهای مختلف (.text، .rodata، .data و .bss) و اندازه نمادها را نمایش میدهد. این فایل هرگز تصویر اجرایی نیست و نباید روی حافظه منتقل شود.
| پسوند فایل | ماهیت محتوا | حاوی آدرس بارگذاری | شامل اطلاعات خطایابی | قابلیت دانلود مستقیم روی فلش |
|---|---|---|---|---|
| .elf | ساختار باینری ساختاریافته | بله | بله (در صورت فعال بودن پرچم) | بله (نرمافزار آدرس را از سربرگ میخواند) |
| .hex | متن اسکی خطبندیشده | بله | خیر | بله (بر پایه رکوردهای آدرس موجود در فایل) |
| .bin | بایتهای خام ماشین | خیر | خیر | بله (نیازمند تعیین دستی آدرس مبدا 0x08000000) |
| .map | گزارش متنی تفکیک حافظه | بله (صرفاً متنی) | خیر | خیر (هرگز قابل فلشکردن نیست) |
بر اساس مستند مرجع RM0316، حافظه فلش میکروکنترلر STM32F303CBT6 دارای ظرفیت 128 KiB بوده که در فضای آدرسدهی از 0x08000000 تا 0x0801FFFF نگاشت شده است. هنگام انتقال داده، قابلیت تطبیق (Program Verification) محتوای نوشتهشده در فلش را مجدداً خوانده و بایتبهبایت با فایل مبدا مقایسه میکند. توجه داشته باشید که Verify تطابق دادههای خواندهشده با فایل ورودی در همان بررسی را نشان میدهد، نه درستی منطق نرمافزاری برنامه را.

اصول سیمبندی رابط سختافزاری SWD و هشدارهای ولتاژ
پروگرامکردن و خطایابی میکروکنترلرهای سری Cortex-M در این دوره از طریق رابط SWD (Serial Wire Debug) انجام میشود؛ روشهای دیگری مانند بوتلودر موضوع درس جداگانهاند. در برد GebraBit STM32F303 (GB100ST V2.0)، این مسیر با خطوط ارتباطی زیر برقرار میشود:
- خط داده SWDIO: متصل به پایه PA13 برای انتقال دوطرفه دادههای کنترلی.
- خط کلاک SWCLK: متصل به پایه PA14 جهت همگامسازی تبادل اطلاعات تحت فرکانس کاری پروگرامر.
- خط ریست سختافزاری NRST: کنترل ریست پردازنده توسط پروگرامر جهت برقراری اتصال تحت ریست (Connect Under Reset).
- زمین مشترک (GND): مرجع ولتاژ یکپارچه و غیرقابلچشمپوشی میان پروگرامر و برد هدف.
- ولتاژ مرجع 3V3 (VTref): پایه سنجش ولتاژ در پروگرامرهای استاندارد نظیر ST-LINK/V2. این پایه به منظور نمونهبرداری از سطح منطقی تغذیه تارگت جهت تطبیق شیفترهای سطح ولتاژ داخلی تعبیه شده است و نقش منبع تغذیه ندارد.
تغذیه نامی ورودی برد GB100ST V2.0 برابر با 5V است که از طریق رگولاتور روی برد به سطح 3.3V برای تغذیه VDD تبدیل میگردد. هرگز ولتاژ 5V را به پایههای 3.3V، VDD یا خطوط SWD متصل نکنید. همچنین از اعمال تغذیه همزمان از پروگرامر و منبع مجزا بدون بررسی مدار تغذیه و مستندات همان پروگرامر خودداری ورزید. پایههای پروگرامرهای کپی یا غیراصل ممکن است از چیدمان استاندارد 20 پین ST-LINK/V2 رسمی تبعیت نکنند؛ بنابراین اتصال را صرفاً بر مبنای برچسب رسمی پایهها و دیتاشیت کنترل کنید نه رنگبندی سیمها.
روی برد یک نشانگر تغذیه (POWER LED) قرار دارد که روشنبودن مسیر تغذیهٔ نشانگر را نشان میدهد؛ جای اندازهگیری ولتاژ هدف را نمیگیرد، اما روشن بودن آن به هیچ عنوان اثباتکننده صحت ارتباط SWD یا اجرای کد نیست. الایدی کاربر (USER LED) به پایه PB6 متصل بوده و توسط یک ترانزیستور درایور NPN در حالت لاجیک یک (Active High) کنترل میشود و به دلیل وجود مقاومتهای روی برد، نیازی به سیمبندی قطعات جانبی ندارد.

هشدارهای امنیتی Option Bytes و خطر برگشتناپذیر RDP Level 2
بخش Option Bytes در حافظه ماندگار میکروکنترلر شامل بیتهای پیکربندی سختافزاری و سطوح حفاظت از خواندن حافظه (Readout Protection – RDP) است. مطابق با مرجع فنی RM0316، سه سطح حفاظتی تعریف شده است:
- سطح صفر (Level 0): حالت پیشفرض بدون قفل؛ دسترسی کامل به حافظه فلش و خطایابی از طریق درگاههای دیباگ میسر است.
- سطح 1: حفاظت خواندن محدودیتهایی بر دسترسی به Flash و حالتهای اجرای برنامه اعمال میکند. آن را معادل قطع کامل همهٔ ارتباطات SWD فرض نکنید. بازگشت از این سطح به 0 با پاکشدن Flash همراه است؛ در این درس چنین تغییری انجام نمیدهیم.
- سطح 2: حفاظت برگشتناپذیر است و دسترسی دیباگ و بوت از حافظهٔ سیستمی محدود یا غیرفعال میشود. امکان بازگرداندن RDP به سطح پایینتر وجود ندارد. این به معنی سوختن فیزیکی تراشه یا ناممکنشدن Reset و اجرای برنامهٔ موجود نیست؛ آن را برای آزمایش فعال نکنید.
در این آموزش، بخش Option Bytes صرفاً به صورت فقطخواندنی (Read-Only) بررسی میشود و اعمال تغییرات یا فعالسازی آزمایشی Level 2 اکیداً ممنوع است.
پیادهسازی برنامه چشمکزن و تحلیل زمانبندی HAL
برای بررسی عملیاتی فرآیند پروگرامکردن، قطعهکد تغییر وضعیت پایه PB6 در حلقه اصلی برنامه درون فایل Core/Src/main.c در محدوده نشانهگذاریشده درج میگردد:
فایل Core/Src/main.c را باز کنید و فقط دو خط زیر را داخل بلوک موجود USER CODE BEGIN 3 در حلقهٔ اصلی قرار دهید. حلقهٔ while یا توابع تولیدشده را دوباره نسازید. این دو خط از پروژهٔ واقعاً کامپایلشده استخراج شدهاند.
HAL_GPIO_TogglePin(USER_LED_GPIO_Port, USER_LED_Pin);
HAL_Delay(500U);
در این پیادهسازی، هر بار فراخوانی تابع HAL_GPIO_TogglePin نشاندهنده یک تغییر سطح منطقی (نیمپریود) است. یک سیکل کامل شامل دو بار فراخوانی (یک بار روشن و یک بار خاموش) است؛ بنابراین دوره تناوب اسمی تغییرات برابر با 1000 میلیثانیه یا فرکانس تقریبی 1 Hz خواهد بود. تابع HAL_GPIO_TogglePin وضعیت جاری پایه را از ثبات ورودی/خروجی (ODR) خوانده و وضعیت معکوس را در ثبات BSRR مینویسد؛ لذا این فرآیند ذاتاً یک عملیات خواندن-تغییر-نوشتن نرمافزاری است و نباید آن را با خروجی مستقل تایمر سختافزاری اشتباه گرفت.
در کتابخانه STM32F3 HAL، تابع HAL_Delay از شمارنده تیک سیستم (SysTick) استفاده میکند. در کد مبنا، شرط پایان تاخیر به صورت wait = Delay + uwTickFreq محاسبه میشود که با گام پیشفرض تیک برابر 1 ms، تاخیر درخواستی 500 میلیثانیه نیازمند گذشت 501 تیک است. علاوه بر این، خطای نوسانساز داخلی HSI طبق شرایط دیتاشیت، سربار اجرای دستورالعملها و اولویت سایر وقفهها موجب میشود زمانبندی دقیقاً بدون جیتر نباشد. تابع HAL_Delay یک تاخیر مسدودکننده پردازنده (Blocking Delay) است و در برنامهٔ این درس فقط در حلقهٔ اصلی به کار میرود. استفادهٔ مسدودکننده در وقفه میتواند رسیدگی به رخدادها را مختل کند و اگر تیک نتواند پیش برود، باعث انتظار بیپایان شود.
مراحل برنامهریزی تراشه با STM32CubeProgrammer و STM32CubeIDE
فرآیند ارسال کدهای کامپایلشده روی حافظه فلش از دو مسیر نرمافزاری رسمی پشتیبانی میشود:
روش اول: نرمافزار مستقل STM32CubeProgrammer
- پروگرامر ST-LINK را به درگاه USB رایانه و پینهای SWD برد متصل کرده و نرمافزار را اجرا کنید.
- در پانل سمت راست، نوع اتصال را روی ST-LINK و رابط را روی SWD قرار دهید؛ سرعت انتخابی باید با همان پروگرامر و سیمبندی سازگار باشد.
- روی دکمه Connect کلیک کنید. شناسه و اطلاعات هدفِ خواندهشده را با تراشهٔ برد تطبیق دهید؛ نبودن پاسخ را با موفقیت اتصال اشتباه نگیرید.
- از منوی Open File، فایل باینری .elf یا .hex را باز کنید. در صورت انتخاب فایل .bin، آدرس پایه بارگذاری را حتماً برابر با 0x08000000 تنظیم نمایید.
- گزینه Download را همراه با فعالسازی گزینه تایید (Verify programming) انتخاب کنید تا اطلاعات روی Flash داخلی نوشته و با فایل تطبیق داده شود. سپس مطابق نسخهٔ نرمافزار اجرای برنامه را آغاز یا برد را Reset کنید. چشمکزدن LED نتیجهٔ مورد انتظار است و در تهیهٔ این مقاله روی برد مشاهده نشده است.
روش دوم: کامپایل و پروگرام در محیط STM32CubeIDE
از نسخهٔ 2.0 به بعد CubeMX مستقل است. برای مسیر Eclipse از .ioc یک کپی در پوشهای جدا بسازید و خروجی STM32CubeIDE تولید کنید؛ سپس پروژهٔ دارای .project و .cproject را وارد IDE کنید. پروژه و پیکربندی Debug یا Release درست را انتخاب و Build Project را اجرا کنید. در Run / Debug Configurations رابط ST-LINK و SWD، فایل اجرایی همان ساخت و گزینههای دانلود و شروع اجرا را بررسی کنید؛ رفتار دانلود تابع تنظیمات Launch است. بستهٔ بررسیشدهٔ این مقاله خروجی CMake است؛ مسیر گرافیکی CubeIDE و پروگرام واقعی در این بررسی اجرا نشدهاند.
راهنمای عیبیابی خطاهای اتصال و عدم اجرای برنامه
در صورت بروز خطا در فرآیند شناسایی یا اجرای نرمافزار، مراحل ساختاریافته زیر را گامبهگام بررسی نمایید:
- عدم شناسایی پروگرامر در نرمافزار: درایور ST-LINK USB را در سیستمعامل بررسی کنید و از اتصال کابل مرغوب داده اطمینان حاصل فرمایید.
- خطای No target connected: سطح ولتاژ 3.3V و اتصال پایه زمین مشترک (GND) را با مولتیمتر بسنجید. سیمها را کوتاه و اتصالات را محکم نگه دارید؛ حد طول ثابتی برای همهٔ پروگرامرها و شرایط وجود ندارد.
- مسدود شدن ارتباط به دلیل بازتعریف پایهها: اگر در کدهای پیشین پایههای PA13 یا PA14 به عنوان ورودی/خروجی عادی استفاده شده باشند، از مد Connect Under Reset در تنظیمات پروگرامر استفاده کنید تا تراشه پیش از اجرای برنامه متوقف گردد. هرگز پایه NRST را به صورت دائم به زمین متصل نکنید.
- کاهش موقت فرکانس کلاک SWD: در صورت وجود نویز محیطی، فرکانس ارتباطی پروگرامر را در نرمافزار به مقداری پایینتر و پشتیبانیشده توسط همان ابزار کاهش دهید و نتیجهٔ اتصال را دوباره بررسی کنید.
- بررسی جامپر بوت: جامپر BOOT0 روی برد باید به صورت پیشفرض در وضعیت اتصال به زمین (GND) قرار داشته باشد تا پردازنده پس از ریست از حافظه فلش بوت شود.
- عدم چشمکزدن نشانگر پس از پروگرام: از گزینهٔ Run نرمافزار یا خط Reset طبق شماتیک و روش مستند برد استفاده کنید؛ وجود دکمهٔ اختصاصی Reset را صرفاً از نام برد فرض نکنید. فایل پروگرامشده و پیکربندی ساخت را نیز کنترل کنید. روشن ماندن نشانگر ثابت POWER به معنی کارکرد نرمافزار نیست؛ بررسی کنید که آیا برنامه درون حلقه بیپایان Error_Handler متوقف شده است یا خیر.
جدول مراجع معتبر و پیوند اسناد مرجع
تمامی پارامترهای فنی، آدرسهای حافظه و قواعد سختافزاری این درس مستقیماً از اسناد رسمی سازنده استخراج شدهاند:
| شناسه سند | عنوان مرجع فنی | مرجع ارائهدهنده | پیوند دسترسی رسمی |
|---|---|---|---|
| UM2237 | STM32CubeProgrammer software description | STMicroelectronics | دریافت راهنمای UM2237 |
| UM1075 | ST-LINK/V2 in-circuit debugger/programmer | STMicroelectronics | دریافت راهنمای UM1075 |
| RM0316 | STM32F303xB/C Reference Manual | STMicroelectronics | دریافت مرجع RM0316 |
| DS9118 | STM32F303CB Datasheet | STMicroelectronics | دریافت دیتاشیت DS9118 |
| GB100ST V2.0 | GebraBit STM32F303 Schematic V2.0 | GebraBit Technical Team | دریافت شماتیک برد GB100ST |
| UM2609 | STM32CubeIDE User Guide | STMicroelectronics | دریافت راهنمای UM2609 |
| HAL Source | STM32F3xx HAL Driver Repository | STMicroelectronics | مشاهده سورس در گیتهاب |
خودآزمایی مفهومی
-
چرا فایل با فرمت .bin برای پروگرامشدن روی میکروکنترلر نیازمند تعیین دستی آدرس 0x08000000 است، در حالی که فایلهای .hex و .elf به آن نیاز ندارند؟
پاسخ: فایل باینری خام (.bin) صرفاً دنبالهای از کدهای ماشین به صورت پیوسته است و هیچ سربرگ، متادیتا یا رکورد آدرسی ندارد؛ بنابراین پروگرامر مکان بارگذاری آن را نمیداند. در مقابل، فایلهای .elf و .hex دارای جدول بخشها یا فیلدهای آدرسدهی مبدا در ساختار خود هستند و نرمافزار آدرس مقصد را مستقیماً از فایل استخراج میکند. -
چرا وجود تاخیر HAL_Delay(500U) در حلقه اصلی موجب دستیابی به پریود کلی حدود 1 ثانیه (1 Hz) میشود نه 0.5 ثانیه؟
پاسخ: هر بار فراخوانی دستور تغییر وضعیت (Toggle) تنها نیمی از دوره تناوب (روشن یا خاموش شدن) را شکل میدهد. یک چرخه کامل عملکردی نیازمند یک بار روشن شدن و یک بار خاموش شدن است که در مجموع شامل دو تاخیر 500 میلیثانیهای و رسیدن به زمان تناوب تقریبی 1000 میلیثانیه میگردد. -
چرا موفقیت در اجرای گزینه Verify در نرمافزار پروگرامر اثباتکننده کارکرد درست منطق برنامه نیست؟
پاسخ: گزینه تایید (Verify) صرفاً تطبیق دادههای خواندهشده از حافظه فلش را با بایتهای فایل ورودی بررسی میکند و تطابق فایل و حافظه را در همان بررسی نشان میدهد؛ این فرآیند اطلاعی از درستی توابع، تنظیمات حلقهها، خطاهای زمانبندی یا باگهای منطقی نرمافزار ندارد. -
چرا فعالسازی حفاظت از حافظه سطح دو (RDP Level 2) در بخش Option Bytes نباید برای آزمایش استفاده شود؟
پاسخ: سطح دو حفاظت در خانواده STM32F3 یک پیکربندی ماندگار و بازگشتناپذیر در حافظهٔ Option Bytes (Irreversible) است. امکان پایینآوردن سطح حفاظت وجود ندارد و دسترسی دیباگ غیرفعال میشود؛ این با سوختن فیزیکی تراشه یا ناتوانی در Reset فرق دارد. برنامهٔ موجود میتواند همچنان اجرا شود و برخی کاربردها ممکن است از قبل برنامهریزی درونبرنامهای داشته باشند؛ راه بازگشایی RDP یا جایگزین سادهٔ دیباگ نیست.
تمرین عملی و ارزیابی مقایسهای
پروژه را در هر دو پیکربندی Debug و Release کامپایل نمایید. اندازه بخشهای مختلف حافظه را از گزارش بیلد استخراج کرده و نتایج را در کاربرگ زیر ثبت کنید. پس از انتقال برنامه روی برد واقعی، رفتار مشاهدهشده را با مقادیر محاسباتی تطبیق دهید:
| پیکربندی بیلد | پرچم بهینهسازی | حجم بخش .text (بایت) | حجم بخش .data (بایت) | حجم بخش .bss (بایت) | پریود محاسباتی (ثانیه) | وضعیت در برد واقعی |
|---|---|---|---|---|---|---|
| Debug | درج پرچم واقعی بیلد | ثبت از خروجی بیلد | ثبت از خروجی بیلد | ثبت از خروجی بیلد | 1.0 | در انتظار تست کاربر |
| Release | درج پرچم واقعی بیلد | ثبت از خروجی بیلد | ثبت از خروجی بیلد | ثبت از خروجی بیلد | 1.0 | در انتظار تست کاربر |
در درس هفتم با تکیه بر زیرساخت ارتباطی SWD و پیکربندی Debug، وارد دنیای خطایابی بیدرنگ، تنظیم نقاط توقف (Breakpoints) و پایش زنده متغیرها خواهیم شد.
دانلود فایلهای همراه این آموزش
پروژهٔ کامل و فایل .ioc، خروجیهای واقعی ELF و HEX و BIN و MAP در Debug و Release، گزارش ساخت بدون هشدار، اندازهها و هش فایلها، اسکریپت محاسبات و تصویرهای آموزشی. ساخت با CMake بررسی شده است؛ پروگرام و آزمون روی برد و اجرای CubeIDE انجام نشدهاند.
- پوشهٔ درس 6 در گیتهاب
- دانلود همهٔ فایلهای همراه ـ ZIP، حدود 1095 kB
- راهنمای استفاده از فایلهای این درس
دانلود به نسخهٔ مشخص همراه مقاله متصل است. ابتدا ZIP را استخراج و راهنما را مطالعه کنید.