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