2009-04-19 09:45 AM
Reserving fixed memory space for bit banding flags
2011-05-17 04:09 AM
I would like to reserve 16 bytes at the beginning of the RAM area (0x20000000 to 0x20000010) where I can be sure that the compiler will not use to store any variable.
Does anyone know how to do this simply? These location will then be used to store flag bits using bit banded read/writes. For example, I would like to be able to just write 1 to address 0x22000000 in order to set the first bit of the word at 0x20000000. When looking at dissasembly code, I noticed that the bit banding example code takes a lot of instructions to determine the address for a given bit. This makes flags handled via bit banding to actually be very inefficient. Thanks2011-05-17 04:09 AM
Which tool chain are you using?
This is usually done with linker options. You can use linker option to make sure certain part of memory is not used. There are some additional information in here http://www.keil.com/support/man/docs/armcc/armcc_cjaebife.htm2011-05-17 04:09 AM
Using IAR:
#pragma location=0x20000000 __no_init volatile char reserved[16]; That's what my IAR help says. I haven't tried it though. You might have to reserve that space in the linker control file. JJS2011-05-17 04:09 AM
Thanks. I am using RIDE (GNU tools).
Where would I place the #pragma location=0x20000000 ... I tried inside main() and outside main() (as a global) but that didnt work.2011-05-17 04:09 AM
That does not work for GCC. The conventional way is to place the variable(s) in a separate section (with the section attribute, check the manual) and place that section at the appropriate address in the linker script or on the command line.
However the bit-banding address calculations should be performed at compile-time if used correctly. Are you using the macros with non-constant parameters? It might be simplest to do something like the following (untested). uint32_t flags_storage[(NFLAGS+31)/32]; static uint32_t* const flags = (uint32_t*)(((uint32_t)flags_storage - SRAM_BASE) * 32 + BB_SRAM_BASE); And access the flags with flags[flag_number]. It is not necessary to have flags_storage at a fixed location if you don't need to.2011-05-17 04:10 AM
In ARM Application note 179, there is a bit band example using C macros.
Could you try using that to see if it generate run time code? (http://infocenter.arm.com/help/topic/com.arm.doc.dai0179b/AppsNote179.pdf)2011-05-17 04:10 AM
I ended up creating a section of 16 bytes that I keep unused. See listing at end. The code goes in the sections_FLASH.ld file.
Regarding the bit banding code, what you show is what I have right now. However, when tracing in dissassembly, I see that all these operations are taking place at runtime, so there are a lot of assembly instructions for just setting a bit. I will be using *(vu32 *) FLAG1 = 1; where FLAG1 is a hard definitions like RAM_BB_BASE+1. This take only 3 assembly instructions and resembles more the BSET, BCLR common of the simple but efficient MCUs like the ST7 .flags : { . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _sflags = .; . = . + 16; . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _eflags = . ; } >RAM2011-05-17 04:10 AM
cosmapa:
You're right, it can't be done as I wrote since C doesn't allow anything other than adding or subtracting an integer from the address of flags_storage when calculating the initializer for flags. A rather stupid limitation, but that's the way it is. So, because of the multiplication, flags must be a define, and all calculations made at runtime (the optimizer could be smarter). Of course the symbol 'flags' could be defined in the linker script with the calculations done there, but that would provide little benefit over your solution.2011-05-17 04:10 AM
joseph:
That example does not generate run time calculations, because the target addresses are hard coded. The ''problem'' arises when you want to bit-band access a regular variable.