Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
ob:o7:memory [2018/11/30 01:13] 127.0.0.1 внешнее изменение |
ob:o7:memory [2020/10/29 07:08] (текущий) |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ====== | + | ====== |
| При выполнении команды **O7ARMv{6, | При выполнении команды **O7ARMv{6, | ||
| Строка 9: | Строка 9: | ||
| * таблица указателей, | * таблица указателей, | ||
| - | Куча используется только при динамическом выделении памяти через команду NEW, и она заполняется снизу вверх. Для сборки мусора в куче надо вызывать команду **MicroGC0.Collect**. Количество выделенной динамической памяти доступно в переменной **MicroKernel0.allocated**, | + | Куча используется только при динамическом выделении памяти через команду |
| Стек заполняет выделенную под него память сверху вниз. И когда этот объем полностью заполняется, | Стек заполняет выделенную под него память сверху вниз. И когда этот объем полностью заполняется, | ||
| Строка 23: | Строка 23: | ||
| Так возможно контролировать при отладке, | Так возможно контролировать при отладке, | ||
| - | Переполнение стека возможно обнаружить и более простым путем, сравнив **stkPos** с **MicroKernel0.heapLim**. Если он меньше, | + | Переполнение стека возможно обнаружить и более простым путем, сравнив **stkPos** с **MicroKernel0.heapLim**. Если он меньше, |
| + | |||
| + | ===== Тестирование сборщика мусора ===== | ||
| + | |||
| + | Александр Ширяев разработал модуль для тестирования сборщика мусора: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | MODULE TmpTestGC0; | ||
| + | |||
| + | (* | ||
| + | Alexander Shiryaev, 2019.10 | ||
| + | |||
| + | Dynamic memory (and garbage collection) test | ||
| + | |||
| + | Board: Nucleo-F446RE | ||
| + | PA2: UART TX | ||
| + | PA3: UART RX | ||
| + | PA5: LED | ||
| + | *) | ||
| + | |||
| + | IMPORT | ||
| + | SYSTEM, | ||
| + | ARMv7M := MicroARMv7M, | ||
| + | Traps := MicroARMv7MTraps, | ||
| + | Kernel := MicroKernel0, | ||
| + | GC := MicroGC0, | ||
| + | TPorts := MicroSTM32F4TPorts, | ||
| + | Pins := MicroSTM32F4Pins, | ||
| + | Sys := MicroSTM32F405System, | ||
| + | SysTick0 := DplaARMv7MSTM32SysTick0, | ||
| + | WWDG := MicroARMv7MSTM32F4WWDG; | ||
| + | |||
| + | CONST | ||
| + | enableLED = TRUE; | ||
| + | |||
| + | led0PinPort = Pins.A; | ||
| + | led0PinN = 5; | ||
| + | led0BSRR = Pins.GPIOABSRR; | ||
| + | |||
| + | freq0 = 128; (* Hz *) | ||
| + | |||
| + | TYPE | ||
| + | Operation = POINTER TO OperationDesc; | ||
| + | OperationDesc = RECORD | ||
| + | END; | ||
| + | Repeat = POINTER TO RepeatDesc; | ||
| + | RepeatDesc = RECORD (OperationDesc) | ||
| + | value: INTEGER | ||
| + | END; | ||
| + | End = POINTER TO EndDesc; | ||
| + | EndDesc = RECORD (OperationDesc) | ||
| + | END; | ||
| + | |||
| + | VAR | ||
| + | cnt0: INTEGER; | ||
| + | operations: | ||
| + | nOp: INTEGER; | ||
| + | port: TPorts.Port; | ||
| + | |||
| + | PROCEDURE LEDOn; | ||
| + | BEGIN | ||
| + | SYSTEM.PUT(led0BSRR, | ||
| + | END LEDOn; | ||
| + | |||
| + | PROCEDURE LEDOff; | ||
| + | BEGIN | ||
| + | SYSTEM.PUT(led0BSRR, | ||
| + | END LEDOff; | ||
| + | |||
| + | PROCEDURE InitOperations; | ||
| + | VAR i: INTEGER; | ||
| + | BEGIN | ||
| + | i := 0; | ||
| + | WHILE i < LEN(operations) DO | ||
| + | operations[i] := NIL; | ||
| + | INC(i) | ||
| + | END; | ||
| + | GC.Collect; | ||
| + | nOp := 0 | ||
| + | END InitOperations; | ||
| + | |||
| + | PROCEDURE AddRepeat (val: INTEGER); | ||
| + | VAR repeat: Repeat; | ||
| + | BEGIN | ||
| + | repeat := NIL; | ||
| + | NEW(repeat); | ||
| + | repeat.value := val; | ||
| + | operations[nOp] := repeat; | ||
| + | INC(nOp) | ||
| + | END AddRepeat; | ||
| + | |||
| + | PROCEDURE AddEnd; | ||
| + | VAR end: Repeat; | ||
| + | BEGIN | ||
| + | end := NIL; | ||
| + | NEW(end); | ||
| + | INC(nOp) | ||
| + | END AddEnd; | ||
| + | |||
| + | PROCEDURE PopulateOperations; | ||
| + | VAR i: INTEGER; | ||
| + | BEGIN | ||
| + | i := 0; | ||
| + | WHILE i < 10 DO | ||
| + | AddRepeat(i); | ||
| + | INC(i) | ||
| + | END; | ||
| + | i := 0; | ||
| + | WHILE i < 5 DO | ||
| + | AddEnd; | ||
| + | INC(i) | ||
| + | END | ||
| + | END PopulateOperations; | ||
| + | |||
| + | PROCEDURE Receive (id: CHAR; a: ARRAY OF CHAR; len: INTEGER); | ||
| + | VAR ok: BOOLEAN; | ||
| + | i: INTEGER; | ||
| + | BEGIN | ||
| + | IF id = 20X (* communication test *) THEN | ||
| + | TPorts.Send(port, | ||
| + | ELSIF id = 22X (* clear dynamic memory *) THEN | ||
| + | IF len = 0 THEN | ||
| + | InitOperations; | ||
| + | TPorts.Send(port, | ||
| + | END | ||
| + | ELSIF id = 24X (* populate dynamic memory *) THEN | ||
| + | IF len = 0 THEN | ||
| + | PopulateOperations; | ||
| + | TPorts.Send(port, | ||
| + | END | ||
| + | ELSIF id = 26X (* Kernel.allocated query *) THEN | ||
| + | IF len = 0 THEN | ||
| + | TPorts.Send(port, | ||
| + | END | ||
| + | ELSIF id = 28X (* TRAP test *) THEN | ||
| + | IF len = 0 THEN | ||
| + | ASSERT(FALSE) | ||
| + | END | ||
| + | ELSIF id = 2AX (* hangup test *) THEN | ||
| + | IF len = 0 THEN | ||
| + | REPEAT UNTIL FALSE | ||
| + | END | ||
| + | ELSIF id = 2CX (* multiple clear/ | ||
| + | IF len = 0 THEN | ||
| + | i := 1000; | ||
| + | REPEAT DEC(i); | ||
| + | InitOperations; | ||
| + | PopulateOperations; | ||
| + | WWDG.Update | ||
| + | UNTIL i = 0; | ||
| + | TPorts.Send(port, | ||
| + | END | ||
| + | END | ||
| + | END Receive; | ||
| + | |||
| + | PROCEDURE OnFreq0; | ||
| + | BEGIN | ||
| + | IF enableLED THEN | ||
| + | (* LED blink *) | ||
| + | INC(cnt0); | ||
| + | IF cnt0 MOD (freq0 DIV 4) = 0 THEN | ||
| + | LEDOn | ||
| + | ELSIF cnt0 MOD (freq0 DIV 4) = freq0 DIV 8 THEN | ||
| + | LEDOff | ||
| + | END | ||
| + | END; | ||
| + | |||
| + | WWDG.Update (* reset watchdog timer *) | ||
| + | END OnFreq0; | ||
| + | |||
| + | PROCEDURE MainLoop; | ||
| + | BEGIN | ||
| + | REPEAT | ||
| + | TPorts.Receive(port); | ||
| + | IF SysTick0.OnTimer() THEN | ||
| + | OnFreq0 | ||
| + | END; | ||
| + | ARMv7M.WFI | ||
| + | UNTIL FALSE | ||
| + | END MainLoop; | ||
| + | |||
| + | PROCEDURE Init; | ||
| + | VAR ok: BOOLEAN; | ||
| + | i: INTEGER; | ||
| + | |||
| + | PROCEDURE InitPort; | ||
| + | VAR p: TPorts.InitPar; | ||
| + | BEGIN | ||
| + | p.n := TPorts.USART2; | ||
| + | p.RXPinPort := Pins.A; | ||
| + | p.RXPinN := 3; | ||
| + | p.RXPinAF := Pins.AF7; | ||
| + | p.TXPinPort := Pins.A; | ||
| + | p.TXPinN := 2; | ||
| + | p.TXPinAF := Pins.AF7; | ||
| + | p.UCLK := Sys.PCLK1; | ||
| + | p.baud := 115200; | ||
| + | p.parity := TPorts.parityNone; | ||
| + | p.receive := Receive; | ||
| + | p.version1 := 1; | ||
| + | TPorts.Init(port, | ||
| + | END InitPort; | ||
| + | |||
| + | PROCEDURE InitLED; | ||
| + | BEGIN | ||
| + | Pins.Configure(led0PinPort, | ||
| + | Pins.output, | ||
| + | END InitLED; | ||
| + | |||
| + | BEGIN | ||
| + | InitPort; | ||
| + | IF enableLED THEN | ||
| + | InitLED; | ||
| + | END; | ||
| + | WWDG.Init(WWDG.WDGTBMax, | ||
| + | SysTick0.Init(Sys.HCLK, | ||
| + | |||
| + | IF Traps.trapFlag THEN Traps.ClearTrapFlag; | ||
| + | i := 3; | ||
| + | REPEAT DEC(i); | ||
| + | TPorts.Send(port, | ||
| + | UNTIL i = 0 | ||
| + | ELSE | ||
| + | i := 3; | ||
| + | REPEAT DEC(i); | ||
| + | TPorts.Send(port, | ||
| + | UNTIL i = 0 | ||
| + | END | ||
| + | END Init; | ||
| + | |||
| + | BEGIN | ||
| + | Init; | ||
| + | MainLoop | ||
| + | END TmpTestGC0. | ||
| + | |||
| + | O7ARMv7MLinker.Link STM32F446RE TmpTestGC0 | ||
| ---- | ---- | ||
| Автор заметки: | Автор заметки: | ||