A few details based on Digic X / EOS R5 MPU firmwares (both internal MPU and grip MPU).Details on BG-R10 battery grip MPU UART:
https://www.magiclantern.fm/forum/index.php?topic=7531.msg242570#msg242570FirmwareFor Ghidra I got a better disassembly using ARM Cortex instead of ARMv7.
1st stage bootloader starts at 0x0. It is very small compared to ICU counterpart. Some small chunks of bootloader are copied to RAM before execution.
Then there's a usual cstart() (including copy of some data into RAM) which follows up to a "regular" DryOS.
Early init_task is similar, but differences start quickly.
Init task literally kickstarts everything by filling in interrupt handlers, msg queues, flags, semaphores, registering assert handler and then spawning a single MainTask.
MainTask is where all the other hardware init happens (including spawning all other tasks at once). When its done, it goes into a loop that handles messages from queue.
There's no functions like task_create, firmware calls "internal" kernel functions directly. So it is definitely a lightweit version of DryOS.
R5 firmwares runs DryOS 060+p8, like ICU.
New thing, visible on R5/R5 grip is DbgMgr. Firmware is much more verbose on UART. R/RP/R grip used uart_printf directly.
It seems a simplified form of DbgMgr from EOS firmwares. `DryosDebugMsg` call format is the same.
As said, is it very verbose now (this is UART output on R5):
MON>>> 94.063 : MATRIX ksout:2
94.071 : MATRIX ksin :2
94.650 : [LENS] kick-> 2
94.669 : [LENS] not kick-> 0
94.733 : [LENS] Event -> 2
94.742 : [!!LENS] CtrlEvent -> 5
94.761 : VBAT2Off VDD2Off
95.905 : [LENS] Event -> 0
95.924 : [LENS] waitTimer start
100.321 : AllTask InitComp
114.086 : powerSupply stop
114.105 : [STM] STM_STATE_T: -> SupplyOff
116.426 : ----9V req
117.336 : BATT INFO1 -> 4
117.344 : BATT INFO2 -> 0
117.478 : powerSupply stop
117.497 : [STM] STM_STATE_T: -> SupplyOff
151.749 : para2:1
197.445 : [!!LENS] timer comp-> 0
197.473 : [LENS] event Que Empty...
696.636 : Rcv ICU Cmd :COM_INIT
696.647 : Rcv ICU ID :0x00
696.655 : Rcv ICU DATA:0x00
696.758 : init PDIC_USB_DET = High
699.681 : ------------Startup Time Report------------
699.726 : NOT First run
699.815 : Lens OFF
699.860 : ICU RESET RELEASE [ 68 ms]
699.906 : Response COM_INIT_DATA_REQUEST [ 3 ms]
699.939 : -------------------------------------------
702.067 : Sw Rcv ICU Cmd :0x03
702.116 : Sw Rcv ICU ID :0x32
702.165 : Sw Rcv ICU DATA:0x00
702.266 : Sw Rcv ICU Cmd :0x03
702.273 : Sw Rcv ICU ID :0x32
702.281 : Sw Rcv ICU DATA:0x00
702.878 : Rcv ICU Cmd :COM_TIMER
702.984 : Rcv ICU ID :0x04
703.032 : Rcv ICU DATA:0x00
703.152 : Sw Rcv ICU Cmd :0x02
703.159 : Sw Rcv ICU ID :0x14
703.167 : Sw Rcv ICU DATA:0x00
704.864 : Sw Rcv ICU Cmd :0x02
704.872 : Sw Rcv ICU ID :0x14
704.880 : Sw Rcv ICU DATA:0x00
706.378 : Sw Rcv ICU Cmd :0x02
706.386 : Sw Rcv ICU ID :0x2E
706.394 : Sw Rcv ICU DATA:0x02
706.932 : Rcv ICU Cmd :COM_INFO
706.981 : Rcv ICU ID :0x12
707.134 : Sw Rcv ICU Cmd :0x02
707.183 : Sw Rcv ICU ID :0x14
707.292 : Sw Rcv ICU DATA:0x00
707.456 : Sw Rcv ICU Cmd :0x02
707.464 : Sw Rcv ICU ID :0x2E
707.471 : Sw Rcv ICU DATA:0x02
707.489 : Rcv ICU DATA:0x00
707.514 : Rcv ICU Cmd :COM_INFO
707.521 : Rcv ICU ID :0x31
707.529 : Rcv ICU DATA:0x00
707.539 : NOT exist WFT(default target 1)
812.484 : Rcv ICU Cmd :COM_INFO
812.492 : Rcv ICU ID :0x10
812.500 : Rcv ICU DATA:0xB4
816.857 : MPU_ERROR_HISTORY[4]:0x00
816.880 : MPU_ERROR_HISTORY[5]:0x00
816.888 : MPU_ERROR_HISTORY[6]:0x00
816.895 : MPU_ERROR_HISTORY[7]:0x00
816.903 : MPU_ERROR_HISTORY[8]:0x00
881.214 : Rcv ICU Cmd :COM_INFO
881.221 : Rcv ICU ID :0x12
881.239 : Rcv ICU DATA:0x00
1501.250 : Rcv ICU Cmd :COM_INFO
1501.262 : Rcv ICU ID :0x04
1501.270 : Rcv ICU DATA:0x1F
Not all messages are forwarded to UART, like on usual ICU DebugMgr.
HardwareIt is still the same Toshiba chip. It is a custom part made for Canon, based on TMPM440F10XBG.
The "official" chip has only Japanese datasheet, I asked Toshiba for English one and got a reply that there's no EN datasheet as chip is just for Japan market.
With some translator magic it is possible to get a pretty good translation of that datasheet.
Some important details:
Internal flash is at 0x0. Size 0x100000. A lot of it is unused.
RAM at 0x20000000, size probably 0xE000 - this seems to match the datasheet.
Extra RAM (!) at 0x22000000, size 0x200000 - this is Canon specific.
Devices sit at 0x40000000. Addresses so far doesn't match those in datasheet.
The ones found so far are in "hard fault" regions from datasheet. For ROM to boot into DryOS I had to map 0x4009xxxx, 0x400Bxxxx, 0x400Fxxxx.
0x400Bxxxx contains I2C bus(es?). On R5 one is used to talk to a charger - ISL9241.
0x400bxxxx read: a4dc(4) == 0
0x400bxxxx read: a4dc(4) == 0
0x4009xxxx read: a200 4
0x4009xxxx read: a100 4
0x4009xxxx write: a200 4 60
(9030000:03) <--enq cmd.dev=3,
(9030002:03) func=0,
(9030002:03) sync=1
(9030000:03) -->deq cmd.dev=3,
(9030002:03) func=0,
(9030002:03) sync=1
(1010000:01) drv_i2ccomm.c:496 eventWait Error ch =0
(1010000:01) drv_i2ccomm.c:497 eventWait Error ret=-2
0x400bxxxx read: a4dc(4) == 0
0x400bxxxx read: a4dc(4) == 0
0x400bxxxx read: a4dc(4) == 0
0x400bxxxx read: a4dc(4) == 0
QEMU 
In QEMU for ICU emulation we just replay MPU messages from a list. For some time now I wanted to try emulating MPU ROM in QEMU - if possible it should be easy to spawn two instances (one for MPU and one for ICU) and... let them just talk.
It took just two evenings to see some results.
https://github.com/kitor/qemu-eos/tree/eosmpu/hw/arm/eosmpu.cThis code (with a little help of gdb to skip ISL9241 i2c init) is able to boot firmware into DryOS and MainTask. It then stays waiting for other tasks to spawn, but since timers and interrupts are not yet implemented (as well as UART), it just waits forever.
In the log above prints with data in brackets are taken using GDB from DryosDebugMsg() calls.
(5030000:03) wakeup[0] 00000000
(5030000:03) wakeup[1] 00000000
(5030000:03) wakeup[2] 00000000
(5030000:03) wakeup[3] 00000000
(5030000:03) wakeup[4] 00000000
(5030000:03) wakeup[5] 00000000
(3030000:03) lens VBAT2 VDD2 Keep (0)
(30000:03) INITIAL
(20000:02) Grip exist judge OK
(9030000:03) <--enq cmd.dev=2,
(9030002:03) func=0,
(9030002:03) sync=1
(9030000:03) -->deq cmd.dev=2,
(9030002:03) func=0,
(9030002:03) sync=1
(9030000:03) <--enq cmd.dev=3,
(9030002:03) func=0,
(9030002:03) sync=1
(9030000:03) -->deq cmd.dev=3,
(9030002:03) func=0,
(9030002:03) sync=1