1
+ // Code taken from
2
+ // https://github.com/Zondax/embedded-alloc
3
+ // https://crates.io/crates/embedded-alloc/0.5.1
4
+
5
+ // LLHeap with PIC on RefCell
6
+ // This was required to PIC the RefCell on the Heap struct. Otherwise, the app will fail with segmentation fault.
7
+
8
+ use core:: alloc:: { GlobalAlloc , Layout } ;
9
+ use core:: cell:: RefCell ;
10
+ use core:: ptr:: { self , NonNull } ;
11
+
12
+ use critical_section:: Mutex ;
13
+ use linked_list_allocator:: Heap as LLHeap ;
14
+
15
+ use crate :: pic:: PIC ;
16
+
17
+ /// A linked list first fit heap.
18
+ pub struct Heap {
19
+ pub heap : Mutex < PIC < RefCell < LLHeap > > > ,
20
+ }
21
+
22
+ impl Heap {
23
+ /// Create a new UNINITIALIZED heap allocator
24
+ ///
25
+ /// You must initialize this heap using the
26
+ /// [`init`](Self::init) method before using the allocator.
27
+ pub const fn empty ( ) -> Heap {
28
+ Heap {
29
+ heap : Mutex :: new ( PIC :: new ( RefCell :: new ( LLHeap :: empty ( ) ) ) ) ,
30
+ }
31
+ }
32
+
33
+ /// Initializes the heap
34
+ ///
35
+ /// This function must be called BEFORE you run any code that makes use of the
36
+ /// allocator.
37
+ ///
38
+ /// `start_addr` is the address where the heap will be located.
39
+ ///
40
+ /// `size` is the size of the heap in bytes.
41
+ ///
42
+ /// Note that:
43
+ ///
44
+ /// - The heap grows "upwards", towards larger addresses. Thus `start_addr` will
45
+ /// be the smallest address used.
46
+ ///
47
+ /// - The largest address used is `start_addr + size - 1`, so if `start_addr` is
48
+ /// `0x1000` and `size` is `0x30000` then the allocator won't use memory at
49
+ /// addresses `0x31000` and larger.
50
+ ///
51
+ /// # Safety
52
+ ///
53
+ /// Obey these or Bad Stuff will happen.
54
+ ///
55
+ /// - This function must be called exactly ONCE.
56
+ /// - `size > 0`
57
+ pub unsafe fn init ( & self , start_addr : usize , size : usize ) {
58
+ // zlog("-- init 1 --\x00");
59
+ critical_section:: with ( |cs| {
60
+ self . heap
61
+ . borrow ( cs)
62
+ . borrow_mut ( )
63
+ . init ( start_addr as * mut u8 , size) ;
64
+ } ) ;
65
+ }
66
+
67
+ /// Returns an estimate of the amount of bytes in use.
68
+ pub fn used ( & self ) -> usize {
69
+ // zlog("-- used 1 --\x00");
70
+ critical_section:: with ( |cs| self . heap . borrow ( cs) . borrow_mut ( ) . used ( ) )
71
+ }
72
+
73
+ /// Returns an estimate of the amount of bytes available.
74
+ pub fn free ( & self ) -> usize {
75
+ // zlog("-- free 1 --\x00");
76
+ critical_section:: with ( |cs| self . heap . borrow ( cs) . borrow_mut ( ) . free ( ) )
77
+ }
78
+
79
+ pub fn alloc ( & self , layout : Layout ) -> Option < NonNull < u8 > > {
80
+ // zlog("-- alloc 1 --\x00");
81
+ let res = critical_section:: with ( |cs| {
82
+ // zlog("-- alloc 2 --\x00");
83
+ let heap = & self . heap ;
84
+ // zlog("-- alloc 3 --\x00");
85
+ let heap2 = heap. borrow ( cs) ;
86
+ // zlog("-- alloc 4 --\x00");
87
+ let mut heap3 = heap2. borrow_mut ( ) ;
88
+ // zlog("-- alloc 5 --\x00");
89
+ let result = heap3. allocate_first_fit ( layout) ;
90
+ // zlog("-- alloc 6 --\x00");
91
+ result. ok ( )
92
+ } ) ;
93
+ // zlog("-- alloc 7 --\x00");
94
+ res
95
+ }
96
+
97
+ pub unsafe fn dealloc ( & self , ptr : * mut u8 , layout : Layout ) {
98
+ // zlog("-- dealloc 1 --\x00");
99
+ critical_section:: with ( |cs| {
100
+ self . heap
101
+ . borrow ( cs)
102
+ . borrow_mut ( )
103
+ . deallocate ( NonNull :: new_unchecked ( ptr) , layout)
104
+ } ) ;
105
+ }
106
+ }
107
+
108
+ unsafe impl GlobalAlloc for PIC < Heap > {
109
+ unsafe fn alloc ( & self , layout : Layout ) -> * mut u8 {
110
+ // zlog("-- GlobalAlloc alloc 1 --\x00");
111
+ self . get_ref ( ) . alloc ( layout)
112
+ . map_or ( ptr:: null_mut ( ) , |allocation| allocation. as_ptr ( ) )
113
+ }
114
+
115
+ unsafe fn dealloc ( & self , ptr : * mut u8 , layout : Layout ) {
116
+ // zlog("-- GlobalAlloc dealloc 1 --\x00");
117
+ self . get_ref ( ) . dealloc ( ptr, layout) ;
118
+ }
119
+ }
120
+
121
+ #[ cfg( feature = "allocator_api" ) ]
122
+ mod allocator_api {
123
+ use super :: * ;
124
+ use core:: alloc:: { AllocError , Allocator } ;
125
+
126
+ unsafe impl Allocator for Heap {
127
+ fn allocate ( & self , layout : Layout ) -> Result < NonNull < [ u8 ] > , AllocError > {
128
+ zlog ( "-- Allocator allocate 1 --\x00 " ) ;
129
+ match layout. size ( ) {
130
+ 0 => Ok ( NonNull :: slice_from_raw_parts ( layout. dangling ( ) , 0 ) ) ,
131
+ size => self . alloc ( layout) . map_or ( Err ( AllocError ) , |allocation| {
132
+ Ok ( NonNull :: slice_from_raw_parts ( allocation, size) )
133
+ } ) ,
134
+ }
135
+ }
136
+
137
+ unsafe fn deallocate ( & self , ptr : NonNull < u8 > , layout : Layout ) {
138
+ zlog ( "-- Allocator deallocate 1 --\x00 " ) ;
139
+ if layout. size ( ) != 0 {
140
+ self . dealloc ( ptr. as_ptr ( ) , layout) ;
141
+ }
142
+ }
143
+ }
144
+ }
0 commit comments