🌱 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.
Mục lục
👉 Phần cứng sử dụng
STM32F401RE - 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.
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 😊