🌱 Hoạt động của MPU với DMA
Ở những bài viết trước mình đã từng nói về MPU - Memory Protection Unit. MPU được biết đến như một ngoại vi sử dụng để bảo vệ việc truy cập bộ nhớ. Tuy nhiên, việc hạn chế truy cập đó là đối với Core, còn đối với những master khác (Ví dụ như DMA) thì MPU có thể hạn chế truy cập của chúng đến memory hay không?
Câu trả lời là không! Và bên dưới mình sẽ giải thích và Demo vấn đề này.
Xem thêm:
👉 Về mặt lý thuyết
Rất đơn giản khi xét về mặt lý thuyết, MPU là một Core Peripheral, vì vậy nó sẽ chỉ tác dụng đối với Core. Chúng ta có thể nhìn vào sơ đồ hoạt động của MPU như hình sau:
Có thể thấy MPU nằm trong processor, và là trung gian giữa Core và Memory. Trong khi đó, DMA không nằm trong processor. Vì vậy, dễ thấy DMA và MPU không có liên quan gì đến nhau.
👉 Về mặt thực hành
Bài toán của mình đặt ra để kiểm tra hoạt động này của DMA và MPU. Bài toán sử dụng MPU với 2 Region config như sau:
Region | Start Address | End Address | Access Right |
---|---|---|---|
0 | 0x0000.0000 | 0xFFFF.FFFF | Full Access |
1 | 0x2000.7000 | 0x2000.FFFF | Read Only |
Vùng RAM (Region 1) sẽ dùng để test hoạt động của DMA.
- Sử dụng DMA transfer từ một vùng RAM khác (địa chỉ 0x2001.6000, data = 0x5A5A.5A5A) sang địa chỉ thuộc Region 1 (địa chỉ 0x2000.7F00).
👉 Kết quả mong muốn: Transfer thành công do DMA không bị ảnh hưởng bởi MPU. - Sử dụng Core ghi trực tiếp data vào địa chỉ thuộc Region 1 (địa chỉ 0x2000.7F00).
👉 Kết quả mong muốn: Chương trình nhảy vào Fault (MemManage) do Core bị MPU hạn chế quyền write vào Region 1.
💬 Source Code
#define SRCADDR 0x20016000UL
#define DESTADDR 0x20007F00UL
int main(void)
{
/* Initialize DMA and MPU */
DMA_Init();
MPU_Init(&MPU_Config_0);
/* Write to Source Data - SRAM */
*(uint32 *)(SRCADDR) = 0xA5A5A5A5;
/* Set protect for Region 1 by MPU */
MPU_SetAccessRight(1,MPU_PRIV_R_UNPRIV_R);
/**************************************************
* Try to use DMA Transfer - Successful
* Because MPU can not protect transaction by DMA
* */
DMA_Config(SRCADDR, DESTADDR, 4);
Start_Transfer();
/**************************************************
* Perform a write in T_REGION - Fail
* Because MPU protect transaction by Core
* */
*(uint32_t *)DESTADDR = 0x12345678;
💬 Kết quả
Khi transfer bằng DMA - Data transfer thành công.
Khi ghi trực tiếp bằng Core (câu lệnh ở line 56) - Giá trị ô nhớ không thay đổi, và chương trình nhảy vào fault.
👉 Kết luận
MPU là một công cụ tốt để protect memory khỏi các truy cập của Core, tuy nhiên với các Non-Core Master thì MPU không chắc có tác dụng hạn chế quyền truy cập (Cần kiểm chứng thêm với các Non-Core Master khác ngoài DMA - Ví dụ Debugger). Đối với DMA đã được kiểm chứng hoạt động, nó không bị hạn chế bởi các Attribute (Access Right) của MPU. Vì vậy, để bảo vệ memory khỏi các Non-Core Master như DMA, chúng ta cần các cơ chế khác.
>>>= Follow ngay =<<<