Мы продолжаем видеть этот вопрос в разных формах, и люди продолжают говорить, что есть два стека. Поэтому я попробовал это сам с помощью systick.
В документации сказано, что мы находимся в режиме потока из сброса, и если вы остановить с OpenOCD он говорит, что
target halted due to debug-request, current mode: Thread
У меня есть некоторый код, чтобы вывести регистры:
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
I установки и дождитесь прерывания 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_process он использует sp_main , Он толкает элементы, о которых говорится в руководстве, в том числе о прерванном/обратном адресе, который равен 0x1000074.
Теперь, если я устанавливаю бит SPSEL (прежде всего, сначала установите PSP), кажется, что mov r0, sp в режиме приложения/потока использует PSP, а не MSP. Но тогда обработчик использует ПМП для мов r0, зр, но, как представляется, поставить
ранее в потоке/переднего плана
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 mrs rX, psp; mrs rX, msp; Для указателей процесса и основного стека.
Был ли прерванный код запущен с основным стеком? Если он работает с стеком процессов, то вы разматываете неправильный (поскольку режим Handler всегда использует MSP). В соответствии с документами, которые вы связали, соответствующий стек закодирован в значение EXC_RETURN. – Notlikethat
Да, я заметил, теперь у меня есть код в SysTick_Handler, который фактически считывает правильный ПК с того места, где я был в последний раз.Тем не менее, это плохо, что GDB не работает правильно. – Kristoffer
Вы можете написать макросы 'gdb' для этого. MSP является специфичным для кортикации, и GDB написан для работы на разных платформах и в основном касается пользовательских приложений. Тем не менее, это открытый исходный код, и я уверен, что взносы приветствуются. –