PMP導(dǎo)致異常問題分析
現(xiàn)象和確認異常原因
觸發(fā)了異常中斷
查看異常原因為7 store access-fault exception.
并查看異常訪問的地址為0x28382ad0
gdb也確認這個地址確實只能讀不能寫
查看PMP寄存器確認根本原因
Pmpcfg0 對應(yīng)地址pmp0cfg~pmp3cfg
Pmpcfg1 對應(yīng)地址pmp4cfg~pmp7cfg
Pmpcfg2 對應(yīng)地址pmp8cfg~pmp11cfg
Pmpcfg3 對應(yīng)地址pmp12cfg~pmp15cfg
pmpcfg3為0x5100即對應(yīng)pmp13cfg為0x51
8位的配置屬性0x51如下 只讀
A=10 即NA4表示4字節(jié)區(qū)域,即pmpaddrxx對應(yīng)的4字節(jié)區(qū)域
L=1
A=10=2 NA4
R=1
X=0
W=0
對應(yīng)pmp13cfg的pmpaddr13=0xa0e0ab4 是34位地址右移2位的值,所以左移兩位恢復(fù)實際值是0x2C38 2AD0
表示的范圍是[0x2C38 2AD0,0x2C38 2AD3] 4字節(jié)
我們的地址空間是0x28000000-0x2bffffff
寫0x2C38 2AD0實際映射到了寫0x2838 2AD0 64M繞回。
所以寫0x2838 2AD0這個不具備寫屬性的地址觸發(fā)了store access-fault
exception.異常
所以以上確認了原因是PMP設(shè)置了該地址不具備寫屬性,而代碼中去寫所以導(dǎo)致了異常。
代碼
我們的空間最多只有128M,最多到0x2bff ffff,為什么寫了個0x2C38 2AD0的地址進去,
先找到對應(yīng)的代碼
由于是用的所以13的配置,所以先找這個索引對應(yīng)
#define PMP_FIXED_INDEX_TASK_STACK 13
然后再搜索這個索引
找到如下函數(shù)
這個函數(shù)在vTaskSwitchContext調(diào)用
if (prev != pxCurrentTCB) {
pmp_task_stack_set((uint32_t)pxCurrentTCB- >pxStack);
}
即任務(wù)有切換時,設(shè)置棧底4字節(jié)不可寫,用于棧溢出檢測。
加個死循環(huán)用于在設(shè)置該值時停住
所以要確認什么時候?qū)懥?x2838 2AD0這個地址,由于使能了PMP,所以watchpoint抓不到,先觸發(fā)了pmp的異常。
所以先關(guān)閉pmp設(shè)置
if (prev != pxCurrentTCB) {
///pmp_task_stack_set((uint32_t)pxCurrentTCB- >pxStack);
}
然后設(shè)置數(shù)據(jù)斷點
watch (unsigned int )0x28382ad0
運行
第一次停在棧初始化,第二次停在如下處
可以看到
任務(wù)棧的地址是 0x28382ad0開始但是 臨時變量mem的地址是0x28382a60在棧前面去了,所以棧溢出了。
把棧改大即可
審核編輯:湯梓紅
-
嵌入式
+關(guān)注
關(guān)注
5082文章
19123瀏覽量
305151 -
調(diào)試
+關(guān)注
關(guān)注
7文章
578瀏覽量
33936 -
PMP
+關(guān)注
關(guān)注
0文章
45瀏覽量
18165 -
RISC-V
+關(guān)注
關(guān)注
45文章
2277瀏覽量
46158
發(fā)布評論請先 登錄
相關(guān)推薦
評論