#gdb #microcontroller #cortex-m #cortex-m3 #thumb
#gdb #микроконтроллер #cortex-m #cortex-m3 #большой палец
Вопрос:
Я изучаю Cortex-M с помощью IDE MDK uVision. Я написал простой SysTick_Handler()
способ заменить СЛАБОЕ значение по умолчанию SysTick_Handler()
, которое представляет собой простой мертвый цикл.
Мой SysTick_Handler()
:
Разборка:
Меня смущает выделенная строка сборки. Это просто мертвый цикл.
Почему он там? Почему набор инструментов все еще генерирует его, несмотря на то, что я уже перезаписал СЛАБУЮ реализацию по умолчанию своей собственной SysTick_Handler
?
Я все еще могу установить точку останова в этой строке, и ее можно нажать. И в этом случае мой код никогда не будет выполнен.
Но странно то, что если я удалю точку останова в этой строке, тогда можно будет получить доступ к моему коду. Как это возможно?
Комментарии:
1. Похоже, что разборка не соответствует вашей функции должным образом, т. Е. Отключена на несколько байтов. Это также повлияло бы на точку останова. Мертвый цикл часто используется в качестве обработчика прерываний по умолчанию для немаскируемых прерываний. Таким образом, следует ожидать, что такой код будет найден где-то в вашем двоичном файле.
2. Я согласен с @Codo. Вполне возможно, что отладчик каким-то образом перепутал СЛАБУЮ ссылку и принял неправильный адрес.
3. Да, я сохранил реализацию по умолчанию, которая является мертвым циклом. Это действительно вводит в заблуждение, если отладчик может быть сбит с толку таким образом…
4. дизассемблеры изо всех сил пытаются просто разобрать машинный код, при оптимизации кода нет причин когда-либо предполагать, что высокий уровень и низкий уровень совпадают, а тем более полагаться на это. Отключите отображение языка высокого уровня, и вы будете золотыми, хорошо с такой архитектурой, которая имеет половину шансов на дизассемблирование машинного кода… Если вы хотите точно установить точку останова, не используйте отладчик с графическим интерфейсом, разберитесь сами и используйте что-то вроде openocd с интерфейсом telnet.
5. Это похоже на другой обработчик, который представляет собой бесконечный цикл, nop там, чтобы выровнять его по границе слова.
Ответ №1:
(Спасибо всем подсказкам, предоставленным сообществом. Думаю, теперь я могу это объяснить.)
Мертвый цикл является частью моей main()
функции, которая похожа на приведенную ниже. main()
Функция находится чуть выше моей SysTick_Handler
в том же файле C.
int main (void)
{
LED_Initialize();
SysTick->VAL = 0x9000;
//Start value for the sys Tick counter
SysTick->LOAD = 0x9000;
//Reload value
SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE; //Start and enable interrupt
while(1)
{
; // <========= This is the dead loop I saw!
}
}
Для двойного подтверждения я изменил цикл while на следующий:
int main (void)
{
volatile int32_t jj = 0;
LED_Initialize();
SysTick->VAL = 0x9000; //Start value for the sys Tick counter
SysTick->LOAD = 0x9000; //Reload value
SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE; //Start and enable interrupt
while(1)
{
;
jj =0x12345; // <====== add some landmark value
}
}
Сгенерированный код теперь выглядит так:
Хотя он по-прежнему находится под SysTick_Handler
. Я помещаю туда точку останова, чтобы проверить, что происходит на самом деле:
Это R1
константа 0x12345
. Это R0
локальная переменная jj
. Мы видим R1
, что содержит значение ориентира 0x12345
, которое добавляется в R0
( jj
) . Так что это должно быть частью моего while(1)
цикла в main()
.
Итак, дизассемблирование выполнено правильно. Только то, что отладчику не удалось обеспечить правильное чередование между исходным кодом и дизассемблированием.
И, кстати, не забудьте перестроить цель после изменения кода, иначе отладчик uVision IDE не будет отражать последние изменения….