@@ -188,6 +188,9 @@ static uint32_t core1_stack[stack_size] = {0};
188188mp_obj_t Presto_make_new (const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
189189 _Presto_obj_t *self = nullptr ;
190190
191+ // Clean up any existing instance of Presto.
192+ (void )Presto___del__ (mp_const_none);
193+
191194 enum { ARG_full_res, ARG_palette };
192195 static const mp_arg_t allowed_args[] = {
193196 { MP_QSTR_full_res, MP_ARG_BOOL, {.u_bool = false } },
@@ -408,9 +411,25 @@ mp_obj_t Presto_set_led_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
408411}
409412
410413mp_obj_t Presto___del__ (mp_obj_t self_in) {
411- (void )self_in;
412- // _Presto_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Presto_obj_t);
413- presto_debug (" signal core1\n " );
414+ // Since presto_obj is singleton, relying on __del__ and the finalizer
415+ // could leave us in a situation where an old Presto instance is garbage
416+ // collected after we've allocated a new one- ripping out the presto_obj
417+ // from underneath the new instance.
418+
419+ _Presto_obj_t *self = nullptr ;
420+
421+ if (self_in != mp_const_none) {
422+ self = MP_OBJ_TO_PTR2 (self_in, _Presto_obj_t);
423+ }
424+
425+ // Only allow an instance to tear down core1 if it's the current owner
426+ // or if we're explicitly calling `Presto___del__(mp_const_none)` in make_new.
427+ if (presto_obj == nullptr || (self != nullptr && self != presto_obj)) {
428+ presto_debug (" __del__ called by non-owner, skipping teardown.\n " );
429+ return mp_const_none;
430+ }
431+
432+ presto_debug (" stop core1\n " );
414433 presto_obj->exit_core1 = true ;
415434 __sev ();
416435
@@ -422,7 +441,7 @@ mp_obj_t Presto___del__(mp_obj_t self_in) {
422441 }
423442 } while (fifo_code != 0 );
424443
425- presto_debug (" core1 returned \n " );
444+ presto_debug (" core1 stopped \n " );
426445
427446 m_del_class (ST7701, presto_obj->presto );
428447 presto_obj->presto = nullptr ;
0 commit comments