آیا برای هر بار بارگذاری برنامه حتماً به ST-LINK نیاز داریم؟ STM32F303CB یک برنامهٔ کارخانهای به نام Bootloader در حافظهٔ سیستم دارد که میتواند برنامهٔ کاربر را از رابط ارتباطی دریافت کند. در این درس، مسیر USART1 را برای برد GB100ST بررسی میکنیم و فایل برنامهٔ قابل بارگذاری، سیمبندی و مراحل کار با STM32CubeProgrammer را آماده میکنیم. این راهنما با کامپایل پروژه همراه است؛ اتصال به مبدل و پروگرام روی برد هنوز انجام نشده است.
وضعیت اعتبارسنجی: کامپایلشده؛ پروژهٔ واقعی بدون خطا و هشدار ساخته شده است. اجرای روی برد، پروگرام و اندازهگیری فیزیکی هنوز انجام نشدهاند.
مثال برای STM32F303CBT6 با بستهٔ LQFP48 روی برد GebraBit GB100ST V2.0 است. قطعهکدها گزیدهٔ پروژهٔ کاملاند و به تعریفها و فایلهای همراه وابستهاند.
تفاوت برنامهٔ کاربر با بوتلودر کارخانهای
برنامهای که خودمان میسازیم در Flash اصلی قرار میگیرد. Bootloader کارخانهای، برنامهٔ دیگری است که ST هنگام تولید در حافظهٔ سیستم قرار داده است. پاککردن عادی Flash کاربر، این برنامهٔ کارخانهای را جایگزین نمیکند. بنابراین برای آزمایش این درس لازم نیست ابتدا یک بوتلودر اختصاصی در Flash بنویسیم.
هنگام ریست، پردازنده از جدول بردار انتخابشده، مقدار اولیهٔ پشته و نشانی شروع راهانداز را دریافت میکند. در این تراشه، سه انتخاب بوت شامل Flash کاربر، حافظهٔ سیستم و SRAM وجود دارد. انتخاب محل بوت به معنی تغییر نشانی فیزیکی حافظه نیست؛ حافظهٔ انتخابشده در ابتدای فضای آدرس نیز قابل دسترسی میشود.
Flash تراشهٔ CB از 0x08000000 شروع میشود و 128 KiB ظرفیت دارد. طبق بخش مربوط به F303xB/C در AN2606 Rev 70، بلوک 8 KiB بوتلودر سیستم از 0x1FFFD800 شروع میشود. این نشانی را نباید از مثال یک STM32 دیگر برداشت کرد.
BOOT0، بیت nBoot1 و سیمبندی برد
در این خانواده، برای ورود به بوت حافظهٔ سیستم، الگوی 2 سند AN2606 لازم است: پایهٔ BOOT0=1 و بیت گزینهٔ nBoot1=1. این بیت از Option Bytes میآید؛ پایهٔ فیزیکی PB2 با نام BOOT1 در مثالهای بعضی خانوادهها جایگزین آن نیست. مقدار واقعی گزینه را فقط بررسی کنید؛ این پروژه آن را تغییر نمیدهد.
در برد GB100ST V2.0، جامپر BOOT SEL در حالت معمول BOOT0 را به GND میبندد. سمت دیگر، آن را از طریق R3 برابر 10 kΩ به 3.3 V متصل میکند. وضعیت جامپر را پیش از ریست انتخاب کنید. ورود به حافظهٔ سیستم را فقط با بالا بردن BOOT0، بدون توجه به بیت nBoot1، تضمینشده فرض نکنید.

برای مسیر USART1، خروجی TX مبدل USB-UART با منطق 3.3 V را به PA10 و ورودی RX مبدل را به PA9 وصل کنید. زمین مشترک لازم است. PA9 و PA10 نام منطقی پایهاند؛ شمارههای فیزیکی آنها در بستهٔ LQFP48 بهترتیب 30 و 31 هستند. جهت هدر برد را از شماتیک و نام پایهها بخوانید؛ شکل آموزشی، شمارهٔ فرضی هدر نمیسازد.
برد را از مسیر تغذیهٔ مناسب خودش روشن کنید و خروجی تغذیهٔ نامعلوم مبدل را به ریل برد وصل نکنید. مبدل سطح RS-232 یا منطق 5 V جای مبدل 3.3 V این آزمایش نیست.

حافظهٔ انتخابشده در نشانی صفر آینه میشود، ولی Flash فیزیکی همچنان در 0x08000000 است. دو کلمهٔ نخست جدول بردار، بهترتیب مقدار اولیهٔ MSP و بردار ریستاند؛ آنها دستورهای عادی ابتدای برنامه نیستند. رجیستر VTOR در ادامه محل جدول بردار استثناها را تعیین میکند.
رابطهای موجود و قالب پروتکل سریال
بخش 26 از AN2606 برای F303xB/C، USART1 روی PA9/PA10، USART2 روی PD5/PD6 و USB DFU را بیان میکند. PD5 و PD6 در بستهٔ 48 پایهای ما بیرون آورده نشدهاند. USB نیز به شرایط کلاک و اتصال، از جمله مقاومت بالاکش خارجی 1.5 kΩ روی DP، نیاز دارد؛ وجود نام USB در فهرست تراشه به معنی آمادهبودن درگاه USB روی برد نیست. مسیر این درس USART1 است.
Bootloader کلاک خودش را تنظیم میکند؛ تنظیم 72 MHz برنامهٔ آموزشی را به آن نسبت ندهید. جدول نسخهها در سند، V4.1 را برای این گروه معرفی میکند، اما این عدد به معنی خواندن نسخهٔ ROM از برد ما نیست. فرمان Get باید فهرست دستورهای واقعاً پشتیبانیشده را مشخص کند.
طبق AN3155، قالب USART بوتلودر 8 بیت داده، توازن زوج و 1 بیت توقف، یعنی 8E1 است. میزبان بایت همگامسازی 0x7F را میفرستد و در ارتباط موفق انتظار ACK برابر 0x79 داریم. NACK برابر 0x1F است؛ نبود پاسخ و NACK را یک وضعیت واحد فرض نکنید.

در 115200 baud، زمان اسمی هر بیت حدود 8.681 میکروثانیه و زمان یک فریم 11 بیتی حدود 95.486 میکروثانیه است. اینها محاسبهٔ زمان خطاند، نه زمان پاسخ ROM و نه اندازهگیری واقعی اسیلوسکوپ.
Tbit = 1 / 115200 s; Tframe = 11 × Tbit
هر دستور با متمم بایتی خود همراه میشود؛ مثلاً Get با دو بایت 0x00 و 0xFF ارسال میشود و XOR آنها 0xFF است. در بستههای داده، قاعدهٔ checksum متفاوت است: XOR داده و بایت checksum باید 0 شود. همهٔ دستورهای جدید سند عمومی AN3155 لزوماً در ROM قدیمی این تراشه موجود نیستند.
بارگذاری با STM32CubeProgrammer؛ مراحل پیشنهادی آزمایش
فایلهای BIN و HEX همراه از پروژهٔ واقعی همین درس ساخته شدهاند. این برنامهٔ ساده در Flash اصلی اجرا میشود، LED روی PB6 را تغییر میدهد و از USART1 گزارش میفرستد؛ خودش Bootloader نیست. فایل BIN بایت خام است و نشانی مقصد همراهش نیست. برای این نسخه، نشانی شروع 0x08000000 است. فایل Intel HEX رکوردهای نشانی را نیز دارد.

- سیمبندی 3.3 V، زمین و جهت TX/RX را بررسی کنید. پایانهای که پورت سریال را گرفته ببندید.
- گزینهٔ nBoot1 را بررسی و BOOT SEL را برای ورود به حافظهٔ سیستم تنظیم کنید؛ سپس برد را ریست کنید.
- در STM32CubeProgrammer رابط UART، پورت مبدل و قالب Even، 8 بیت داده و 1 توقف را انتخاب کنید. نرخ 115200 یک انتخاب آزمایشی در این راهنماست؛ ابتدا اتصال را برقرار و پاسخ واقعی دستگاه را بررسی کنید.
- فایل همان نسخه را انتخاب کنید. برای BIN نشانی پایه را صریحاً 0x08000000 بگذارید؛ برای HEX نشانیهای رکوردها را بررسی کنید. محدودهٔ پاککردن و نوشتن را پیش از اجرای Download کنترل کنید.
- پس از نوشتن، بررسی صحت یا Verify را انجام دهید و نتیجهٔ واقعی را ثبت کنید؛ صرف پایان کپی فایل کافی نیست.
- BOOT SEL را به GND برگردانید و ریست کنید. سپس برای گزارش برنامهٔ کاربر، پورت را با 115200 و قالب 8N1 باز کنید.
برای این پروژه نیازی به تغییر حفاظت خواندن، نوشتن Option Bytes یا پاککردن کامل تراشه نیست. اگر ابزار به علت حفاظت اجازهٔ عملیات نداد، وضعیت را ثبت و بررسی کنید؛ NACK مجوز اجرای خودکار فرمان رفع حفاظت نیست. جزئیات ظاهر پنجرهها با نسخهٔ ابزار فرق میکند؛ شکل ارائهشده نمودار مراحل است، نه اسکرینشات اجرای انجامشده.
VTOR چه میکند و چه نمیکند؟
اگر برنامهای در نشانی دیگری پیوند بخورد، صرف کپی بایتها به آن محل یا تغییر VTOR برای اجرای درست کافی نیست. VTOR فقط پایهٔ جدول بردار استثناها را تعیین میکند؛ پشته و PC را مقداردهی نمیکند و عملیات آغاز به کار C را انجام نمیدهد.

در یک بوتلودر اختصاصی، قرارداد کامل انتقال کنترل باید شامل اعتبارسنجی تصویر و بردارها، وضعیت وقفهها و DMA، کلاک و واحدهای جانبی، محدوده و همترازی پشته، بردار Thumb و رفتار SystemInit برنامهٔ مقصد باشد. پس از تغییر MSP نباید اجرای C با فرض پشتهٔ قبلی ادامه پیدا کند. شکل این درس فقط این مسئولیتها را معرفی میکند و دستور اجرایی عمومی برای پرش ارائه نمیدهد.
پروژهٔ حاضر در نشانی معمول 0x08000000 پیوند خورده است. در main.c، USER CODE BEGIN 1، مقدار VTOR ثبت و سپس پیش از HAL_Init صریحاً به پایهٔ Flash تنظیم میشود؛ DSB و ISB ترتیب اثرگذاری را کنترل میکنند. مقدارهای اولیهٔ MSP و بردار ریست از تصویر خوانده میشوند. این کد نه به ROM میپرد و نه یک برنامهٔ جابهجاشده را اجرا میکند.
گزیدهٔ تابع تولیدشده در Core/Src/usart.c؛ این تعریف را در main دوباره ننویسید.
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
main.c USER CODE 1 — VTOR and vector snapshot
گزیدهٔ دقیق سورس کامپایلشده؛ تابع مستقل جدیدی نیست و نباید تابع تولیدشده را دوباره تعریف کرد.
vtor_before = SCB->VTOR;
SCB->VTOR = FLASH_BASE; /* Normal application vectors, not a bootloader jump. */
__DSB();
__ISB();
vtor_after = SCB->VTOR;
vector_initial_msp = *(const volatile uint32_t *)(FLASH_BASE);
vector_reset_handler = *(const volatile uint32_t *)(FLASH_BASE + 4U);
main.c USER CODE 0 — ReportApplication
گزیدهٔ دقیق سورس کامپایلشده؛ تابع مستقل جدیدی نیست و نباید تابع تولیدشده را دوباره تعریف کرد.
static void ReportApplication(void)
{
char line[128];
int n = snprintf(line, sizeof line,
"APP HCLK=%lu VTOR=%08lX MSP0=%08lX RESET=%08lX count=%lu\r\n",
(unsigned long)HAL_RCC_GetHCLKFreq(), (unsigned long)vtor_after,
(unsigned long)vector_initial_msp, (unsigned long)vector_reset_handler,
(unsigned long)heartbeat_count);
if ((n > 0) && ((size_t)n < sizeof line)) {
uart_status = HAL_UART_Transmit(&huart1, (uint8_t *)line, (uint16_t)n, 20U);
}
}
main.c USER CODE 3 — loop excerpt
گزیدهٔ دقیق سورس کامپایلشده؛ تابع مستقل جدیدی نیست و نباید تابع تولیدشده را دوباره تعریف کرد.
HAL_GPIO_TogglePin(USER_LED_GPIO_Port, USER_LED_Pin);
heartbeat_count++;
ReportApplication();
HAL_Delay(500U);
در فایل SystemInit همین نسخه، تنظیم VTOR مشروط به فعالبودن USER_VECT_TAB_ADDRESS است؛ در تنظیم پیشفرض پروژه این گزینه فعال نیست. بنابراین تنظیم صریح کد کاربر را نباید به رفتار همیشگی کد تولیدشده نسبت داد. نشانیها و بردارهای واقعی فایل ELF در گزارش همراه ثبت شدهاند.
آزمایش، ثبت نتیجه و عیبیابی
خروجی ساخت این نسخه، فایل BIN با طول 16112 بایت است. کلمهٔ نخست تصویر برابر 0x20008000 و بردار ریست برابر 0x08003D69 است. اینها از فایل ساختهشده خوانده شدهاند و شاهد پروگرام روی برد نیستند. در صورت ساخت دوباره پس از تغییر کد، بردار ریست ممکن است جابهجا شود.
بعد از پروگرام و ریست در حالت Flash، انتظار داریم گزارش APP، کلاک 72000000 و VTOR برابر 0x08000000 را ببینیم؛ مقدار واقعی و وضعیت Verify را در کاربرگ ثبت کنید. LED باید با اجرای حلقه تغییر کند، اما چشمک آن بهتنهایی درستی تمام فرایند پروگرام را ثابت نمیکند.

| نشانه | بررسی |
|---|---|
| اتصال ROM پاسخی ندارد | BOOT SEL و ریست، بیت nBoot1، پورت آزاد، زمین و جهت TX/RX و قالب 8E1 را بررسی کنید. |
| دستور NACK میگیرد | پاسخ Get، پشتیبانی دستور، قالب بسته و checksum و وضعیت حفاظت را بخوانید؛ یک علت قطعی از روی هر NACK نتیجه نگیرید. |
| نوشتن یا Verify ناموفق است | گزارش ابزار، نشانی و نوع فایل و محدودهٔ حافظه را بررسی کنید. وضعیت RDP و WRP را بدون تغییر خودکار ثبت کنید. |
| پس از دانلود APP اجرا نمیشود | BOOT0 را به حالت Flash برگردانید، ریست کنید و فایل و نشانی بارگذاری را با همین نسخه تطبیق دهید. |
| برنامه اجرا میشود ولی UART دیده نمیشود | پس از پایان کار CubeProgrammer، پورت را برای برنامه با 8N1 باز کنید. uart_status، نتیجهٔ HAL_UART_Transmit برنامه است و با پاسخ ACK در ROM فرق دارد. |
مدل همراه، فریم 8E1 و قواعد بستهها را بدون اتصال سریال بررسی میکند. نه آن مدل و نه کامپایل، جای خواندن پاسخ واقعی ROM، Verify و مشاهدهٔ اجرای برد را نمیگیرد.
پرسشهای خودآزمایی
1. آیا برای اجرای بوتلودر کارخانهای باید کدی در Flash نصب کنیم؟
خیر؛ برنامهٔ کارخانهای از قبل در حافظهٔ سیستم وجود دارد. پروژهٔ همراه فقط برنامهٔ کاربر برای بارگذاری است.
2. آیا BOOT0 بالا بهتنهایی همیشه کافی است؟
در این تراشه برای الگوی حافظهٔ سیستم، nBoot1 نیز باید 1 باشد. وضعیت واقعی را بررسی کنید.
3. چرا پس از پروگرام قالب پایانه را عوض میکنیم؟
ROM از 8E1 استفاده میکند، ولی برنامهٔ آموزشی همراه روی 115200 8N1 تنظیم شده است.
4. آیا VTOR همان نشانی شروع برنامه است؟
VTOR محل جدول بردار استثناهاست؛ بهتنهایی نه پشته و PC را تنظیم میکند و نه راهاندازی C را انجام میدهد.
5. تفاوت BIN و HEX در بارگذاری چیست؟
BIN نشانی مقصد درون خود ندارد؛ HEX رکوردهای نشانی دارد. هر دو باید با چیدمان همان نسخهٔ برنامه سازگار باشند.
6. آیا NACK یعنی باید حفاظت تراشه برداشته شود؟
خیر؛ دستور پشتیبانینشده، بستهٔ نادرست و وضعیت حفاظت از علتهای قابل بررسیاند. رفع حفاظت خودکار راهحل عمومی نیست.
تمرینها
1. پایه؛ بازسازی فریم همگامسازی
بیتهای دادهٔ 0x7F را با ترتیب ارسال و بیت توازن در قالب 8E1 بنویسید.
معیار بررسی: 7 بیت 1 در داده داریم؛ بیت توازن 1 تعداد را زوج میکند و فریم با شروع و توقف، 11 بیت دارد.
2. متوسط؛ قواعد دو نوع بسته
دو بایت Get و بایتهای نشانی پایهٔ 0x08000000 همراه checksum را بهصورت آفلاین بنویسید.
معیار بررسی: برای دستور، 0x00 و 0xFF با XOR برابر FF؛ برای نشانی، 08 00 00 00 و checksum برابر 08 با XOR کل صفر باشند. چیزی به برد ارسال نکنید.
3. پیشرفته؛ تحلیل انتقال کنترل
مسئولیتهای بوتلودر اختصاصی و برنامهٔ مقصد را در یک نمودار جدا کنید.
معیار بررسی: تغییر VTOR با تنظیم MSP/PC و مقداردهی دادهها اشتباه نشود؛ اعتبارسنجی تصویر، وقفهها و قرارداد SystemInit نیز مشخص باشند.
منابع و نسخهٔ ساخت
| مرجع | کاربرد |
|---|---|
| DS9118 Rev 14 | ظرفیت دقیق تراشه، پایهها و مشخصات حافظه |
| RM0316 Rev 10 | نقشهٔ حافظه و سازوکار واحدهای خانواده؛ بخشهای مرتبط بررسی شدهاند |
| ES0204 Rev 11 | محدودیتهای وابسته به بازنگری سیلیکون |
| GebraBit GB100ST V2.0 | مدار برد، پایهها و انتخاب بوت |
| AN2606 Rev 70, February 2026 | بخش 26، جدولهای 57 و 58 و الگوی 2؛ رابطها و حافظهٔ سیستم همین تراشه |
| AN3155 Rev 22, September 2026 | قالب 8E1، همگامسازی و قواعد بستهها |
| STM32CubeProgrammer | ابزار رسمی بارگذاری؛ رابط گرافیکی در این کار آزمایش نشده است |
| stm32f3xx_hal_uart.c | گزارش UART برنامهٔ همراه، جدا از پروتکل ROM |
ساخت واقعی با CubeMX 6.14.0 و DB 6.0.140، بستهٔ CubeF3 V1.11.6 و GCC 13.2.1 در مسیر CMake انجام شده است. گزینههای Debug شامل -O0 -g3 -Wall -Werror هستند. شناسهٔ بسته 663d2ba و HAL 953955a است؛ شناسههای کامل و گزارشها در فایلهای همراه آمدهاند. رابط گرافیکی IDE و اجرای فیزیکی برد آزمایش نشدهاند.
دانلود فایلهای همراه درس 34
بسته شامل پروژهٔ واقعی با IOC و سورس، خروجیهای ELF/MAP و گزارش ساخت، مدل محاسباتی، کاربرگ آزمایش، مجوزها و 6 تصویر همراه اسکریپت قابل ویرایش است. ابتدا ZIP را استخراج و README را بخوانید. اجرای روی برد و اندازهگیریها هنوز انجام نشدهاند.