@@ -79,8 +79,12 @@ STATIC void common_hal_rgbmatrix_rgbmatrix_construct1(rgbmatrix_rgbmatrix_obj_t
79
79
}
80
80
// verify that the matrix is big enough
81
81
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 ;
82
83
} 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 ;
84
88
self -> bufinfo .len = self -> bufsize ;
85
89
self -> bufinfo .typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW ;
86
90
}
@@ -146,7 +150,9 @@ STATIC void free_pin_seq(uint8_t *seq, int count) {
146
150
147
151
extern int pm_row_count ;
148
152
STATIC 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
+ }
150
156
151
157
if (_PM_protoPtr == & self -> protomatter ) {
152
158
_PM_protoPtr = NULL ;
@@ -160,15 +166,15 @@ STATIC void common_hal_rgbmatrix_rgbmatrix_deinit1(rgbmatrix_rgbmatrix_obj_t *se
160
166
161
167
// If it was supervisor-allocated, it is supervisor-freed and the pointer
162
168
// 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 );
166
171
}
167
172
168
-
169
173
// If a framebuffer was passed in to the constructor, clear the reference
170
174
// here so that it will become GC'able
171
175
self -> framebuffer = mp_const_none ;
176
+
177
+ self -> bufinfo .buf = NULL ;
172
178
}
173
179
174
180
void 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) {
187
193
self -> base .type = & mp_type_NoneType ;
188
194
}
189
195
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
+
190
203
void common_hal_rgbmatrix_rgbmatrix_reconstruct (rgbmatrix_rgbmatrix_obj_t * self ) {
191
204
if (self -> framebuffer != mp_const_none ) {
192
205
memset (& self -> bufinfo , 0 , sizeof (self -> bufinfo ));
@@ -196,11 +209,6 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t *self)
196
209
common_hal_rgbmatrix_rgbmatrix_deinit1 (self );
197
210
common_hal_rgbmatrix_rgbmatrix_construct1 (self , mp_const_none );
198
211
#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
- }
204
212
memset (self -> bufinfo .buf , 0 , self -> bufinfo .len );
205
213
common_hal_rgbmatrix_rgbmatrix_set_paused (self , false);
206
214
}
@@ -214,6 +222,9 @@ void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t *self,
214
222
_PM_stop (& self -> protomatter );
215
223
} else if (!paused && self -> paused ) {
216
224
_PM_resume (& self -> protomatter );
225
+ if (self -> allocation ) {
226
+ self -> bufinfo .buf = self -> allocation -> ptr ;
227
+ }
217
228
_PM_convert_565 (& self -> protomatter , self -> bufinfo .buf , self -> width );
218
229
_PM_swapbuffer_maybe (& self -> protomatter );
219
230
}
@@ -226,6 +237,9 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t *self)
226
237
227
238
void common_hal_rgbmatrix_rgbmatrix_refresh (rgbmatrix_rgbmatrix_obj_t * self ) {
228
239
if (!self -> paused ) {
240
+ if (self -> allocation != NULL ) {
241
+ self -> bufinfo .buf = self -> allocation -> ptr ;
242
+ }
229
243
_PM_convert_565 (& self -> protomatter , self -> bufinfo .buf , self -> width );
230
244
_PM_swapbuffer_maybe (& self -> protomatter );
231
245
}
@@ -240,11 +254,43 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t *self) {
240
254
return computed_height ;
241
255
}
242
256
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
+
243
270
void * common_hal_rgbmatrix_allocator_impl (size_t sz ) {
244
271
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 ;
246
284
}
247
285
248
286
void 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
+ }
250
296
}
0 commit comments