I think you missed the point. MCU's are quite complex if you expect to just run any code on any one. Just look at the arduino libraries, I dunno, take analogueRead, Ahh what a pile of poo, why? it totally dumbs down the whole thing and ignores lots of the ADC's functionality. Micro controllers do have a lot of hidden little features that can be very powerful, but most programmers think they are still programming PC's, and so you get the sort of mess that all of these HAL systems are. Actually writing code that can be separated from the hardware comes with penalties and is one hell of a job to do.
If you take a random modern (<1 year old) PC and a similar MCU, or just pick the most complex MCU you can find. Layout the FULL specification of all the hardware components....
Consider that the PC contains several dozen MCUs, ASICs, DSPs before we even begin. So you would need to start with the hardware and bus specs for all of those.
By the time you were done, the documentation pile for your MCU would be about 2 inches high. The documentation for the PC would be 6 feet high.
Now consider that the PC is one of about a billion and the largest single instance count would cover less than 10% of them (probably a Dell Optixplex). So there over half a billion different hardware combinations. Different cards, different memory types, different CPUs, different bus controllers... etc. etc. etc.
So, to write a baremetal application for a modern PC platform is going to involve a LOT of sleepless nights.
Don't get me wrong it can be done. I have personally got it (bare metal code) to boot all the way up into 64bit mode, establish MMU TLBs etc. Yada Yada and was about to start with initing the bus master to access the UART, just like an MCU (well not quite). However. Alas. I ran out of time and motivation.
While it is honestly a reach to compare MCU software and "big iron" software they do collide everywhere. In big iron land we call the part which interfaces with the hardware the "Driver" which is usually a "plugin" component within a layer of the "HAL" in the OS. "Drivers" basically take what the HAL passes them and translates that into the specifics of the hardware. The premise that this layer must be a "facade" or simplification of what that driver (and thus hardware supports) is false for almost any modern OS there are provided ways to pass "extension" data or calls to support. All of the various datastructures have extensibility in mind. Nobody likes drivers that fail with each and every hardware micro update or every OS micro-update. They are designed to be tolerant, but strict and failsafe, ie, not throwing crap back at the hardware or the OS when IT screws up.
Of course the "other end" of that driver communications channel, the way it talks to hardware usually requires other OS functionality to "facilitate and mediate" given there are possibly hundreds of other threads/processes competing. But, ultimately it will end up leaving some from of bus interface IC on the PCB card, or whatever, and become SPI, UART, I2C or whatever. It might even involve an MCU and it will have firmware written for it. Most likely forming a "Driver Version<->Firmware Version" compatibility matrix. Which becomes complex when you want to support multiple "platform".
Here we collide.
For everyones sanity, we keep those people, the driver, os and firmware folks, in a separate room... ideally a separate building.
On terminology there are actually specific academic definitions for a lot of terms people just throw around as proxy of each other.
Quiz: Arduino. Is it a library? A platform? A framework? A pattern? A facade? An abstraction? An eco-system?
BTW. IMHO the only "software engineering" I have ever seen in MCU land has been Arduino **** and STM32 LL and HAL components. Coding != software engineering.