Your understanding is basically correct.
But of course, we can come up with some nit-picking corrections!
the peripheral's controls and own registers are "mapped to memory" by the manufacturer and recorded in the device datasheet
Not all MCUs have "memory mapped" peripherals. Sometimes there is a special address space for the "IO registers" and special instructions for accessing them. 8051 comes to mind. (less and less common, BTW. Peripherals have gotten too large and too numerous to fit in the (usually much smaller, eg 256Bytes on an 8080) special address spaces, while memory address spaces have gotten bigger.)
they can be controlled by register access made easier with C code register access libraries routine tasks are implemented in Hal libraries for further abstraction.
There are at least three levels where "C makes it easier."
- vendor-provided definitions of names and data structures for the peripherals. (USART0->CTRLA = USART_DB8|...)
- low-level libraries for accessing them, provided by vendor or by 3rd parties. (ll_usart_init(USART0, usartInitStruct))
- high-level libraries for doing things (think "Arduino" or MBed.) (Serial.begin(115200))
the CPU directly communicates with the peripherals over the Bus/Bridge (acting as a translation layer) obeying wait and confirmation commands (important for slow peripherals).
Don't confuse "slow to access peripherals", where bus timing is likely to be controlled by the hardware, and "slow peripherals" (like a USART) where software will have to wait for various operations to complete.
their are placeholder error handling routines
Hmm. Maybe.
This is probably more of a carryover from operating systems where some simple flag means "one of many possible errors has happened.")
the CPU core language is defined by the ISA by the CPU designer (A revelation to me that assembly is an umbrella term for all the different instruction sets (or languages) from 8051 to X86, and not a standard its self)
Yes. Very important. There are a lot of commonalities to assembly languages, so that your 2nd and 3rd will be much easier to learn than the first, but...
the Compiler is mostly the concern of the CPU IP holder such as ARM and not the MCU manufacturer.
Note that the "CPU Designer" and "MCU Manufacturer" are sometimes the same company. (Used to be "frequently." Multiple MCU Manufacturers sharing a instruction set and compiler is a relatively recent thing, as are "CPU designers" that are separate from manufacturers. (Probably a good thing, since good compilers are so much work to create. (heh. "If we use this CPU architecure, we can just use the already existing gcc!" is lazy, common, and probably a good thing.)
Because the compiler, like the CPU, does not know about the peripherals and and the FLASH, RAM ect.. are also peripherals, the compiler needs a "linker file" so it knows where to put stuff;
That's one way to do it. Most (but not all) chips seem to specify the peripheral locations in .h files, rather than linker files.
the language that the compiler understands is defined by the C programming language standard.
It doesn't have to be C.
However, C is relatively easy to "port" to new CPUs, and ... gcc already exists for many CPU architectures.
Chips USED to come out with nothing but an assembler (and maybe not that), leading people to write their own languages. ("JAL" for PIC is an example. Assorted mutually-incompatible BASIC implementations. The original Mac OS was written in a flavor of Pascal.)
So a very determined person who knows C could write the code and program an MCU without any of the IDEs or libraries, as long as they had the compiler and the device datasheet.
Certainly. And there's always assembly language. Or even machine code.
I wrote my own 8085 assembler (sort-of) and can remember hand-assembling 1802 code to hex...
It would just be slow inefficient
Slow and inefficient for the programmer, perhaps. The code is likely to be faster and more efficient than most vendor-provided libraries.
There is also the start up code that the IDE config GUIs help generate to create boot up routines and initialise clocks/ peripherals correctly depending on use case.
This can also be written by hand, directly from the datasheet. Some modern CPUs are designed so that you can write code entirely with a high level language (usually C), without needing any machine or assembly code. I find it moderately amusing to note which ARM vendors provide asm vs C "startup code."
Alas, how much the startup code does can vary (whether or not clocks are set up there, or whether you need to do something else to configure them, seems particularly variable. (Perhaps because clock systems have become so complex.))
It's relatively interesting to have lived through the history of all of this.
- Here's a chip and a description of its instruction set. (~1975)
- Here's a chip, and we'll sell you a cross-assembler written in fortran that will run on your mainframe.
- Oh cool! Personal Computers!
- Here's a chip, and a cross assembler written in BASIC that might run on most PCs.
- Oh look! MIT/others have a X compiler that will run on your mainframe! Shareware! Freeware! OSSW!
- Someone ported a (C/BASIC/Pascal) compiler to CP/M! Only $$$!
- "Portable C compiler." "USCD P-System"
- Personal Computers with Hard Drives! (1984) Myriad 68000-based "unix" systems. (About the same time, more $$)
- GCC C compiler (68k: 1987, x86:1988)
- First C compiler for 8051: also 1988.
- First electrically eraseable mcirocontrollers: 1993
- First microcontroller (Atmel AVR) "designed for C": 1997
- First ARM microcontroller (ARM7TDMI): 1998
- First MIPS microcontroller (PIC32): 2007
- First Cortex ARM: 2004
(wow. It's been more years between the advent of "general purpose microcontrollers" than it was between the first microcprocessor and gcc! (Counting the advent of gcc as the start of wide-spread use of compiled HLLs in embedded systems.))