Keil compiles the project. If microlib is used, you can use malloc. A heap management module is located inside the micro-database. The memory size of the chip is fixed. The memory size is divided into global variables and allocated to the heap and stack. This is a general development method. However, during the development project process, the market encountered various problems. Stack penetration into the heap, or the heap is not large enough, which is quite annoying! Sometimes I think, why not share all Ram except the global variables with the stack? It is theoretically feasible because the stack is allocated from low to high, and the stack is allocated from high to low!
However, the heap allocation is determined by the _ heap_base and _ heap_limit labels. It cannot be changed without variables!
Because we use many chips, the RAM size of each chip may be different. However, smartos is pursuing cross-platform platforms and does not want to make too many settings for different chips. Previously, we have implemented the change of MSP to move the top stack to the top of the ram, so that the stack can be used as much as possible! But the heap is not good!
If heap_limit is too large to be allocated, an error will occur in small-capacity chips. Unable to help, I decided to analyze how the micro-database manages the heap.
First open the link address ing file linker address map generated after project compilation. Here we are smartosf0_debug.map Locate the symbol table segment global symbols _ Heap_base 0x200005a0 DATA 0 startup_0000f0xx.o (HEAP) _ Heap_limit 0x200005a0 DATA 0 startup_0000f0xx.o (HEAP) _ Initial_sp 0x200005c0 DATA 0 startup_0000f0xx.o (stack) The stack has been allocated.
Heap allocation uses the malloc function and finds it in the mc_p.l file of the Keil library. My directory is D: \ Keil \ Arm \ ARMCC \ Lib \ armlib
It's the turn of magic weapon IDA to go into the game. It's too simple to choose malloc. O. There are only malloc/free functions. The Assembly GUI is as follows:
IDA has no arm plug-in at hand. Otherwise, a F5 can get the C source code of malloc. Work hard to make money and sell arm plug-ins...
If there is no tool assistance, write it by yourself!
The above is a hand-written C code, which is annotated with the most original compilation method, and then gradually simplified and optimized. I have probably figured out the mechanism of malloc. The key point is to initialize it and use _ heap_limit. _ Heap_limit is compiled into flash as a constant and cannot be dynamically modified in the memory. There is no way, so you have to write code in bytes to replace it to initialize the entire heap. The initialization code I wrote is as follows:
The attached malloc/free code is incomplete. You can only understand its mechanism:
Void free (void * P) {If (! P) return 0; R3 = _ microlib_freelist; void * r2 = 0; P-= 4; void * R1 = * R3; // R1 = r3-> node while (R1) {If (r1> P) break; r2 = R1; R1 = * (R1 + 4 ); // R1 = R1-> next} If (! R2) R3-> node = P; else {R3 = * R2; r4 = p-R2; If (R4! = R3) * (r2 + 4) = P; else {P = * P; P + = R3 ;}} typedef struct {uint size; void * Next;} node; __microlib_freelist: node * _ freelist; __microlib_freelist_initialised: int _ freelist_initialised = 0; void * malloc (INT size) {/* R0 + = 0x0b; R0> = 3; r0 <= 3; */R1 = (size + 11) & 0xfffffff8; R7 = _ microlib_freelist_initialised; R6 = 0;/* r2 = _ microlib_freelist; If (! * R2 &&! * R7) */If (! _ Freelist &&! _ Freelist_initialised) {/* r2 = _ microlib_freelist; R0 = _ heap_base + 4; * r2 = R0; r2 = _ heap_limit; r2-= R0; r2 & = 0xfffffff0; * R0 = R2; * (R0 + 4) = 0; * R7 = 1; */_ freelist = (node *) (_ heap_base + 4); _ freelist-> size = (_ heap_limit-_ heap_base-4) & 0xfffffff8; _ freelist-> next = 0; _ freelist_initialised = 1;} // r2 = _ microlib_freelist; R0 = _ freelist; while (true) {/* R0 = * R2; If (! R0) {R0 = R6; break;} * // R0 = * R2; If (! R0) return 0; // R3 = * R0; R3 = R0-> size; If (R3 <= R1) break; // r2 = R0 + 4; // r2 = R0-> next; R0 = * (R0-> next);} If (R3 <= R1) {// R3 = * (R0 + 4 ); /* R3 = _ freelist-> next; * r2 = R3; */_ freelist-> size = R1; _ freelist = _ freelist-> next; Return &;} else {/* r4 = r3-R1; R3 = R0 + R1; R5 = * (R0 + 4); * R3 = R4; R3 + = 4; * (R3 + 4) = R5; R3 + = 4; r3-= 8; // minus 8 to get back to R3 */node * lst = (void *) _ freelist + R1; lst-> size = _ freelist-> size-R1; lst-> next = _ freelist-> next; _ freelist-> size = R1; _ freelist = lst; Return & lst-> next;} return R0 ;}
End.
|
Turn stone brother |
Automatically Set the heap size when using the microlib of Keil-the most difficult to use for Embedded Systems