🌱 Lập Trình MPU - Memory Protection Unit trên STM32F4: Thanh Ghi và Ví Dụ

🌱 Lập Trình MPU - Memory Protection Unit trên STM32F4: Thanh Ghi và Ví Dụ

    Ở bài viết trước mình đã giới thiệu về ngoại vi MPU sử dụng trong lõi Cortex M4, cùng với các thanh ghi sử dụng để cấu hình ngoại vi MPU. Bài viết này mình sẽ giới thiệu về cách triển khai MPU cho vi điều khiển STM32.

ARM Cortex M4 Memory Protection Unit

Mục lục

👉 Phần cứng sử dụng

STM32F401RE - NUCLEO Board.

STM32F401 NUCLEO Board

👉 Phần mềm sử dụng

STM32CubeIDE ⇒ Xem hướng dẫn sử dụng.

👉 Bài toán

    Cấu hình 2 Region MPU cho Vi điều khiển STM32 như sau:

  • Background Region - Region 0:
    • Địa chỉ từ 0x00 đến 0xFFFF.FFFF.
    • Memory Types: Strong Order.
    • Access Right: Full Access.
  • Test Region - Region 1:
    • Địa chỉ từ 0x4000.0000 đến 0x4000.0400.
    • Memory Types: Normal, NonCacheable.
    • Access Right: Read Only.
MPU Regions
Hình 1: Minh họa cấu hình 2 Region MPU

    Sau đó, test thử công dụng của MPU bằng cách Write vào vùng nhớ Read Only (Region 1). Việc ghi này là không được cho phép nên chương trình sẽ nhảy vào HardFault, sau đó có thể test thêm để chương trình nhảy vào MemFault.

👉 Ví dụ lập trình MPU

    Dưới đây là code minh họa để cấu hình MPU trên STM32F401RE theo bài toán trên, sử dụng CMSIS trong STM32CubeIDE:

#include "stm32f4xx.h"

void MPU_Config(void) {
    // 1. Disable MPU trước khi cấu hình
    MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;

    // 2. Cấu hình Region 0 - Background Region
    MPU->RNR  = 0;                          // Chọn Region 0
    MPU->RBAR = 0x00000000;                 // Base Address = 0x00
    MPU->RASR = (0x1F << MPU_RASR_SIZE_Pos) |  // Size = 4GB (2^32, SIZE = 31)
                (0x3 << MPU_RASR_AP_Pos)   |   // Full Access (Privileged/Unprivileged)
                (0x2 << MPU_RASR_TEX_Pos)  |   // Strongly Ordered (TEX=010, C=0, B=0)
                MPU_RASR_ENABLE_Msk;           // Enable Region

    // 3. Cấu hình Region 1 - Test Region
    MPU->RNR  = 1;                          // Chọn Region 1
    MPU->RBAR = 0x40000000;                 // Base Address = 0x4000.0000
    MPU->RASR = (0x09 << MPU_RASR_SIZE_Pos) |  // Size = 1KB (2^10, SIZE = 9, đủ để bao 0x400)
                (0x5 << MPU_RASR_AP_Pos)   |   // Read Only (Privileged RO, Unprivileged RO)
                (0x1 << MPU_RASR_TEX_Pos)  |   // Normal, NonCacheable (TEX=001, C=0, B=0)
                MPU_RASR_ENABLE_Msk;           // Enable Region

    // 4. Enable MPU với Default Memory Map (PRIVDEFENA)
    MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;

    // Đồng bộ hóa để đảm bảo MPU được áp dụng
    __DSB();
    __ISB();
}

void HardFault_Handler(void) {
    while (1); // Dừng chương trình để debug
}

void MemManage_Handler(void) {
    while (1); // Dừng chương trình để debug
}

int main(void) {
    MPU_Config();

    // Test ghi vào Region 1 (Read Only)
    volatile uint32_t* test_addr = (uint32_t*)0x40000000;
    *test_addr = 0xDEADBEEF; // Ghi vào vùng Read Only → HardFault hoặc MemFault

    while (1);
}
    

    Giải thích:

  • Region 0: Full Access, Strong Order, bao toàn bộ không gian nhớ (4GB).
  • Region 1: Read Only, Normal NonCacheable, kích thước 1KB (đủ để bao phủ 0x4000.0000 - 0x4000.0400).
  • Khi ghi vào 0x4000.0000 (Read Only), chương trình sẽ nhảy vào HardFault (nếu MPU_CTRL.HFNMIENA = 0) hoặc MemFault (nếu bật HFNMIENA và MemManage được kích hoạt trong NVIC).

👉 Video thực hành

    Chi tiết các bạn xem Video thực hành bên dưới của mình:

>>>>>> Follow ngay <<<<<<<

Để nhận được những bài học miễn phí mới nhất nhé 😊
Chúc các bạn học tập tốt 😊

Nguyễn Văn Nghĩa

Mình là một người thích học hỏi và chia sẻ các kiến thức về Nhúng IOT.

Đăng nhận xét

Mới hơn Cũ hơn
//