Показаны различия между двумя версиями страницы.
ob:o7:debug [2018/11/30 01:13] |
ob:o7:debug [2020/10/29 07:08] (текущий) |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Отладка программ на языке Оберон-07 ====== | ||
+ | |||
+ | Отладка программ на Обероне при использовании компилятора [[ob: | ||
+ | |||
+ | Так во время разработки и отладки программы удобным является следующий прием: | ||
+ | |||
+ | < | ||
+ | IMPORT Traps := MicroARMv7MTraps; | ||
+ | |||
+ | PROCEDURE Init; | ||
+ | BEGIN | ||
+ | ... | ||
+ | IF Traps.trapFlag THEN Traps.ClearTrapFlag; | ||
+ | ... | ||
+ | END Init; | ||
+ | |||
+ | BEGIN | ||
+ | Init; | ||
+ | MainLoop | ||
+ | END MyProgram.</ | ||
+ | |||
+ | |||
+ | Аварийные остановки происходят по ряду причин. | ||
+ | |||
+ | Программные причины (Oberon): | ||
+ | * Код 1: index check | ||
+ | * Код 2: type cast | ||
+ | * Код 3: array size | ||
+ | * Код 4: nil check | ||
+ | * Код 5: nil check (procedure call) | ||
+ | * Код 6: bad divisor (must be > 0) | ||
+ | * Код 7: assert | ||
+ | |||
+ | Аппаратные причины (ARMv{6, | ||
+ | * Код 10: hard fault | ||
+ | * Код 11: memory manage | ||
+ | * Код 12: bus fault | ||
+ | * Код 13: usage fault | ||
+ | |||
+ | Аварийные остановки сообщают program counter **pc** и положение в исходном тексте модуля **pos**, поэтому, | ||
+ | - Используя значение **pc** узнать модуль, | ||
+ | - По номеру положения **pos** (номер символа) найти место в исходном тексте модуля (**O7-> | ||
+ | |||
+ | Для микроконтроллеров NXP достаточно **pc** поделить на 2 (т. к. команды Thumb 2-байтные). Потом сравнить полученное число со списком вывода команды O7ARMv{6, | ||
+ | |||
+ | Для микроконтроллеров STM32 надо предварительно из **pc** вычесть 8000000H, так как программа в ROM начинается с этого положения. | ||
+ | |||
+ | |||
+ | ===== ASSERT ===== | ||
+ | |||
+ | ASSERT в готовых модулях служит для проверки предусловия или постусловия в рамках контрактного программирования. | ||
+ | |||
+ | SYSTEM.GET(SYSTEM.REG(SP), | ||
+ | ASSERT(stkPos > MicroKernel0.heapLim); | ||
+ | |||
+ | Этот код проверит, | ||
+ | |||
+ | Чтобы узнать больше про особенности работы с памятью читайте [[ob: | ||
+ | |||
+ | |||
+ | ===== Пример отладчика ===== | ||
+ | |||
+ | Чтобы осуществлять отладку микроконтроллера необходимо обмениваться сообщениями. Более подробно организация обмена описана в заметке [[ob: | ||
+ | |||
+ | < | ||
+ | |||
+ | IMPORT SYSTEM, ARMv7M := MicroARMv7M, | ||
+ | Traps := MicroARMv7MTraps, | ||
+ | Sys := MicroSTM32F103x8System, | ||
+ | Pins := MicroSTM32F10xPinCfg, | ||
+ | TPs := MicroSTM32F1TPorts; | ||
+ | |||
+ | CONST | ||
+ | idInit = 0CBX; idTrap = 0DEX; | ||
+ | |||
+ | VAR | ||
+ | p0: TPs.Port; | ||
+ | |||
+ | PROCEDURE Receive (id: CHAR; a: ARRAY OF CHAR; len: INTEGER); | ||
+ | BEGIN | ||
+ | ASSERT(FALSE) | ||
+ | END Receive; | ||
+ | |||
+ | PROCEDURE MainLoop; | ||
+ | BEGIN | ||
+ | REPEAT | ||
+ | TPs.Receive(p0); | ||
+ | ARMv7M.WFI | ||
+ | UNTIL FALSE | ||
+ | END MainLoop; | ||
+ | |||
+ | PROCEDURE Init; | ||
+ | VAR ok: BOOLEAN; par: TPs.InitPar; | ||
+ | BEGIN | ||
+ | par.n := TPs.USART1; | ||
+ | par.RXPinPort := Pins.A; par.RXPinN := 10; | ||
+ | par.TXPinPort := Pins.A; par.TXPinN := 9; | ||
+ | par.UCLK := Sys.PCLK2; | ||
+ | par.baud := 19200; | ||
+ | par.parity := TPs.parityNone; | ||
+ | par.receive := Receive; | ||
+ | par.version2 := 2; | ||
+ | TPs.Init(p0, | ||
+ | |||
+ | TPs.Send(p0, | ||
+ | IF Traps.trapFlag THEN | ||
+ | Traps.ClearTrapFlag; | ||
+ | TPs.Send(p0, | ||
+ | END | ||
+ | END Init; | ||
+ | |||
+ | BEGIN | ||
+ | Init; | ||
+ | MainLoop | ||
+ | END MobxAssert.</ | ||
+ | |||
+ | Собирать командой: | ||
+ | < | ||
+ | |||
+ | В журнал будет выведена информация о модулях. | ||
+ | < | ||
+ | MicroARMv7M 256 | ||
+ | MicroKernel0 301 | ||
+ | MicroARMv7MTraps 987 | ||
+ | MicroSTM32F10xxD 1283 | ||
+ | MicroSTM32F103x8System 1286 | ||
+ | MicroSTM32F10xPinCfg 1535 | ||
+ | MicroSTM32F1TPorts 1662 | ||
+ | MobxAssert 3146 | ||
+ | ROM: 6816 B; RAM: 748 B | ||
+ | </ | ||
+ | |||
+ | |||
+ | Программа для Блэкбокса, | ||
+ | |||
+ | < | ||
+ | IMPORT SYSTEM, TP := MicroTPorts, | ||
+ | |||
+ | TYPE | ||
+ | MessagesHandler = POINTER TO RECORD (TP.MessagesHandler) END; | ||
+ | |||
+ | CONST | ||
+ | id = 20X; | ||
+ | idTrap = 0DEX; | ||
+ | |||
+ | VAR | ||
+ | p: TP.Port; | ||
+ | mh: MessagesHandler; | ||
+ | |||
+ | PROCEDURE Send*(t: INTEGER); | ||
+ | VAR a: ARRAY 4 OF SHORTCHAR; | ||
+ | BEGIN | ||
+ | SYSTEM.PUT(SYSTEM.ADR(a), | ||
+ | TP.SendMessage(p, | ||
+ | END Send; | ||
+ | |||
+ | PROCEDURE (h: MessagesHandler) MessageReceived (id: SHORTCHAR; IN a: ARRAY OF SHORTCHAR; len: INTEGER); | ||
+ | VAR pc, pos, code: INTEGER; | ||
+ | BEGIN | ||
+ | IF id = idTrap THEN | ||
+ | SYSTEM.GET(SYSTEM.ADR (a), pc); | ||
+ | SYSTEM.GET(SYSTEM.ADR (a)+4, pos); | ||
+ | code := ORD(a[8]); | ||
+ | IF pc >= 8000000H THEN pc := pc - 8000000H END; | ||
+ | Log.String(" | ||
+ | Log.String(" | ||
+ | Log.String(" | ||
+ | END | ||
+ | END MessageReceived; | ||
+ | |||
+ | PROCEDURE Open*(port: ARRAY OF CHAR); | ||
+ | BEGIN | ||
+ | IF p = NIL THEN | ||
+ | p := TP.NewPort(port, | ||
+ | Log.Bool(p # NIL); Log.Ln; | ||
+ | END | ||
+ | END Open; | ||
+ | |||
+ | PROCEDURE Close*; | ||
+ | BEGIN | ||
+ | TP.Close(p) | ||
+ | END Close; | ||
+ | |||
+ | BEGIN | ||
+ | NEW(mh) | ||
+ | CLOSE | ||
+ | Close | ||
+ | END MobxDebug.</ | ||
+ | |||
+ | В Windows запускается командой: | ||
+ | < | ||
+ | |||
+ | Для Linux будет следующая команда: | ||
+ | < | ||
+ | |||
+ | Любая отправка МК команды, | ||
+ | < | ||
+ | |||
+ | В журнал Блэкбокса будет выведена информация: | ||
+ | < | ||
+ | pos: 337 | ||
+ | code: 7</ | ||
+ | |||
+ | Program Counter (pc) равен 3155, что больше 3146 (см. информацию при сборке), | ||
+ | |||
+ | Чтобы перейти к положению ошибки в модуле, | ||
+ | |||
+ | |||
+ | ===== Сторожевой таймер ===== | ||
+ | |||
+ | Чтобы определить, | ||
+ | |||
+ | Чтобы его использовать, | ||
+ | |||
+ | Более универсальный сторожевой таймер не имеет возможности определения места остановки: | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | Авторы заметки: | ||