Skip to content
13 changes: 5 additions & 8 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,15 @@ void start_mp(supervisor_allocation* heap) {
// to recover from limit hit. (Limit is measured in bytes.)
mp_stack_ctrl_init();

if (stack_alloc != NULL) {
mp_stack_set_limit(stack_alloc->length - 1024);
if (stack_get_bottom() != NULL) {
mp_stack_set_limit(stack_get_length() - 1024);
}


#if MICROPY_MAX_STACK_USAGE
// _ezero (same as _ebss) is an int, so start 4 bytes above it.
if (stack_alloc != NULL) {
mp_stack_set_bottom(stack_alloc->ptr);
if (stack_get_bottom() != NULL) {
mp_stack_set_bottom(stack_get_bottom());
mp_stack_fill_with_sentinel();
}
#endif
Expand All @@ -148,7 +148,7 @@ void start_mp(supervisor_allocation* heap) {
#endif

#if MICROPY_ENABLE_GC
gc_init(heap->ptr, heap->ptr + heap->length / 4);
gc_init(heap->ptr, heap->ptr + get_allocation_length(heap) / 4);
#endif
mp_init();
mp_obj_list_init(mp_sys_path, 0);
Expand Down Expand Up @@ -451,9 +451,6 @@ int __attribute__((used)) main(void) {
// initialise the cpu and peripherals
safe_mode_t safe_mode = port_init();

// Init memory after the port in case the port needs to set aside memory.
memory_init();

// Turn on LEDs
init_status_leds();
rgb_led_status_init();
Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ void reset_cpu(void) {
reset();
}

supervisor_allocation* port_fixed_stack(void) {
return NULL;
bool port_has_fixed_stack(void) {
return false;
}

uint32_t *port_stack_get_limit(void) {
Expand Down
8 changes: 2 additions & 6 deletions ports/cxd56/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,8 @@ void reset_to_bootloader(void) {
}
}

supervisor_allocation _fixed_stack;

supervisor_allocation* port_fixed_stack(void) {
_fixed_stack.ptr = port_stack_get_limit();
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
return &_fixed_stack;
bool port_has_fixed_stack(void) {
return true;
}

uint32_t *port_stack_get_limit(void) {
Expand Down
8 changes: 2 additions & 6 deletions ports/esp32s2/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,8 @@ uint32_t *port_stack_get_top(void) {
return port_stack_get_limit() + ESP_TASK_MAIN_STACK / (sizeof(uint32_t) / sizeof(StackType_t));
}

supervisor_allocation _fixed_stack;

supervisor_allocation* port_fixed_stack(void) {
_fixed_stack.ptr = port_stack_get_limit();
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
return &_fixed_stack;
bool port_has_fixed_stack(void) {
return true;
}

// Place the word to save just after our BSS section that gets blanked.
Expand Down
4 changes: 2 additions & 2 deletions ports/litex/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ void reset_cpu(void) {
for(;;) {}
}

supervisor_allocation* port_fixed_stack(void) {
return NULL;
bool port_has_fixed_stack(void) {
return false;
}

uint32_t *port_heap_get_bottom(void) {
Expand Down
7 changes: 2 additions & 5 deletions ports/mimxrt10xx/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,8 @@ uint32_t *port_stack_get_top(void) {
return &_ld_stack_top;
}

supervisor_allocation _fixed_stack;
supervisor_allocation* port_fixed_stack(void) {
_fixed_stack.ptr = port_stack_get_limit();
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
return &_fixed_stack;
bool port_has_fixed_stack(void) {
return true;
}

uint32_t *port_heap_get_bottom(void) {
Expand Down
4 changes: 2 additions & 2 deletions ports/nrf/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,8 @@ uint32_t *port_heap_get_top(void) {
return port_stack_get_top();
}

supervisor_allocation* port_fixed_stack(void) {
return NULL;
bool port_has_fixed_stack(void) {
return false;
}

uint32_t *port_stack_get_limit(void) {
Expand Down
4 changes: 2 additions & 2 deletions ports/stm/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ uint32_t *port_heap_get_top(void) {
return &_ld_heap_end;
}

supervisor_allocation* port_fixed_stack(void) {
return NULL;
bool port_has_fixed_stack(void) {
return false;
}

uint32_t *port_stack_get_limit(void) {
Expand Down
5 changes: 4 additions & 1 deletion py/circuitpy_mpconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -858,17 +858,20 @@ extern const struct _mp_obj_module_t wifi_module;

#include "supervisor/flash_root_pointers.h"

// From supervisor/memory.c
struct _supervisor_allocation_node;

#define CIRCUITPY_COMMON_ROOT_POINTERS \
const char *readline_hist[8]; \
vstr_t *repl_line; \
mp_obj_t rtc_time_source; \
GAMEPAD_ROOT_POINTERS \
mp_obj_t pew_singleton; \
mp_obj_t terminal_tilegrid_tiles; \
BOARD_UART_ROOT_POINTER \
FLASH_ROOT_POINTERS \
MEMORYMONITOR_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
struct _supervisor_allocation_node* first_embedded_allocation; \

void supervisor_run_background_tasks_if_tick(void);
#define RUN_BACKGROUND_TASKS (supervisor_run_background_tasks_if_tick())
Expand Down
25 changes: 7 additions & 18 deletions shared-module/rgbmatrix/RGBMatrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
// verify that the matrix is big enough
mp_get_index(mp_obj_get_type(self->framebuffer), self->bufinfo.len, MP_OBJ_NEW_SMALL_INT(self->bufsize-1), false);
} else {
_PM_free(self->bufinfo.buf);
_PM_free(self->protomatter.rgbPins);
_PM_free(self->protomatter.addr);
_PM_free(self->protomatter.screenData);
common_hal_rgbmatrix_free_impl(self->bufinfo.buf);
common_hal_rgbmatrix_free_impl(self->protomatter.rgbPins);
common_hal_rgbmatrix_free_impl(self->protomatter.addr);
common_hal_rgbmatrix_free_impl(self->protomatter.screenData);

self->framebuffer = NULL;
self->bufinfo.buf = common_hal_rgbmatrix_allocator_impl(self->bufsize);
Expand Down Expand Up @@ -180,9 +180,6 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) {

void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t* self) {
gc_collect_ptr(self->framebuffer);
gc_collect_ptr(self->protomatter.rgbPins);
gc_collect_ptr(self->protomatter.addr);
gc_collect_ptr(self->protomatter.screenData);
}

void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused) {
Expand Down Expand Up @@ -217,18 +214,10 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self) {
}

void *common_hal_rgbmatrix_allocator_impl(size_t sz) {
if (gc_alloc_possible()) {
return m_malloc_maybe(sz + sizeof(void*), true);
} else {
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
return allocation ? allocation->ptr : NULL;
}
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true);
return allocation ? allocation->ptr : NULL;
}

void common_hal_rgbmatrix_free_impl(void *ptr_in) {
supervisor_allocation *allocation = allocation_from_ptr(ptr_in);

if (allocation) {
free_memory(allocation);
}
free_memory(allocation_from_ptr(ptr_in));
}
57 changes: 14 additions & 43 deletions shared-module/sharpdisplay/SharpMemoryFramebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,10 @@
#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"

#include "supervisor/memory.h"
#include "supervisor/shared/safe_mode.h"

#define SHARPMEM_BIT_WRITECMD_LSB (0x80)
#define SHARPMEM_BIT_VCOM_LSB (0x40)

static void *hybrid_alloc(size_t sz) {
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
if (allocation) {
memset(allocation->ptr, 0, sz);
return allocation->ptr;
}
if (gc_alloc_possible()) {
return m_malloc(sz, true);
}
reset_into_safe_mode(MEM_MANAGE);
return NULL; // unreached
}

static inline void hybrid_free(void *ptr_in) {
supervisor_allocation *allocation = allocation_from_ptr(ptr_in);

if (allocation) {
free_memory(allocation);
}
}

STATIC uint8_t bitrev(uint8_t n) {
uint8_t r = 0;
for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i);
Expand Down Expand Up @@ -102,17 +80,22 @@ void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *s
}

void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self) {
if (!allocation_from_ptr(self->bufinfo.buf)) {
self->bufinfo.buf = NULL;
}
// Look up the allocation by the old pointer and get the new pointer from it.
supervisor_allocation* alloc = allocation_from_ptr(self->bufinfo.buf);
self->bufinfo.buf = alloc ? alloc->ptr : NULL;
}

void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo) {
if (!self->bufinfo.buf) {
int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
int height = common_hal_sharpdisplay_framebuffer_get_height(self);
self->bufinfo.len = row_stride * height + 2;
self->bufinfo.buf = hybrid_alloc(self->bufinfo.len);
supervisor_allocation* alloc = allocate_memory(align32_size(self->bufinfo.len), false, true);
if (alloc == NULL) {
m_malloc_fail(self->bufinfo.len);
}
self->bufinfo.buf = alloc->ptr;
memset(alloc->ptr, 0, self->bufinfo.len);

uint8_t *data = self->bufinfo.buf;
*data++ = SHARPMEM_BIT_WRITECMD_LSB;
Expand All @@ -123,7 +106,9 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob
}
self->full_refresh = true;
}
*bufinfo = self->bufinfo;
if (bufinfo) {
*bufinfo = self->bufinfo;
}
}

void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) {
Expand All @@ -137,7 +122,7 @@ void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *

common_hal_reset_pin(self->chip_select.pin);

hybrid_free(self->bufinfo.buf);
free_memory(allocation_from_ptr(self->bufinfo.buf));

memset(self, 0, sizeof(*self));
}
Expand All @@ -154,19 +139,7 @@ void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_
self->height = height;
self->baudrate = baudrate;

int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
self->bufinfo.len = row_stride * height + 2;
// re-use a supervisor allocation if possible
self->bufinfo.buf = hybrid_alloc(self->bufinfo.len);

uint8_t *data = self->bufinfo.buf;
*data++ = SHARPMEM_BIT_WRITECMD_LSB;

for(int y=0; y<self->height; y++) {
*data = bitrev(y+1);
data += row_stride;
}
self->full_refresh = true;
common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL);
}

void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) {
Expand Down Expand Up @@ -271,7 +244,5 @@ const framebuffer_p_t sharpdisplay_framebuffer_proto = {
};

void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) {
gc_collect_ptr(self->framebuffer);
gc_collect_ptr(self->bus);
gc_collect_ptr(self->bufinfo.buf);
}
1 change: 0 additions & 1 deletion shared-module/sharpdisplay/SharpMemoryFramebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

typedef struct {
mp_obj_base_t base;
mp_obj_t framebuffer;
busio_spi_obj_t* bus;
busio_spi_obj_t inline_bus;
digitalio_digitalinout_obj_t chip_select;
Expand Down
8 changes: 4 additions & 4 deletions shared-module/usb_midi/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ supervisor_allocation* usb_midi_allocation;

void usb_midi_init(void) {
// TODO(tannewt): Make this dynamic.
uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
size_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));

// For each embedded MIDI Jack in the descriptor we create a Port
usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false, false);

mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
ports->base.type = &mp_type_tuple;
Expand Down
33 changes: 23 additions & 10 deletions supervisor/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,45 @@

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

typedef struct {
uint32_t* ptr;
uint32_t length; // in bytes
} supervisor_allocation;



void memory_init(void);
void free_memory(supervisor_allocation* allocation);

// Find the allocation with the given ptr, NULL if not found. When called from the context of a
// supervisor_move_memory() callback, finds the allocation that had that ptr *before* the move, but
// the returned allocation already contains the ptr after the move.
// When called with NULL, may return either NULL or an unused allocation whose ptr is NULL (this is
// a feature used internally in allocate_memory to save code size). Passing the return value to
// free_memory() is a permissible no-op in either case.
supervisor_allocation* allocation_from_ptr(void *ptr);

supervisor_allocation* allocate_remaining_memory(void);

// Allocate a piece of a given length in bytes. If high_address is true then it should be allocated
// at a lower address from the top of the stack. Otherwise, addresses will increase starting after
// statically allocated memory.
supervisor_allocation* allocate_memory(uint32_t length, bool high_address);
// statically allocated memory. If movable is false, memory will be taken from outside the GC heap
// and will stay stationary until freed. While the VM is running, this will fail unless a previous
// allocation of exactly matching length has recently been freed. If movable is true, memory will be
// taken from either outside or inside the GC heap, and when the VM exits, will be moved outside.
// The ptr of the returned supervisor_allocation will change at that point. If you need to be
// notified of that, add your own callback function at the designated place near the end of
// supervisor_move_memory().
supervisor_allocation* allocate_memory(uint32_t length, bool high_address, bool movable);

static inline uint16_t align32_size(uint16_t size) {
if (size % 4 != 0) {
return (size & 0xfffc) + 0x4;
}
return size;
static inline size_t align32_size(size_t size) {
return (size + 3) & ~3;
}

// Called after the heap is freed in case the supervisor wants to save some values.
size_t get_allocation_length(supervisor_allocation* allocation);

// Called after the GC heap is freed, transfers movable allocations from the GC heap to the
// supervisor heap and compacts the supervisor heap.
void supervisor_move_memory(void);

#endif // MICROPY_INCLUDED_SUPERVISOR_MEMORY_H
Loading