Показаны различия между двумя версиями страницы.
ob:o7:debug [2018/05/26 07:00] иван_денисов [Сторожевой таймер] |
ob:o7:debug [2018/11/30 01:13] |
||
---|---|---|---|
Строка 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 (см. информацию при сборке), | ||
- | |||
- | Чтобы перейти к положению ошибки в модуле, | ||
- | |||
- | |||
- | ===== Сторожевой таймер ===== | ||
- | |||
- | Чтобы определить, | ||
- | |||
- | Чтобы его использовать, | ||
- | |||
- | Более универсальный сторожевой таймер для любых типов микроконтроллеров STM32F* не имеет возможности определения места остановки: | ||
- | |||
- | |||
- | ---- | ||
- | |||
- | Авторы заметки: | ||