Hi,
Is there any way to get information about stack and heap at runtime in a C function? I'm looking for a var/table/way to get Stack_Base, Heap_base, Stack_limit and heap_limit at runtime.
That's because I'm trying to make a very very small multitasking kernel for Cortex-M3 and I need somehow to know the Stack memory avail for my alloc routines.
Regards,
Christos Houtouridis, Electrical Engineer
And even if I dont understand how this thread became a discussion about kernel development
How could it possibly avoid to be? What you're asking about is kernel development, after all.
But since you seem to have only listed quite a number of features your kernel doesn't have, but hardly any that it does, that makes it hard to get a feel for what kind of kernel development it is.
But.... CCARM has
Just in case: that name appears mispelled, and the nearest correct spelling would be sign of trouble. CARM is a long since discontinued compiler for ARM. These days you should be using the RealView compiler, a.k.a. armcc.
I also have to tell you that I'm Electrical Engineer and not a software engineer.
Then seriously, please get yourself one to help you out. Or just use one of the existing RTOSes instead of rolling your own. Designing an RTOS kernel, even a little one, takes some rather special expertise that your line of education most likely didn't provide. Nor can that expertise be fully replaced by internet advice.
Just in case: that name appears misspelled, and the nearest correct spelling would be sign of trouble. CARM is a long since discontinued compiler for ARM. These days you should be using the RealView compiler, a.k.a. armcc.
Yes you're right. It's armcc and not ccarm. Sorry.
And yes my kernel will be very small and I also avoid features in the previous post. But It's a forum post. What should I wrote?
Anyway. Is there any way to retrieve the place and size of the stack (and heap), that initially ARMCC placed in RAM? This is the same technique a UNIX-like kernel does when loads the RAM info from BIOS at boot time, in order to init the virtual page allocator and the kernel's free range list. I want to do the same thing but with a simpler allocator and with a smaller portion of ram. I will leave the globals and the compilers loading mechanism out.
In startupxxx.s there is Stack_Mem, Stack_Size etc but i don't know how to get their values. I also found struct __initial_stackheap{ unsigned heap_base, stack_base, heap_limit, stack_limit; }; But i didn't figure out how to fill it without re-init the stack and heap.
Christos Houtouridis
PS: I should probably publish my project after and also post here the link.
There are no ARMCC that magically place any initial stack or heap into RAM.
There is a startup file, where _you_ specify stack size and heap size.
Next thing - a task for small embedded processors are normally threads - not processes. So they don't allocate any memory for any global variables. All threads share the same global memory - each thread then have own stack space for auto variables.
And you - who implement tasks - can implement solutions for thread-local storage, i.e. for a function call or a global pointer to point at memory reserved for this specific thread. And when you do a task-switch, you remap so another task asking for thread-local storage gets a pointer to different memory.
Next thing: It doesn't matter what compiler you have. When _you_ implement this kernel, then _you_ need to implement a function similar to:
create_thread(tread_function_ptr, stack_pointer,stack_size)
and let stack_pointer point to a global block of RAM (statically or dynamically allocated).
Or you can skip the parameter "stack_pointer" and just supply a "stack_size" parameter - and then let the kernel _you_ write perform the allocation.
So turn it anyway around: It is still _you_, the user of your kernel, that must specify how much stack space each task needs. And you, the user of the kernel, who have to specify how large heap to have. Or implement a different solution instead of malloc()/new - especially since malloc() and new both suffer from potential memory fragmentation. Having 20kB free space on the heap doesn't mean that the 20kB are a single, continuous, block. It can just as well be 10 small 2kB blocks or one 10kB block and 100 blocks of 100 bytes each.
So we are discussing design of kernel functionality just because it is _you_ (or a consultant you pay) who have to implement the functionality you are requesting. But only after you have first managed to set together a specification for how it is expected to function.
A common way to have threads is to have:
uint64_t main_stack[MAIN_STACK_SIZE/8]; uint64_t io_stack[IO_STACK_SIZE/8]; uint64_t alarm_stack[ALARM_STACK_SIZE/8]; void main_task(void) { ... } void io_task(void) { ... } void alarm_task(void) { ... } void main(void) { os_init(); os_start_task(main_task,main_stack,MAIN_STACK_SIZE); os_start_task(io_task,io_stack,IO_STACK_SIZE); os_start_task(alarm_task,alarm_stack,ALARM_STACK_SIZE); os_start_scheduling(); // Doesn't return - starts slicing time between available tasks. }
Dear Per,
For start I have to say that I agree with both of your messages. It is exactly how you describe it. Now. You said "There is a startup file, where _you_ specify stack size and heap size"
And this is the reason I need to pass this _user_demand_ to my kernel. I dont want to specify the avail RAM sizes in two places both the startupxxx.s and in some xxconfig.h header. I need to know how much memory the _user_ (probably me again) decide to left for stack/heap in the startupxxx.s. So my kernel will read this information and do its magic. That's why I ask for a way to read the Stack_base etc...(the labels used in the startup file).
Of course there are ways like "read the SP just after the system init" or "do a search using exception handler", or even "do specify eventually RAM sizes and addresses in two places", but I seek for a much more elegant way.
I have to say that this is not the first time i make my own kernel. I have made one for x86. It is just the first time that i build something so freaking small. And I will make it a small module to use it beside any "my-kernel-compatible" project.
Again - you don't seem to have read the above comments very well - there is no real advantage in having a configuration indicating the amount of memory avail to the kernel. Now rewind, read this sentence once again (exit infinite loop). You don't need this if you allocate all the memory you need in compile time - end of discussion. What is the problem?
Dear Tamir,
There is no problem with that. I just want to avoid the "compile time alloc" thing. Of-course if I can not find a solution i'll use something like that
uint8_t kstack_privil[KERNEL_PRIVILEGED_STACK_SIZE]; uint8_t kstack_unprivil[KERNEL_UNPRIVILEGED_STACK_SIZE];
And I'll make the allocator to give stack slices from these tables.
Christos.
You can always allocate memory from the heap. But remember that systems that are built using such a kernel will require the have heap space allocated as well.