For embedded applications, it is often necessary to access fixed memory locations for peripheral registers. The standard way I have found to do this is something like the f
Your linker handles the placement of data and variables. It knows about your target system through a linker script. The linker script defines regions in a memory layout such as .text
(for constant data and code) and .bss
(for your global variables and the heap), and also creates a correlation between a virtual and physical address (if one is needed). It is the job of the linker script's maintainer to make sure that the sections usable by the linker do not override your IO addresses.