После запуска отладки мы обычно останавливаемся в начале функции main(), после чего уже начинаем отлаживать нашу программу. Однако перед тем, как остановиться в main(), среда разработки выполняет различные действия и настройки, которые не видны пользователю. Здесь мы рассмотрим подробный запуск отладки в среде Keil и IAR.
Подробный процесс запуска режима отладки описан на сайте Keil, пункт "Sequence of Execution, и состоит из следующих действий:
1) Сброс МК в соответствии с настройками отладчика и остановка ядра, при этом выполнение начального загрузчика останавливается.
2) Если установлен пункт Options for Target→Debug "Load application at Startup", то происходит загрузка скомпилированной программы по адресам IROM, указанным в настройках проекта.
3) Восстановление параметров режима отладки.
4) Выполнение команд в файле инициализации (*.ini).
5) Запуск выполнения программы с адреса, указанного в регистре счётчика команд PC.
Таким образом, если в файле инициализации значение PC не изменяется, то МК продолжит выполнение начального загрузчика, и в соответствии с режимом загрузки, выполнит дальнейший запуск, например, перейдёт к выполнению программы во Flash памяти. Тогда, как только программа достигнет выполнения первой инструкции из функции main(), отладчик остановит ядро (если задана опция «Run to main()»).
Подробный процесс запуска отладки описан в хэлпе среды: IAR→Help→C-SPY Debugging Guide, "DEBUGGING CODE IN FLASH", стр. 60. Ниже приведён процесс запуска отладки программы, записанной во Flash память:
Согласно данному документу, после запуска режима отладки среда IAR, также как и Keil, сбрасывает МК (при соответствующих настройках отладчика) и останавливает ядро. После это с помощью загрузчика происходит запись программы во Flash память и установка счётчика команд PC равным адресу ResetHandler’a, который считывается из загружаемого образа программы. Далее происходит верификация данных, и соответственно сам запуск, путём старта с адреса, указанного в PC.
Здесь необходимо отметить важную особенность отладки в IAR: так как среда останавливает ядро сразу после сброса, то начальный загрузчик МК (bootloader) не успевает выполниться, далее, после загрузки программы во Flash память, среда не возвращается к выполнению кода начального загрузчика, а сразу выставляет адрес ResetHandler’a, и стартует с него. Таким образом, штатный процесс запуска МК нарушается, т.к. работа начального загрузчика пропускается.
Здесь кроется одно обстоятельство – после сброса значение в регистре смещения таблицы векторов прерывания VTOR = 0x00000000. Flash-память во многих МК, например, 1986ВЕ9x, начинается не с 0-го адреса, поэтому начальный загрузчик устанавливает при запуске верное значение VTOR. Но так как при отладке в IAR выполнение начального загрузчика пропускается, то VTOR остаётся равен 0x00000000. Это приводит к тому, что вызов прерывания в режиме отладки, осуществит переход на неверный вектор, так как процессор считает, что таблица расположена в 0x00000000, а не во Flash памяти.
Обойти данное обстоятельство можно несколькими способами:
1) В основной программе необходимо установить верное значение таблицы векторов прерываний в VTOR. Так, например, сделано в SPL, где значение VTOR устанавливается в функции SystemInit() при запуске программы.
2) Описать реализацию специальных функций IAR, которые вызываются в процессе запуска отладки. Так, например, при запуске отладки программы, записанной во Flash память (рисунок выше), в разные моменты времени вызываются функции: execUserFlashInit(), execUserFlashReset(), execUserSetup() и т.д. Данные функции описываются в макро-файле (*.mac). Для установки значения VTOR можно реализовать функцию execUserSetup(), которая вызывается в конце процесса запуска отладки:
execUserSetup() { __writeMemory32(0x08000000, 0xE000ED08, "Memory"); }
Полный список специальных функций IAR описан в хэлпе среды: IAR→Help→C-SPY Debugging Guide, "Reference information on reserved setup macro function names", стр. 425.
3) В настройках отладчика, например, J-Link, можно выставить опцию сброса «Halt after bootloader»:
Таким образом, после сброса МК остановка ядра будет произведена не сразу, а после выполнения начального загрузчика, который в свою очередь выставит верное значение VTOR.