AVR with XRAM?

I have an ATMega128 which has 32k of external RAM; I use the GCC port of FreeRTOS using winAVR 2006*. I’d really like to use the XRAM for things like queues etc, as well as be able to use pvPortMalloc routines to allocate memory in this region. I believe I can do this relatively easily by using the __heap_start and __heap_end linker directives. However, I would like the stacks to remain in the internal memory of the AVR. Is there an easy way for  FreeRTOS to handle this? Would I have to generate an extra pvPortMalloc routine to allocate memory in the external memory (pvPortXRAMMalloc())? Or will FreeRTOS automatically allocate the stacks in the internal memory and the rest of the heap in the external memory? Cheers, Matt van de Werken.

AVR with XRAM?

Looking at the source of FreeRTOS, it seems that pvPortMalloc is not called in the taskcreate functions, although the documentation would indicate it is. The FAQ reads: "How is RAM allocated to tasks? To create a task the kernel makes two calls to pvPortMalloc(). The first allocates the task control block, the second allocates the task stack. Please read the memory configuration section of the API documentation for details of the allocation scheme. " I had interpreted this as the task creation allocates the entire stack inside the heap, however the source indicates that the stack is only referred to via pointers. So, when a task is created, the start (and end??) of the stack is retained in the (statically-allocated) heap, not the entire stack itself. So, the bottom line is I believe I am free to allocate as much heap in XRAM as I want, which will of course free up the internal ram for more stack space (to run more processes, etc). Please correct me if I am wrong, Cheers, Matt van de Werken.

AVR with XRAM?

Take a look at the line: pxNewTCB = prvAllocateTCBAndStack( usStackDepth ); in xTaskCreate().  This is where the stack and the task control block are allocated – it is within the task create function. This makes use of pvPortMalloc.  You should be able to set the memory pool used by port malloc to use your internal RAM.  If you then set your heap (allocated by the linker rather than the heap used by the kernel) to be in external RAM you could use the standard library malloc and free to allocated external memory, and pvPortMalloc/vPortFree to allocate memory from internal RAM. Regards.

AVR with XRAM?

Thanks Richard; I hadn’t looked into the xTaskCreate function in enough detail to realise it called pvPortMalloc indirectly. Your suggestion of using the libc malloc() and free() functions to allocate memory in the XRAM while setting the pvPortMalloc function to use internal RAM is a good one. I believe that a simple __malloc_heap_start and __malloc_heap_end directive on the linker command line should fix my problem. Am I right in assuming that the big array from which pvPortMalloc allocates memory lives in the .bss section? On a related note, the sizes of the .bss section and the .data section, they are quite large (total 3k between them – I have a whole stack of strings I haven’t moved into program space yet). Now, if the .bss section is where the task stacks are allocated, then I can surely let these grow to almost the entire memory space, minus the stack required for main() to start, I would guess. Is this a correct assumption? Cheers, Matt van de Werken

AVR with XRAM?

Thanks for all the suggestions, Richard; just to tie up all the loose ends, I had to adjust the linker options to get it all to work; it’s now working well (I managed to put .data in the XRAM along with the rest of the heap): Add the following lines to the Makefile:     LDFLAGS += -Wl,–section-start,.bss=0x800100               -Wl,–section-start,.data=0x808000               -Wl,–defsym,__malloc_heap_start=__data_end               -Wl,–defsym,__malloc_heap_end=0x80FFFF Note that the .bss start has to be explicitly defined, otherwise ld will stick it after the .data section, which is definitely not what we want (don’t forget that all the stacks for each process are allocated in .bss, which must therefore be in internal RAM).