@@ -79,8 +79,12 @@ STATIC void common_hal_rgbmatrix_rgbmatrix_construct1(rgbmatrix_rgbmatrix_obj_t
7979 }
8080 // verify that the matrix is big enough
8181 mp_get_index (mp_obj_get_type (self -> framebuffer ), self -> bufinfo .len , MP_OBJ_NEW_SMALL_INT (self -> bufsize - 1 ), false);
82+ self -> allocation = NULL ;
8283 } else {
83- self -> bufinfo .buf = common_hal_rgbmatrix_allocator_impl (self -> bufsize );
84+ // The supervisor allocation can move memory by changing self->allocation->ptr.
85+ // So we hold onto it and update bufinfo every time we use it.
86+ self -> allocation = allocate_memory (align32_size (self -> bufsize ), false, true);
87+ self -> bufinfo .buf = self -> allocation -> ptr ;
8488 self -> bufinfo .len = self -> bufsize ;
8589 self -> bufinfo .typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW ;
8690 }
@@ -146,7 +150,9 @@ STATIC void free_pin_seq(uint8_t *seq, int count) {
146150
147151extern int pm_row_count ;
148152STATIC void common_hal_rgbmatrix_rgbmatrix_deinit1 (rgbmatrix_rgbmatrix_obj_t * self ) {
149- common_hal_rgbmatrix_timer_disable (self -> timer );
153+ if (self -> timer != NULL ) {
154+ common_hal_rgbmatrix_timer_disable (self -> timer );
155+ }
150156
151157 if (_PM_protoPtr == & self -> protomatter ) {
152158 _PM_protoPtr = NULL ;
@@ -160,15 +166,15 @@ STATIC void common_hal_rgbmatrix_rgbmatrix_deinit1(rgbmatrix_rgbmatrix_obj_t *se
160166
161167 // If it was supervisor-allocated, it is supervisor-freed and the pointer
162168 // is zeroed, otherwise the pointer is just zeroed
163- if (self -> bufinfo .buf ) {
164- common_hal_rgbmatrix_free_impl (self -> bufinfo .buf );
165- self -> bufinfo .buf = NULL ;
169+ if (self -> allocation != NULL ) {
170+ free_memory (self -> allocation );
166171 }
167172
168-
169173 // If a framebuffer was passed in to the constructor, clear the reference
170174 // here so that it will become GC'able
171175 self -> framebuffer = mp_const_none ;
176+
177+ self -> bufinfo .buf = NULL ;
172178}
173179
174180void common_hal_rgbmatrix_rgbmatrix_deinit (rgbmatrix_rgbmatrix_obj_t * self ) {
@@ -187,6 +193,13 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t *self) {
187193 self -> base .type = & mp_type_NoneType ;
188194}
189195
196+ void common_hal_rgbmatrix_rgbmatrix_get_bufinfo (rgbmatrix_rgbmatrix_obj_t * self , mp_buffer_info_t * bufinfo ) {
197+ if (self -> allocation != NULL ) {
198+ self -> bufinfo .buf = self -> allocation -> ptr ;
199+ }
200+ * bufinfo = self -> bufinfo ;
201+ }
202+
190203void common_hal_rgbmatrix_rgbmatrix_reconstruct (rgbmatrix_rgbmatrix_obj_t * self ) {
191204 if (self -> framebuffer != mp_const_none ) {
192205 memset (& self -> bufinfo , 0 , sizeof (self -> bufinfo ));
@@ -196,11 +209,6 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t *self)
196209 common_hal_rgbmatrix_rgbmatrix_deinit1 (self );
197210 common_hal_rgbmatrix_rgbmatrix_construct1 (self , mp_const_none );
198211 #endif
199- if (self -> bufinfo .buf == NULL ) {
200- self -> bufinfo .buf = common_hal_rgbmatrix_allocator_impl (self -> bufsize );
201- self -> bufinfo .len = self -> bufsize ;
202- self -> bufinfo .typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW ;
203- }
204212 memset (self -> bufinfo .buf , 0 , self -> bufinfo .len );
205213 common_hal_rgbmatrix_rgbmatrix_set_paused (self , false);
206214}
@@ -214,6 +222,9 @@ void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t *self,
214222 _PM_stop (& self -> protomatter );
215223 } else if (!paused && self -> paused ) {
216224 _PM_resume (& self -> protomatter );
225+ if (self -> allocation ) {
226+ self -> bufinfo .buf = self -> allocation -> ptr ;
227+ }
217228 _PM_convert_565 (& self -> protomatter , self -> bufinfo .buf , self -> width );
218229 _PM_swapbuffer_maybe (& self -> protomatter );
219230 }
@@ -226,6 +237,9 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t *self)
226237
227238void common_hal_rgbmatrix_rgbmatrix_refresh (rgbmatrix_rgbmatrix_obj_t * self ) {
228239 if (!self -> paused ) {
240+ if (self -> allocation != NULL ) {
241+ self -> bufinfo .buf = self -> allocation -> ptr ;
242+ }
229243 _PM_convert_565 (& self -> protomatter , self -> bufinfo .buf , self -> width );
230244 _PM_swapbuffer_maybe (& self -> protomatter );
231245 }
@@ -240,11 +254,43 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t *self) {
240254 return computed_height ;
241255}
242256
257+ // Track the returned pointers and their matching allocation so that we can free
258+ // them even when the memory was moved by the supervisor. This prevents leaks
259+ // but doesn't protect against the memory being used after its been freed! The
260+ // long term fix is to utilize a permanent heap that can be shared with MP's
261+ // split heap.
262+ typedef struct matrix_allocation {
263+ void * original_pointer ;
264+ supervisor_allocation * allocation ;
265+ } matrix_allocation_t ;
266+
267+ // Four should be more than we ever need. ProtoMatter does 3 allocations currently.
268+ static matrix_allocation_t allocations [4 ];
269+
243270void * common_hal_rgbmatrix_allocator_impl (size_t sz ) {
244271 supervisor_allocation * allocation = allocate_memory (align32_size (sz ), false, true);
245- return allocation ? allocation -> ptr : NULL ;
272+ if (allocation == NULL ) {
273+ return NULL ;
274+ }
275+ for (size_t i = 0 ; i < sizeof (allocations ); i ++ ) {
276+ matrix_allocation_t * matrix_allocation = & allocations [i ];
277+ if (matrix_allocation -> original_pointer == NULL ) {
278+ matrix_allocation -> original_pointer = allocation -> ptr ;
279+ matrix_allocation -> allocation = allocation ;
280+ return allocation -> ptr ;
281+ }
282+ }
283+ return NULL ;
246284}
247285
248286void common_hal_rgbmatrix_free_impl (void * ptr_in ) {
249- free_memory (allocation_from_ptr (ptr_in ));
287+ for (size_t i = 0 ; i < sizeof (allocations ); i ++ ) {
288+ matrix_allocation_t * matrix_allocation = & allocations [i ];
289+ if (matrix_allocation -> original_pointer == ptr_in ) {
290+ matrix_allocation -> original_pointer = NULL ;
291+ free_memory (matrix_allocation -> allocation );
292+ matrix_allocation -> allocation = NULL ;
293+ return ;
294+ }
295+ }
250296}
0 commit comments