Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
ob:o7:memory [2016/08/24 19:05] иван_денисов |
ob:o7:memory [2020/10/29 07:08] (текущий) |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ====== | + | ====== |
| - | При выполнении команды **O7ARMv{6, | + | При выполнении команды **O7ARMv{6, |
| Доступная память RAM используется под следующие ресурсы: | Доступная память RAM используется под следующие ресурсы: | ||
| - | * heap (heapLim - heapOrg) | + | * куча; |
| - | * stack | + | * стек; |
| - | * global variables | + | * глобальные переменные; |
| - | * pointers table, strings, modules table | + | * таблица указателей, строки, таблица модулей. |
| - | Heap (куча) используется только при динамическом выделении памяти через команду NEW, и она заполняется снизу вверх. (Перед вызовом команды NEW для указателя, | + | Куча используется только при динамическом выделении памяти через команду |
| - | Стек заполняет выделенную под него память сверху вниз. И когда этот объем полностью заполняется, | + | Стек заполняет выделенную под него память сверху вниз. И когда этот объем полностью заполняется, |
| - | Размер памяти, | + | Размер памяти, |
| - | Чтобы | + | Степень заполнение стека |
| - | SYSTEM.GET(SYSTEM.REG(6), stkOrg); | + | SYSTEM.GET(SYSTEM.REG(MT), stkOrg); |
| - | SYSTEM.GET(SYSTEM.REG(13), stkPos); | + | SYSTEM.GET(SYSTEM.REG(SP), stkPos); |
| stkLen := stkOrg - stkPos; | stkLen := stkOrg - stkPos; | ||
| - | Так возможно контролировать при отладка, не превышает ли **stkLen** значение **StkSize** | + | Так возможно контролировать при отладке, не превышает ли **stkLen** значение **StkSize** |
| - | Переполнение стека возможно | + | Переполнение стека возможно |
| + | |||
| + | ===== Тестирование сборщика мусора ===== | ||
| + | |||
| + | Александр Ширяев разработал модуль для тестирования сборщика мусора: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | 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 | ||
| + | |||
| + | ---- | ||
| + | |||
| + | Автор заметки: | ||