stm: Tidy up memory labels; optimise GC root scanning.
Addresses issues #272 and #273.
This commit is contained in:
parent
d46ca25757
commit
ed378cd12f
@ -8,20 +8,36 @@
|
|||||||
#include "gccollect.h"
|
#include "gccollect.h"
|
||||||
#include "systick.h"
|
#include "systick.h"
|
||||||
|
|
||||||
void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
|
machine_uint_t gc_helper_get_regs_and_sp(machine_uint_t *regs);
|
||||||
|
|
||||||
|
// obsolete
|
||||||
|
// void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
|
||||||
|
|
||||||
void gc_collect(void) {
|
void gc_collect(void) {
|
||||||
|
// get current time, in case we want to time the GC
|
||||||
uint32_t start = sys_tick_counter;
|
uint32_t start = sys_tick_counter;
|
||||||
|
|
||||||
|
// start the GC
|
||||||
gc_collect_start();
|
gc_collect_start();
|
||||||
gc_collect_root((void**)&_ram_start, ((uint32_t)&_heap_start - (uint32_t)&_ram_start) / sizeof(uint32_t));
|
|
||||||
|
// scan everything in RAM before the heap
|
||||||
|
// this includes the data and bss segments
|
||||||
|
// TODO possibly don't need to scan data, since all pointers should start out NULL and be in bss
|
||||||
|
gc_collect_root((void**)&_ram_start, ((uint32_t)&_bss_end - (uint32_t)&_ram_start) / sizeof(uint32_t));
|
||||||
|
|
||||||
|
// get the registers and the sp
|
||||||
machine_uint_t regs[10];
|
machine_uint_t regs[10];
|
||||||
gc_helper_get_regs_and_clean_stack(regs, (machine_uint_t)&_heap_end);
|
machine_uint_t sp = gc_helper_get_regs_and_sp(regs);
|
||||||
gc_collect_root((void**)&_heap_end, ((uint32_t)&_ram_end - (uint32_t)&_heap_end) / sizeof(uint32_t)); // will trace regs since they now live in this function on the stack
|
|
||||||
|
// trace the stack, including the registers (since they live on the stack in this function)
|
||||||
|
gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t));
|
||||||
|
|
||||||
|
// end the GC
|
||||||
gc_collect_end();
|
gc_collect_end();
|
||||||
uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
|
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
// print GC info
|
// print GC info
|
||||||
|
uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
|
||||||
gc_info_t info;
|
gc_info_t info;
|
||||||
gc_info(&info);
|
gc_info(&info);
|
||||||
printf("GC@%lu %lums\n", start, ticks);
|
printf("GC@%lu %lums\n", start, ticks);
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
|
// variables defining memory layout
|
||||||
|
// (these probably belong somewhere else...)
|
||||||
|
extern uint32_t _text_end;
|
||||||
|
extern uint32_t _data_start_init;
|
||||||
extern uint32_t _ram_start;
|
extern uint32_t _ram_start;
|
||||||
|
extern uint32_t _data_start;
|
||||||
|
extern uint32_t _data_end;
|
||||||
|
extern uint32_t _bss_start;
|
||||||
|
extern uint32_t _bss_end;
|
||||||
extern uint32_t _heap_start;
|
extern uint32_t _heap_start;
|
||||||
extern uint32_t _ram_end;
|
|
||||||
extern uint32_t _heap_end;
|
extern uint32_t _heap_end;
|
||||||
|
extern uint32_t _stack_end;
|
||||||
|
extern uint32_t _ram_end;
|
||||||
|
|
||||||
void gc_collect(void);
|
void gc_collect(void);
|
||||||
|
|
||||||
|
@ -4,6 +4,32 @@
|
|||||||
.text
|
.text
|
||||||
.align 2
|
.align 2
|
||||||
|
|
||||||
|
@ uint gc_helper_get_regs_and_sp(r0=uint regs[10])
|
||||||
|
.global gc_helper_get_regs_and_sp
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type gc_helper_get_regs_and_sp, %function
|
||||||
|
gc_helper_get_regs_and_sp:
|
||||||
|
@ store registers into given array
|
||||||
|
str r4, [r0], #4
|
||||||
|
str r5, [r0], #4
|
||||||
|
str r6, [r0], #4
|
||||||
|
str r7, [r0], #4
|
||||||
|
str r8, [r0], #4
|
||||||
|
str r9, [r0], #4
|
||||||
|
str r10, [r0], #4
|
||||||
|
str r11, [r0], #4
|
||||||
|
str r12, [r0], #4
|
||||||
|
str r13, [r0], #4
|
||||||
|
|
||||||
|
@ return the sp
|
||||||
|
mov r0, sp
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
||||||
|
@ this next function is now obsolete
|
||||||
|
|
||||||
|
.size gc_helper_get_regs_and_clean_stack, .-gc_helper_get_regs_and_clean_stack
|
||||||
@ void gc_helper_get_regs_and_clean_stack(r0=uint regs[10], r1=heap_end)
|
@ void gc_helper_get_regs_and_clean_stack(r0=uint regs[10], r1=heap_end)
|
||||||
.global gc_helper_get_regs_and_clean_stack
|
.global gc_helper_get_regs_and_clean_stack
|
||||||
.thumb
|
.thumb
|
||||||
|
21
stm/main.c
21
stm/main.c
@ -171,20 +171,13 @@ static mp_obj_t pyb_info(void) {
|
|||||||
|
|
||||||
// to print info about memory
|
// to print info about memory
|
||||||
{
|
{
|
||||||
extern void *_sidata;
|
printf("_text_end=%p\n", &_text_end);
|
||||||
extern void *_sdata;
|
printf("_data_start_init=%p\n", &_data_start_init);
|
||||||
extern void *_edata;
|
printf("_data_start=%p\n", &_data_start);
|
||||||
extern void *_sbss;
|
printf("_data_end=%p\n", &_data_end);
|
||||||
extern void *_ebss;
|
printf("_bss_start=%p\n", &_bss_start);
|
||||||
extern void *_estack;
|
printf("_bss_end=%p\n", &_bss_end);
|
||||||
extern void *_etext;
|
printf("_stack_end=%p\n", &_stack_end);
|
||||||
printf("_etext=%p\n", &_etext);
|
|
||||||
printf("_sidata=%p\n", &_sidata);
|
|
||||||
printf("_sdata=%p\n", &_sdata);
|
|
||||||
printf("_edata=%p\n", &_edata);
|
|
||||||
printf("_sbss=%p\n", &_sbss);
|
|
||||||
printf("_ebss=%p\n", &_ebss);
|
|
||||||
printf("_estack=%p\n", &_estack);
|
|
||||||
printf("_ram_start=%p\n", &_ram_start);
|
printf("_ram_start=%p\n", &_ram_start);
|
||||||
printf("_heap_start=%p\n", &_heap_start);
|
printf("_heap_start=%p\n", &_heap_start);
|
||||||
printf("_heap_end=%p\n", &_heap_end);
|
printf("_heap_end=%p\n", &_heap_end);
|
||||||
|
@ -47,15 +47,15 @@
|
|||||||
|
|
||||||
/* start address for the initialization values of the .data section.
|
/* start address for the initialization values of the .data section.
|
||||||
defined in linker script */
|
defined in linker script */
|
||||||
.word _sidata
|
.word _data_start_init
|
||||||
/* start address for the .data section. defined in linker script */
|
/* start address for the .data section. defined in linker script */
|
||||||
.word _sdata
|
.word _data_start
|
||||||
/* end address for the .data section. defined in linker script */
|
/* end address for the .data section. defined in linker script */
|
||||||
.word _edata
|
.word _data_end
|
||||||
/* start address for the .bss section. defined in linker script */
|
/* start address for the .bss section. defined in linker script */
|
||||||
.word _sbss
|
.word _bss_start
|
||||||
/* end address for the .bss section. defined in linker script */
|
/* end address for the .bss section. defined in linker script */
|
||||||
.word _ebss
|
.word _bss_end
|
||||||
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
|
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,9 +90,9 @@ LoopCopyDataInit:
|
|||||||
cmp r2, r3
|
cmp r2, r3
|
||||||
bcc CopyDataInit
|
bcc CopyDataInit
|
||||||
*/
|
*/
|
||||||
ldr r0, =_sidata @ source pointer
|
ldr r0, =_data_start_init @ source pointer
|
||||||
ldr r1, =_sdata @ destination pointer
|
ldr r1, =_data_start @ destination pointer
|
||||||
ldr r2, =_edata @ maximum destination pointer
|
ldr r2, =_data_end @ maximum destination pointer
|
||||||
b data_init_entry
|
b data_init_entry
|
||||||
data_init_loop:
|
data_init_loop:
|
||||||
ldr r3, [r0], #4
|
ldr r3, [r0], #4
|
||||||
@ -117,8 +117,8 @@ LoopFillZerobss:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
movs r0, #0 @ source value
|
movs r0, #0 @ source value
|
||||||
ldr r1, =_sbss @ destination pointer
|
ldr r1, =_bss_start @ destination pointer
|
||||||
ldr r2, =_ebss @ maximum destination pointer
|
ldr r2, =_bss_end @ maximum destination pointer
|
||||||
b bss_init_entry
|
b bss_init_entry
|
||||||
bss_init_loop:
|
bss_init_loop:
|
||||||
str r0, [r1], #4
|
str r0, [r1], #4
|
||||||
@ -158,7 +158,7 @@ Infinite_Loop:
|
|||||||
|
|
||||||
|
|
||||||
g_pfnVectors:
|
g_pfnVectors:
|
||||||
.word _estack
|
.word _stack_end
|
||||||
.word Reset_Handler
|
.word Reset_Handler
|
||||||
.word NMI_Handler
|
.word NMI_Handler
|
||||||
.word HardFault_Handler
|
.word HardFault_Handler
|
||||||
|
@ -17,7 +17,7 @@ _minimum_stack_size = 2K;
|
|||||||
_minimum_heap_size = 16K;
|
_minimum_heap_size = 16K;
|
||||||
|
|
||||||
/* top end of the stack */
|
/* top end of the stack */
|
||||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
_stack_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
|
||||||
/* RAM extents for the garbage collector */
|
/* RAM extents for the garbage collector */
|
||||||
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
|
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
@ -47,8 +47,8 @@ SECTIONS
|
|||||||
/* *(.glue_7t) */ /* glue thumb to arm code */
|
/* *(.glue_7t) */ /* glue thumb to arm code */
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_etext = .; /* define a global symbol at end of code */
|
_text_end = .; /* define a global symbol at end of code */
|
||||||
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
|
_data_start_init = _text_end; /* This is used by the startup in order to initialize the .data secion */
|
||||||
} >FLASH_TEXT
|
} >FLASH_TEXT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -69,29 +69,29 @@ SECTIONS
|
|||||||
The program executes knowing that the data is in the RAM
|
The program executes knowing that the data is in the RAM
|
||||||
but the loader puts the initial values in the FLASH (inidata).
|
but the loader puts the initial values in the FLASH (inidata).
|
||||||
It is one task of the startup to copy the initial values from FLASH to RAM. */
|
It is one task of the startup to copy the initial values from FLASH to RAM. */
|
||||||
.data : AT ( _sidata )
|
.data : AT ( _data_start_init )
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
|
_data_start = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
|
||||||
_ram_start = .; /* create a global symbol at ram start for garbage collector */
|
_ram_start = .; /* create a global symbol at ram start for garbage collector */
|
||||||
*(.data) /* .data sections */
|
*(.data) /* .data sections */
|
||||||
*(.data*) /* .data* sections */
|
*(.data*) /* .data* sections */
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
|
_data_end = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
|
||||||
} >RAM
|
} >RAM
|
||||||
|
|
||||||
/* Uninitialized data section */
|
/* Uninitialized data section */
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_sbss = .; /* define a global symbol at bss start; used by startup code */
|
_bss_start = .; /* define a global symbol at bss start; used by startup code */
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_ebss = .; /* define a global symbol at bss end; used by startup code */
|
_bss_end = .; /* define a global symbol at bss end; used by startup code and GC */
|
||||||
} >RAM
|
} >RAM
|
||||||
|
|
||||||
/* this is to define the start of the heap, and make sure we have a minimum size */
|
/* this is to define the start of the heap, and make sure we have a minimum size */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user