2016-08-02 45 views
-1

我想在代碼中找到發生特定中斷的位置。在這種情況下,它位於stm32f4微控制器上,中斷是SysTick_Handler。找到哪裏中斷髮生在cortex-m4上

我想要的基本上是從哪裏發現systick中斷。我使用的臂無 - EABI-gdb來試圖找到回溯,但我從那裏得到的唯一信息是:

(gdb) bt 
#0 SysTick_Handler() at modules/profiling.c:66 
#1 <signal handler called> 
#2 0x55555554 in ??() Backtrace stopped: previous frame identical to this frame (corrupt stack?) 

我怎樣才能得到關於該程序是中斷髮射之前的一些信息?

看看arm文檔here,看來我應該能夠讀取堆棧指針,並從那裏獲取PC。但是,這正是GDB的開拓者正在做的不是嗎?

+0

與主棧運行中斷的代碼?如果它與進程堆棧一起運行,那麼你解開了錯​​誤的一個(因爲處理程序模式總是使用MSP)。根據鏈接的文檔,相關的堆棧以EXC_RETURN值編碼。 – Notlikethat

+0

是的,我注意到了,我現在已經在我的SysTick_Handler代碼實際上讀出從那裏我最後一次正確的PC。儘管如此,GDB並沒有正確的放鬆。 – Kristoffer

+0

你可以編寫'gdb'宏來做到這一點。 MSP特定於cortex-m,GDB被編寫爲可在多種不同平臺上運行,主要關注用戶應用程序。這就是說,它是開源的,我相信我們的貢獻是值得歡迎的。 –

回答

0

正如許多人評論說,該PC將是兩個不同的堆棧,我解決它是由真正找到在組件中的HardFault_Handling代碼,並採取從那裏我需要什麼樣的方式。要正確獲取PC值,我使用下面的代碼。

register int *r0 __asm("r0"); 

__asm( "TST lr, #4\n" 
     "ITE EQ\n" 
     "MRSEQ r0, MSP\n" 
     "MRSNE r0, PSP\n" // stack pointer now in r0 
     "ldr r0, [r0, #0x18]\n" // stored pc now in r0 
     //"add r0, r0, #6\n" // address to stored pc now in r0 
    ); 

的地方中斷happended現在可以通過

uint32_t PC = *r0; 

訪問,並且現在可以用於任何我想要它的價值。不幸的是我沒有設法讓GDB爲我自動解除堆棧。但至少我發現中斷髮生在哪裏,這是目標。

-2

這叫做DEBUGGING。最簡單的入門方法是在整個代碼中粘貼一堆printf()調用。運行該程序。如果它打印出:

得A點
得B點
得C點

裏死了,那麼你就知道它的「C」和「D」之間死亡現在,您可以通過使用更緊密間距的printf()調用將「C」和「D」之間的代碼進行花飾來細化。

這是初學者入門的最佳方式。許多經驗豐富的專家也喜歡使用printf()進行調試。調試器可以阻擋。

+4

這並沒有幫助我,因爲我的程序沒有崩潰, 我沒有printf,我特別想知道從 – Kristoffer

1

您在問題結束時處於正確的軌道上。 ARM Cortex-M內核有兩個堆棧指針,主堆棧指針(MSP,用於中斷)和進程堆棧指針(用於任務的PSP)。

當具有優先級的中斷進入時,當前寄存器值(用於大多數寄存器)被壓入當前堆棧(如果中斷後臺應用程序則爲PSP,或者如果中斷較低優先級中斷則爲MSP),然後堆棧被切換到MSP(如果尚未存在)。

當您第一次輸入中斷時,鏈接寄存器(LR,返回地址)將具有大多數爲F的值,而不是實際的返回地址。該值告訴核心如何在分支時退出。通常情況下,如果後臺任務中斷,您將看到值0xFFFFFFFD,如果較低優先級的中斷被中斷,則會看到0xFFFFFFF1。如果您使用浮點單位,這些值將有所不同。然而,這個值的神奇之處在於,位2(0x4)告訴你,你的堆棧幀是在PSP還是MSP上。

一旦您確定了您的框架所在的堆棧,您可以通過查看適當的堆棧指針減去24(6個32位位置)來找到您正在執行的地址。在你的鏈接中見圖2.3。這會將您指向您被中斷的PC。

1

我們一直在以各種形式看到這個問題,人們總是說有兩個堆棧。所以我用systick自己試了一下。

文檔說,我們是在線程模式復位的,如果你停止與OpenOCD的它說,

​​

我有一些代碼來轉儲寄存器:

20000000 APSR 
00000000 IPSR 
00000000 EPSR 
00000000 CONTROL 
00000000 SP_PROCESS 
20000D00 SP_PROCESS after I modified it 
20000FF0 SP_MAIN 
20000FF0 mov r0,sp 
then I dump the stack up to 0x20001000 which is where I know my stack started 
20000FF0 00000000 
20000FF4 00000000 
20000FF8 00000000 
20000FFC 0100005F 

我的設置並等待systick中斷,處理程序轉儲寄存器和RAM,然後進入無限循環。一般的不好的做法,只是在這裏調試/學習。在中斷前我預習一些寄存器:

.thumb_func 
.globl iwait 
iwait: 
    mov r0,#1 
    mov r1,#2 
    mov r2,#3 
    mov r3,#4 
    mov r4,#13 
    mov r12,r4 
    mov r4,#15 
    mov r14,r4 
    b . 

,並在處理程序中我看到

20000000 APSR 
0000000F IPSR 
00000000 EPSR 
00000000 CONTROL 
20000D00 SP_PROCESS 
20000FC0 SP_MAIN 
20000FC0 mov r0,sp 
20000FC0 0000000F 
20000FC4 20000FFF 
20000FC8 00000000 
20000FCC FFFFFFF9 this is our special lr (not one rjp mentioned) 
20000FD0 00000001 this is r0 
20000FD4 00000002 this is r1 
20000FD8 00000003 this is r2 
20000FDC 00000004 this is r3 
20000FE0 0000000D this is r12 
20000FE4 0000000F this is r14/lr 
20000FE8 01000074 and this is where we were interrupted from 
20000FEC 21000000 this is probably the xpsr mentioned 
20000FF0 00000000 stuff that was there before 
20000FF4 00000000 
20000FF8 00000000 
20000FFC 0100005F 


01000064 <iwait>: 
1000064: 2001  movs r0, #1 
1000066: 2102  movs r1, #2 
1000068: 2203  movs r2, #3 
100006a: 2304  movs r3, #4 
100006c: 240d  movs r4, #13 
100006e: 46a4  mov ip, r4 
1000070: 240f  movs r4, #15 
1000072: 46a6  mov lr, r4 
1000074: e7fe  b.n 1000074 <iwait+0x10> 
1000076: bf00  nop 

因此,在這種情況下,徑直出了ARM的文檔,所以不能用它使用sp_main的sp_process 。它正在推送手動表示它正在推送的項目,包括0x1000074被中斷/返回的地址。現在

,如果我設置SPSEL位(注意首先設置PSP),似乎一個MOV R0,SP在應用程序/線程模式使用PSP沒有MSP。但隨後的處理程序現在使用MSP爲MOV R0,SP,但似乎把

前線程/前景

20000000 APSR 
00000000 IPSR 
00000000 EPSR 
00000000 SP_PROCESS 
20000D00 SP_PROCESS modified 
00000000 CONTROL 
00000002 CONTROL modified 
20000FF0 SP_MAIN 
20000D00 mov r0,sp 

在處理

20000000 APSR 
0000000F IPSR 
00000000 EPSR 
00000000 CONTROL (interesting!) 
20000CE0 SP_PROCESS 
20000FE0 SP_MAIN 
20000FE0 mov r0,sp 
dump of that stack 
20000FE0 0000000F 
20000FE4 20000CFF 
20000FE8 00000000 
20000FEC FFFFFFFD 
20000FF0 00000000 
20000FF4 00000000 
20000FF8 00000000 
20000FFC 0100005F 
dump of sp_process stack 
20000CE0 00000001 
20000CE4 00000002 
20000CE8 00000003 
20000CEC 00000004 
20000CF0 0000000D 
20000CF4 0000000F 
20000CF8 01000074 our return value 
20000CFC 21000000 

所以要在這個位置處理人們不斷提及的替代堆棧,你必須把自己置於這個位置(或者你依賴的某些代碼)。爲什麼你想爲簡單的裸機程序這麼做,誰知道,所有零的控制寄存器都很好,很容易,可以共享一個堆棧就好了。

我不使用gdb,但你需要讓它轉儲所有的寄存器sp_process和sp_main,然後根據你找到的,然後在每個轉儲一打左右的單詞,在那裏你應該看到0xFFFFFFFx作爲標記然後倒數,看到返回地址。您可以讓您的處理程序讀取兩個堆棧指針,然後您可以查看gprs。用gnu彙編語言rX,psp; mrs rX,msp;對於進程和主棧指針。

+0

發生中斷的位置,注意這是一個ti msp432啓動板中的cortex-m4。我有其他人,但這足以證明你不一定要處理雙棧問題,尤其是如果你沒有設置備用堆棧。 –