เจาะลึกโครงสร้าง STM32: Bus Matrix, Memory Map และกับดัก Unaligned Access
เกริ่นนำ: จินตนาการว่า STM32 คือ “โรงงานอัจฉริยะ”
สวัสดีครับ ยินดีต้อนรับสู่บทเรียนทฤษฎีที่จะทำให้คุณมองเห็น “ภาพในสมอง” ของ STM32 ได้ชัดเจนขึ้นครับ ในฐานะ Technical Writer ผมจะขอเปลี่ยนเรื่องโครงสร้างสถาปัตยกรรมที่ดูซับซ้อน ให้กลายเป็นเรื่องที่เข้าใจง่ายเหมือนเรากำลังดูผังโรงงานครับ
ระดับความยาก: ⭐⭐⭐ (เนื้อหาเชิงลึกแต่นำไปใช้ประโยชน์ได้จริง) เวลาที่ใช้: ~15 นาที
ถ้าเปรียบ STM32F4 เป็นโรงงานขนาดใหญ่:
- Cortex-M4 Core: คือ “ผู้จัดการโรงงาน” (CPU) ที่คอยสั่งงาน
- Flash Memory: คือ “ห้องสมุดคู่มือ” ที่เก็บคำสั่งการทำงาน (Code)
- SRAM: คือ “โต๊ะทำงาน” ที่วางเอกสารรอการประมวลผล (Variables)
- Peripherals (GPIO, UART): คือ “แผนกต้อนรับและจัดส่ง” ที่ติดต่อกับโลกภายนอก
- Bus Matrix: คือ “ระบบถนนและทางด่วน” ภายในโรงงานที่เชื่อมทุกอย่างเข้าด้วยกัน
ความเข้าใจเรื่องถนน (Bus) และแผนที่ (Memory Map) จะทำให้คุณเขียนโค้ดได้มีประสิทธิภาพสูงสุดและแก้ปัญหา Hard Fault ที่ชวนปวดหัวได้ครับ
2. ระบบบัส (Bus Matrix): ถนนหลายชั้น ไม่ใช่แค่เส้นเดียว
หลายคนเข้าใจผิดว่า CPU วิ่งไปหา RAM และ Peripherals บนถนนเส้นเดียวกัน (ซึ่งจะทำให้เกิดคอขวด) แต่ใน STM32F4 (Cortex-M4) ใช้สถาปัตยกรรมแบบ Harvard ที่มีถนนแยกกันชัดเจน และมีชุมทางที่เรียกว่า Multi-AHB Bus Matrix ครับ
2.1 ถนนสายหลักของ CPU (Master Ports)
CPU มี “ขา” หรือพอร์ตเชื่อมต่อหลักๆ 3 เส้นทาง เพื่อให้ทำงานขนานกันได้:
- I-Bus (Instruction Bus): ถนนสายด่วนสำหรับวิ่งไปหยิบ “คำสั่ง” จาก Flash เท่านั้น (ห้ามขนของอย่างอื่น)
- D-Bus (Data Bus): ถนนสำหรับขนถ่าย “ข้อมูล” (ตัวแปร, Debug) และเชื่อมต่อไปยังหน่วยความจำ CCM (Core Coupled Memory) โดยเฉพาะ เพื่อความเร็วสูงสุด
- S-Bus (System Bus): ถนนสายหลักที่วิ่งไปหา Peripherals และ SRAM ทั่วไป
2.2 ชุมทางจราจร (Bus Matrix)
Bus Matrix ทำหน้าที่เหมือน “วงเวียนอัจฉริยะ” ที่ยอมให้ Masters (ผู้สั่งงาน เช่น CPU, DMA1, DMA2) คุยกับ Slaves (ผู้รับคำสั่ง เช่น Flash, RAM, Peripherals) ได้พร้อมกันหลายคู่
Magic Moment: ในขณะที่ CPU กำลังอ่านคำสั่งจาก Flash (ผ่าน I-Bus), ตัว DMA สามารถขนข้อมูลจาก UART ไปเก็บที่ RAM (ผ่าน System Bus) ได้ พร้อมกัน โดยไม่แย่งถนนกัน นี่คือหัวใจของความแรงใน STM32F4 ครับ
3. แผนผังหน่วยความจำ (Memory Map): แผนที่เดียว เที่ยวทั่วไทย (4GB)
มาตรฐาน ARM Cortex กำหนดให้ทุกอย่างอยู่ใน “แผนที่แผ่นเดียว” ขนาด 4GB (32-bit address) ไม่ว่าจะเป็น RAM, Flash หรือขา Pin ต่างๆ ก็มี “บ้านเลขที่” (Address) ของตัวเอง

โครงสร้างหลักแบ่งเป็นโซนดังนี้:
| ช่วง Address (Hex) | ชื่อโซน (Region) | หน้าที่และการใช้งาน |
|---|---|---|
0x0000 0000 |
Code (Boot) | พื้นที่เริ่มต้นระบบ ปกติจะ Aliased (วาร์ป) ไปยัง Flash หรือ Bootloader |
0x0800 0000 |
Flash Memory | บ้านจริงๆ ของ Flash Memory ที่เก็บโปรแกรมของเรา |
0x2000 0000 |
SRAM | พื้นที่แรมหลัก (SRAM1, SRAM2) สำหรับเก็บตัวแปรและ Stack |
0x4000 0000 |
Peripherals | ที่อยู่ของอุปกรณ์ต่างๆ เช่น GPIO, Timer, UART |
0xE000 0000 |
System | โซนหวงห้ามของ CPU เช่น NVIC (ตัวคุม Interrupt) และ Debug |
4. การเข้าถึงแบบ Unaligned Access: สะดวกแต่มีราคาที่ต้องจ่าย
ในอดีต (เช่น ยุค ARM7 หรือ Cortex-M0) ถ้าคุณประกาศตัวแปร int (4 bytes) มันต้องวางอยู่ที่ Address ที่หารด้วย 4 ลงตัวเท่านั้น (0, 4, 8, C) ถ้าวางเบี้ยว (เช่น เริ่มที่ 1) จะเกิด Hard Fault ทันที
แต่ Cortex-M3/M4 (STM32F4) ฉลาดกว่านั้นครับ มันรองรับ Unaligned Access
สถานการณ์ตัวอย่าง
สมมติคุณมีตัวแปร uint32_t val (4 bytes) วางอยู่ที่ Address 0x20000001 (เลขคี่ ไม่ลงตัวด้วย 4)
- Cortex-M0: แจ้ง Error ทันที (Usage Fault) 💥
- Cortex-M4: อ่านค่าได้ถูกต้อง! ฮาร์ดแวร์จะแอบทำงานเบื้องหลังโดยการอ่าน Memory 2 ครั้ง แล้วเอามาต่อกันให้คุณอัตโนมัติ
ข้อควรระวัง (The Catch) ⚠️
แม้จะทำได้ แต่ “ของฟรีไม่มีในโลก” ครับ:
- ช้าลง: เสียเวลา Bus Cycle เพิ่มขึ้นเพราะต้องอ่าน 2 รอบแทนที่จะเป็นรอบเดียว
- Atomicity: การอ่านแบบ Unaligned ไม่การันตีว่าเป็น Atomic (อาจถูก Interrupt แทรกกลางระหว่างอ่านไบต์แรกกับไบต์หลังได้)
- คำสั่งยกเว้น: คำสั่ง Assembly บางตัว เช่น
LDRD(Load Double) หรือLDM(Load Multiple) ยังคงต้องการ Aligned Address เสมอ ถ้า Compiler เผลอใช้คำสั่งพวกนี้กับข้อมูลที่วางเบี้ยว ก็ Hard Fault ได้ครับ
สรุป: พยายามจัดโครงสร้างข้อมูล (Structure Padding) ให้ลงตัว (Aligned) เสมอ เพื่อประสิทธิภาพสูงสุด แต่ถ้ารับข้อมูลดิบจาก UART ที่เรียงมาแบบติดๆ กัน (Packed) Cortex-M4 ก็ช่วยชีวิตคุณได้โดยไม่ต้องเขียนโค้ดเรียงไบต์เองครับ