- PVSM.RU - https://www.pvsm.ru -
В данной статье я расскажу вам как можно использовать регистры отладки и breakpoint'ов в микроконтроллерах, построенных на ядрах ARM Cortex-M
Знали ли вы что ядра ARM Cortex-M в микроконтроллерах могут отлаживать сами себя?
Оказывается могут.
Читая Technical Reference Manual [1] на ядро Cortex M3 обнаружил что у него есть прерывание DebugMon. Далее проанализировал все регистры с ним связанные. В итоге выяснил что МК может попадать в это прерывание при условии равенства регистра PC и одного из регистров FP_COMP.
Это означает что мы можем устанавливать точки останова в отлаживаемой прошивке. Так-же можно принудительно вызывать прерывание DebugMon установив бит MON_PEND регистра DEMCR в 1.
Так как данные регистры присутствуют во всём семействе ядер ARM Cortex-M, возьмем первую попавшуюся отладочную плату. У меня это оказалось stm32f723e-disco. Для того чтобы не тратить время на написание инициализационного кода периферии, используем CubeMX
Из периферии нам понадобится лишь UART6, соединенный с ST-Link'ом и светодиод на плате:
Генерируем проект и сразу открываем его IDE.
Для того чтобы не запутаться в регистрах связанных с отладкой, сразу введем для них определения в коде:
#define DHCSR (*(uint32_t*)0xE000EDF0)
#define DCRSR (*(uint32_t*)0xE000EDF4)
#define DCRDR (*(uint32_t*)0xE000EDF8)
#define DEMCR (*(uint32_t*)0xE000EDFC)
#define NUMOFBKPTS 8
typedef struct {
uint32_t FP_CTRL;
uint32_t FP_REMAP;
uint32_t FP_COMP[NUMOFBKPTS];
} fp_t;
#define FP ((fp_t*)0xE0002000)
Для проверки что наш проект в принципе работает, пишем код, мигающий светодиодом:
while (1)
{
for (int i=0;i<1000000;i++)
asm("nop");
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_7);
}
Светодиод успешно заморгал, значит проект успешно компилируется и запускается.
Добавляем в этот цикл строчку:
asm("BKPT #0");
Эта ассемблерная вставка является программной точкой останова. Теперь при отладке через ST-Link программа всегда будет останавливаться на этой строчке. Выходим из Debug в IDE и светодиод начинает моргать как и раньше.
Но что нам это дало?
А то что мы можем отлавливать точку останова прерыванием DebugMon.
Пишем его обработчик:
void DebugMon_Handler(void)
{
while (1)
{
if ((USART6->ISR & USART_ISR_TXE) != 0U)
{
USART6->TDR = '!';
}
}
}
Компилируем, прошиваем и ничего не изменилось. Чтобы разрешить работу прерывания DebugMon, нужно поднять бит MON_EN в регистре DEMCR.
Теперь при отладке через ST-Link программа будет останавливаться как и раньше на этой строчке. Как только мы выйдем из режима отладки, в терминале начнут появляться восклицательные знаки:
Далее проверяем тоже самое с регистром FP_COMP.
Находим адрес любой инструкции в цикле функции main средствами IDE и активируем точку останова:
FP->FP_COMP[0] = 0x080017CC | 1; // адрес середины бесконечного цикла = 0x080017CC
При отключенном аппаратном отладчике, микроконтроллер тоже попадает в прерывание DebugMon.
С помощью вышеприведенных регистров и прерывания DebugMon возможно реализовать отладку микроконтроллера без SWD/JTAG отладчика. Так-же становится возможным отлаживать прошивку устройства, с которым есть связь, но доступ к выводам SWD затруднен.
Продолжение следует…
Автор: Дмитрий
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/stm32/346916
Ссылки в тексте:
[1] Technical Reference Manual: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf
[2] Источник: https://habr.com/ru/post/488672/?utm_source=habrahabr&utm_medium=rss&utm_campaign=488672
Нажмите здесь для печати.