Показаны различия между двумя версиями страницы.
ob:o7:memory [2019/10/27 09:44] иван_денисов |
ob:o7:memory [2020/10/29 07:08] |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | ====== Работа с динамической памятью ====== | ||
- | При выполнении команды **O7ARMv{6, | ||
- | |||
- | Доступная память RAM используется под следующие ресурсы: | ||
- | * куча; | ||
- | * стек; | ||
- | * глобальные переменные; | ||
- | * таблица указателей, | ||
- | |||
- | Куча используется только при динамическом выделении памяти через команду **NEW**, и она заполняется снизу вверх. Для сборки мусора в куче надо вызывать команду **MicroGC0.Collect**. Количество выделенной динамической памяти доступно в переменной **MicroKernel0.allocated**, | ||
- | |||
- | Стек заполняет выделенную под него память сверху вниз. И когда этот объем полностью заполняется, | ||
- | |||
- | Размер памяти, | ||
- | |||
- | Степень заполнение стека возможно вычислить, | ||
- | |||
- | SYSTEM.GET(SYSTEM.REG(MT), | ||
- | SYSTEM.GET(SYSTEM.REG(SP), | ||
- | stkLen := stkOrg - stkPos; | ||
- | |||
- | Так возможно контролировать при отладке, | ||
- | |||
- | Переполнение стека возможно обнаружить и более простым путем, сравнив **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 | ||
- | |||
- | ---- | ||
- | |||
- | Автор заметки: |