Hi,
I will probably step back and do some testing on an STM32F4 discovery board. This is a custom port to an obsolete platform from TI/Stellaris (LM3s9D92). Please, check my comments below
dhylands wrote:Did you have a print in your finaliser? How do you know your finaliser was called?
I don't see any evidence in your log. It would be good to have the make_new method also do a print which includes the address of the object (i.e. the pointer returned by mp_new_obj_with_finalizer and also have your __del__ method print the pointer value for self.
,
I am connected with my gdb session to the target. So, I have set a breakpoint on the __del__ method implementation and from there on I was following a backtrace.
dhylands wrote:
I tried on the pyboard, and for objects created in the REPL, I'm seeing the opposite problem. My finaliser isn't getting called at all. It gets called fine for objects created in a function that are then collected.
Can you share your source for the C code?
What does your C gc_collect function look like?
On the other hand, if I don't perform any action in the REPL - so no heap memory gets used initially and I just instantiate the class, and throw away the local variable (that retains the instance reference), it would trigger the finaliser correctly. If I keep the variable to reference the instance it won't trigger the finaliser as long as I don't make REPL use some more heap space - e.g. by some of the actions shown in the log in the original post
The project is not ready to be completely published yet, below is the current platform specific part of the GC that my port provides. As you can see it is fairly simple, I have had no issues with it until now. Maybe it is just me not understanding the API properly.
Code: Select all
#include <stdint.h>
#include "py/gc.h"
/* FreeRTOS includes */
#include <FreeRTOS.h>
#include "lib-rtos/assert.h"
#include "micropython-freertos-hal/mp/gc_helper.h"
/** End of the stack of the micropython task */
static uint32_t gc_stack_end;
/**
* Initialize the garbage collector with the bottom of our stack
*
* @param sp - stack pointer that donotes the current top of the stack
*/
void gc_collect_init(mp_uint_t sp) {
void *mp_heap;
// GC init
mp_heap = pvPortMalloc(CONFIG_MICROPYTHON_FREERTOS_HAL_HEAP_SIZE);
assert_ptr(mp_heap);
gc_init(mp_heap, mp_heap + CONFIG_MICROPYTHON_FREERTOS_HAL_HEAP_SIZE);
gc_stack_end = sp;
}
/**
* @todo: Add timing information
*/
void gc_collect(void) {
// TODO: move this to architecture specific section (ARM-Cortex)
// get the registers and the sp
mp_uint_t regs[10];
/* start the GC */
gc_collect_start();
mp_uint_t sp = gc_helper_get_regs_and_sp(regs);
/* perform garbage collection on the stack including the registers */
gc_collect_root((void**)sp, ((uint32_t)gc_stack_end - sp) / sizeof(uint32_t));
/* end the GC */
gc_collect_end();
}
This is the code for the make_new method:
Code: Select all
STATIC mp_obj_t mp_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_uart_obj_t *self;
int uart_id = 0;
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
uart_id = mp_obj_get_int(args[0]);
if (uart_id < 0 || uart_id >= MAX_UART_ID) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id));
}
/* create new UART object - we have an explicit finaliser */
self = m_new_obj_with_finaliser(mp_uart_obj_t);
self->base.type = &mp_uart_type;
self->uart_id = uart_id;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
mp_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return self;
}
In every case, thank you for any input on this.
Best regards,
Jan