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 "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) {
|
||||
// get current time, in case we want to time the GC
|
||||
uint32_t start = sys_tick_counter;
|
||||
|
||||
// start the GC
|
||||
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];
|
||||
gc_helper_get_regs_and_clean_stack(regs, (machine_uint_t)&_heap_end);
|
||||
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
|
||||
machine_uint_t sp = gc_helper_get_regs_and_sp(regs);
|
||||
|
||||
// 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();
|
||||
uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
|
||||
|
||||
if (0) {
|
||||
// print GC info
|
||||
uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
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 _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 _ram_end;
|
||||
extern uint32_t _heap_end;
|
||||
extern uint32_t _stack_end;
|
||||
extern uint32_t _ram_end;
|
||||
|
||||
void gc_collect(void);
|
||||
|
||||
|
@ -4,6 +4,32 @@
|
||||
.text
|
||||
.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)
|
||||
.global gc_helper_get_regs_and_clean_stack
|
||||
.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
|
||||
{
|
||||
extern void *_sidata;
|
||||
extern void *_sdata;
|
||||
extern void *_edata;
|
||||
extern void *_sbss;
|
||||
extern void *_ebss;
|
||||
extern void *_estack;
|
||||
extern void *_etext;
|
||||
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("_text_end=%p\n", &_text_end);
|
||||
printf("_data_start_init=%p\n", &_data_start_init);
|
||||
printf("_data_start=%p\n", &_data_start);
|
||||
printf("_data_end=%p\n", &_data_end);
|
||||
printf("_bss_start=%p\n", &_bss_start);
|
||||
printf("_bss_end=%p\n", &_bss_end);
|
||||
printf("_stack_end=%p\n", &_stack_end);
|
||||
printf("_ram_start=%p\n", &_ram_start);
|
||||
printf("_heap_start=%p\n", &_heap_start);
|
||||
printf("_heap_end=%p\n", &_heap_end);
|
||||
|
@ -47,15 +47,15 @@
|
||||
|
||||
/* start address for the initialization values of the .data section.
|
||||
defined in linker script */
|
||||
.word _sidata
|
||||
.word _data_start_init
|
||||
/* 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 */
|
||||
.word _edata
|
||||
.word _data_end
|
||||
/* 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 */
|
||||
.word _ebss
|
||||
.word _bss_end
|
||||
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
|
||||
|
||||
/**
|
||||
@ -90,9 +90,9 @@ LoopCopyDataInit:
|
||||
cmp r2, r3
|
||||
bcc CopyDataInit
|
||||
*/
|
||||
ldr r0, =_sidata @ source pointer
|
||||
ldr r1, =_sdata @ destination pointer
|
||||
ldr r2, =_edata @ maximum destination pointer
|
||||
ldr r0, =_data_start_init @ source pointer
|
||||
ldr r1, =_data_start @ destination pointer
|
||||
ldr r2, =_data_end @ maximum destination pointer
|
||||
b data_init_entry
|
||||
data_init_loop:
|
||||
ldr r3, [r0], #4
|
||||
@ -117,8 +117,8 @@ LoopFillZerobss:
|
||||
*/
|
||||
|
||||
movs r0, #0 @ source value
|
||||
ldr r1, =_sbss @ destination pointer
|
||||
ldr r2, =_ebss @ maximum destination pointer
|
||||
ldr r1, =_bss_start @ destination pointer
|
||||
ldr r2, =_bss_end @ maximum destination pointer
|
||||
b bss_init_entry
|
||||
bss_init_loop:
|
||||
str r0, [r1], #4
|
||||
@ -158,7 +158,7 @@ Infinite_Loop:
|
||||
|
||||
|
||||
g_pfnVectors:
|
||||
.word _estack
|
||||
.word _stack_end
|
||||
.word Reset_Handler
|
||||
.word NMI_Handler
|
||||
.word HardFault_Handler
|
||||
|
@ -17,7 +17,7 @@ _minimum_stack_size = 2K;
|
||||
_minimum_heap_size = 16K;
|
||||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_stack_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* RAM extents for the garbage collector */
|
||||
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||
@ -47,8 +47,8 @@ SECTIONS
|
||||
/* *(.glue_7t) */ /* glue thumb to arm code */
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbol at end of code */
|
||||
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
|
||||
_text_end = .; /* define a global symbol at end of code */
|
||||
_data_start_init = _text_end; /* This is used by the startup in order to initialize the .data secion */
|
||||
} >FLASH_TEXT
|
||||
|
||||
/*
|
||||
@ -69,29 +69,29 @@ SECTIONS
|
||||
The program executes knowing that the data is in the RAM
|
||||
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. */
|
||||
.data : AT ( _sidata )
|
||||
.data : AT ( _data_start_init )
|
||||
{
|
||||
. = 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 */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
|
||||
. = 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
|
||||
|
||||
/* Uninitialized data section */
|
||||
.bss :
|
||||
{
|
||||
. = 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*)
|
||||
*(COMMON)
|
||||
|
||||
. = 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
|
||||
|
||||
/* this is to define the start of the heap, and make sure we have a minimum size */
|
||||
|
Loading…
Reference in New Issue
Block a user