Static implies the variable is both isolated to that file/function/area of code. The place where it is defined it is both only visible there and when used on non-globals essentially turns that variable into a global from a storage perspective. A local variable with a static definition means I want to not lose that value from one call of this function to another, so it has to be stored globally for that function, normally a local variable is on the stack so the function can be re-entrant (a new copy of the local variables for every entry into the function). So static globals are global anyway, static locals are local but stored along with the globals. In what is often called .data but toolchains may have different names. This is basically the ram/memory (read/write) where your other globals are stored or where variables that are initialized when defined
int x = 7;
are stored. Global variables or static locals that are not initialized when defined
int y;
are in what is often called .bss. This is another chunk of read/write memory, but this memory before starting main() is zeroed for you so that per the spec or per assumption those variables are zero when your program starts.
const is a way of saying I am declaring this as a read only variable, I dont plan on every storing to it just reading from it. So the compiler may choose (actually it is the programmer as they ultimately dictate what the linker does, often letting the default linker script be used and not taking over that job) whether that goes to flash or ram, it can go either place and work just fine.
For microcontrollers and other places where you need to boot and start running from non-volatile memory (flash/rom/etc). First off the program itself has to be stored in something non-volatile. Next the .data stuff, things that you initialized in your code when defining the variable, stuff that at compile time can be determined. has to also be in non-volatile storage, but that data is read/write ultimately so the bootstrap code that runs before main() is called, does the job of copying the .data blocks to read/write memory. The .bss code or global or static local variables that are not initialized and assumed to be zero when you start, those do not need non-volatile storage, just the location and how much does, and from that the bootstrap can zero that read/write memory.
There are reasons why we communicate using terms like .text, .data, .bss, .rodata, etc. Because we see that the tools place elements of our program into those places and then we can see where those places have to live in non-volatile storage and then during runtime if that is different. .text although goofy, is our program, the machine code and other associated data. .data is variables from our program that are initilized before starting to be non-zero so they have to be stored in non-volatile storage then moved to read/write before using them. .bss is variables from our program that are assumed to be zero when we start, so the amount and location needs to be stored in non-volatile and the boostrap can do the zeroing (or sometimes they are just stored as a bunch of zeros in the flash/rom as well). .rodata is sometimes separate it is the consts sometimes the consts are found in .text, .text and .rodata are considered to be read-only so they can remain in flash if your product can handle that (newer flashes have read-disturb problems so outside the flash on a microcontroller you dont necessarily want to do that, you have to be careful) or they can be copied to ram as well.
Then there are the terms heap and stack, which often after your program if needed, .bss and .data consume some amount of ram, often from the lower addresses up. then the rest of that ram is divided up into heap and stack, sometimes without a solid line between them, ill behaved programs can have the heap and stack collide causing a crash. stack is often top down and heap is often bottom up, but these are not hard and fast rules.
Where are these on your board? well it depends both on the chip and the board as to what the options are then ultimately it is up to you the programmer to decide as you control the compile and linking process. Most folks get an example or a toolchain that knows about your system and you leave the default settings. But you are utimately responsible. For a microcontroller to boot you have to have a way to do that, usually that is a flash on or off chip depending on the mcu, and the above mentioned non-volatile stuff has to be stored there or in some other non-volatile place. Likewise you have some ram, you have to divide that up with the read/write things you need including stack and heap if you are brave enough to use it in such a system (not wise). Some processors the stack is part of the design and you dont have to worry about, others you do. If you have multiples of these things, non-volatile or read/write ram then great you can pick and choose where to put things.
if you use a toolchain from someone, or have access to different ones there is no reason to assume they will do the exact same thing with your program with their default linker script. usually toolchains provide map files or other ways to see where they have placed things for you.
it is certainly possible to have a microcontroller based system with no flash, every hear of a mouse or keyboard? Some of the along with many other products can work without such things. Some may for example have in the logic of the chip to manage the usb enumeration, then the operating system driver for that product contains the firmware, downloads the firmware to ram on the device, and starts the processor and perhaps re-enumerates the usb so that it is now a mouse or whatever. not everyone does it but it is done sometimes. Likewise you may have some other design where some other hardware or solution downloads the program into the chip/ram before starting the processor effectively making it feel like that processor has no flash. But you still have the same .text, .data, .bss concepts and the program you run be it ram only still was compiled down into program, zero init data, and non-zero init data and the linker had to be told where to place these things in the binary and patch up the code to know where the linker had placed the variables it needs to use.