GCC Code Coverage Report


Directory: ./
File: firmware/controllers/lua/lua_heap.cpp
Date: 2025-11-16 14:52:24
Coverage Exec Excl Total
Lines: 100.0% 7 0 7
Functions: 100.0% 1 0 1
Branches: 100.0% 4 0 4
Decisions: 100.0% 4 - 4

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "rusefi_lua.h"
4
5 #if EFI_LUA
6
7 #include "lua.hpp"
8 #include "lua_heap.h"
9
10 #if EFI_PROD_CODE || EFI_SIMULATOR
11
12 #ifndef MCU_HAS_CCM_RAM
13 #define MCU_HAS_CCM_RAM FALSE
14 #endif
15
16 #ifndef LUA_EXTRA_HEAP
17 #define LUA_EXTRA_HEAP 0
18 #endif
19
20 #if (LUA_EXTRA_HEAP > 0)
21 CH_HEAP_AREA(luaExtraHeapArea, LUA_EXTRA_HEAP)
22 #ifdef EFI_HAS_EXT_SDRAM
23 SDRAM_OPTIONAL
24 #endif
25 ;
26 #endif
27
28 class Heap {
29 public:
30 memory_heap_t m_heap;
31
32 size_t m_size = 0;
33 uint8_t* m_buffer = nullptr;
34
35 void* alloc(size_t n) {
36 if (m_buffer && m_size) {
37 return chHeapAlloc(&m_heap, n);
38 }
39
40 return nullptr;
41 }
42
43 void free(void* obj) {
44 chHeapFree(obj);
45 }
46
47 public:
48 template<size_t TSize>
49 Heap(uint8_t (&buffer)[TSize])
50 {
51 init(buffer, TSize);
52 }
53
54 Heap()
55 {
56 init(nullptr, 0);
57 }
58
59 void init(uint8_t *buffer, size_t size) {
60 criticalAssertVoid(used() == 0, "Too late to init Lua heap: already in use");
61
62 m_size = size;
63 m_buffer = buffer;
64
65 reset();
66 }
67
68 size_t size() const {
69 return m_size;
70 }
71
72 size_t used() {
73 if (size() == 0) {
74 return 0;
75 }
76
77 size_t heapFree = 0;
78 size_t lagestFree = 0;
79 chHeapStatus(&m_heap, &heapFree, &lagestFree);
80
81 return m_size - heapFree;
82 }
83
84 // Use only in case of emergency - obliterates all heap objects and starts over
85 void reset() {
86 if (m_buffer && m_size) {
87 chHeapObjectInit(&m_heap, m_buffer, m_size);
88 }
89 }
90 };
91
92 // see [tag:multi-step-lua-alloc] below
93 // this is a bit over-complicated at the moment, one argument would be that this supports multi-region RAM use-case
94 #if (LUA_EXTRA_HEAP > 0)
95 // Optional SDRAM
96 static Heap luaExtraHeap(luaExtraHeapArea);
97 #endif
98
99 #if defined(STM32F4)
100 // Optional RAM3 exist on STM32F42x
101 static Heap luaOptionalHeap;
102 #endif
103
104 #if MCU_HAS_CCM_RAM
105 // CCM RAM leftovers on STM32F4xx
106 static Heap luaCcmHeap;
107 #endif
108
109 void luaHeapInit()
110 {
111 // stm32f4xx can have optional ram3 region
112 #if defined(STM32F4)
113 // Some boads can be equiped with STM32F42x only, in this case we allow linker to take care of ram3
114 #if !defined(EFI_IS_F42x)
115 // cute hack: let's check at runtime if you are a lucky owner of board with extra RAM and use that extra RAM for extra Lua
116 // we need this on microRusEFI for sure
117 // definitely should NOT have this on Proteus
118 // on Hellen a bit of open question what's the best track
119 if (isStm32F42x()) {
120 // This is safe to use section base and end as we define ram3 for all F4 chips
121 extern uint8_t __ram3_base__[];
122 extern uint8_t __ram3_end__[];
123 luaOptionalHeap.init(__ram3_base__, __ram3_end__ - __ram3_base__);
124 }
125 #endif // !EFI_IS_F42x
126 #endif // STM32F4
127
128 // stm32f4xx have CCM memory that may have some leftovers
129 #if MCU_HAS_CCM_RAM
130 extern uint8_t __heap_ccm_base__[];
131 extern uint8_t __heap_ccm_end__[];
132 luaCcmHeap.init(__heap_ccm_base__, __heap_ccm_end__ - __heap_ccm_base__);
133 #endif
134 }
135
136 static size_t luaMemoryUsed = 0;
137
138 void* luaHeapAlloc(void* /*ud*/, void* optr, size_t osize, size_t nsize) {
139 void *nptr = nullptr;
140
141 if (nsize) {
142 // [tag:multi-step-lua-alloc]
143 // First try dedicated Lua heap(s)
144 #if (LUA_EXTRA_HEAP > 0)
145 if (nptr == nullptr) {
146 nptr = luaExtraHeap.alloc(nsize);
147 }
148 #endif
149 #if defined(STM32F4)
150 if (nptr == nullptr) {
151 nptr = luaOptionalHeap.alloc(nsize);
152 }
153 #endif
154 #if MCU_HAS_CCM_RAM
155 if (nptr == nullptr) {
156 nptr = luaCcmHeap.alloc(nsize);
157 }
158 #endif
159
160 // [tag:multi-step-lua-alloc]
161 // then try ChibiOS default heap
162 if (nptr == nullptr) {
163 nptr = chHeapAlloc(NULL, nsize);
164 }
165 }
166
167 if (nptr) {
168 luaMemoryUsed += nsize;
169 }
170
171 if (optr) {
172 chDbgAssert(osize <= chHeapGetSize(optr), "Lua lost track of allocated mem");
173 // An old pointer was passed in, copy the old data in, then free
174 if (nptr != nullptr) {
175 memcpy(nptr, optr, osize > nsize ? nsize : osize);
176 }
177 // chHeapFree will find correct heap to return memory to
178 chHeapFree(optr);
179 luaMemoryUsed -= osize;
180 }
181
182 if (engineConfiguration->debugMode == DBG_LUA) {
183 engine->outputChannels.debugIntField1 = luaHeapUsed();
184 }
185
186 return nptr;
187 }
188
189 size_t luaHeapUsed()
190 {
191 return luaMemoryUsed;
192 }
193
194 void luaHeapReset()
195 {
196 #if (LUA_EXTRA_HEAP > 0)
197 luaExtraHeap.reset();
198 #endif
199 #if defined(STM32F4)
200 luaOptionalHeap.reset();
201 #endif
202 #if MCU_HAS_CCM_RAM
203 luaCcmHeap.reset();
204 #endif
205
206 luaMemoryUsed = 0;
207 }
208
209 #if CH_CFG_MEMCORE_SIZE == 0
210 extern uint8_t __heap_base__[];
211 extern uint8_t __heap_end__[];
212 #endif
213
214 void luaHeapPrintInfo() {
215 size_t chMemTotal =
216 /* Chibios heap size */
217 #if CH_CFG_MEMCORE_SIZE == 0
218 (__heap_end__ - __heap_base__);
219 #else
220 CH_CFG_MEMCORE_SIZE;
221 #endif
222 auto totalHeapSize =
223 chMemTotal +
224 #if (LUA_EXTRA_HEAP > 0)
225 luaExtraHeap.size() +
226 #endif
227 #if defined(STM32F4)
228 luaOptionalHeap.size() +
229 #endif
230 #if MCU_HAS_CCM_RAM
231 luaCcmHeap.size() +
232 #endif
233 0;
234
235 if (totalHeapSize) {
236 auto memoryUsed = luaHeapUsed();
237 float pct = 100.0f * memoryUsed / totalHeapSize;
238 efiPrintf("Lua total heap(s) usage: %d / %d bytes = %.1f%%", memoryUsed, totalHeapSize, pct);
239 } else {
240 efiPrintf("No heap available for Lua");
241 }
242
243 #if (LUA_EXTRA_HEAP > 0)
244 efiPrintf("Lua extra heap usage: %d / %d", luaExtraHeap.used(), luaExtraHeap.size());
245 #endif
246 #if defined(STM32F4)
247 efiPrintf("Lua optional heap usage: %d / %d", luaOptionalHeap.used(), luaOptionalHeap.size());
248 #endif
249 #if MCU_HAS_CCM_RAM
250 efiPrintf("Lua CCM heap usage: %d / %d", luaCcmHeap.used(), luaCcmHeap.size());
251 #endif
252
253 size_t chHeapFree = 0;
254 chHeapStatus(NULL, &chHeapFree, NULL);
255 /* total available for ChibiOS minus left free, plus free in Chibios Heap */
256 size_t chMemCoreUsed = chMemTotal - chCoreGetStatusX() - chHeapFree;
257 efiPrintf("Common ChibiOS heap: %d bytes free", chHeapFree);
258 efiPrintf("ChibiOS memcore usage: %d / %d", chMemCoreUsed, chMemTotal);
259 }
260
261 #else // not EFI_PROD_CODE
262 // Non-MCU code can use plain realloc function instead of custom implementation
263 207621 void* luaHeapAlloc(void* /*ud*/, void* ptr, size_t /*osize*/, size_t nsize) {
264
2/2
✓ Branch 0 taken 112112 times.
✓ Branch 1 taken 95509 times.
2/2
✓ Decision 'true' taken 112112 times.
✓ Decision 'false' taken 95509 times.
207621 if (!nsize) {
265 112112 free(ptr);
266 112112 return nullptr;
267 }
268
269
2/2
✓ Branch 0 taken 89445 times.
✓ Branch 1 taken 6064 times.
2/2
✓ Decision 'true' taken 89445 times.
✓ Decision 'false' taken 6064 times.
95509 if (!ptr) {
270 89445 return malloc(nsize);
271 }
272
273 6064 return realloc(ptr, nsize);
274 }
275 #endif // EFI_PROD_CODE
276
277 #endif // EFI_LUA
278