| 316 | = Initializing the SOC without bootcode = |
| 317 | |
| 318 | |
| 319 | Booting is quite touchy, as there are quite some dependencies on even just getting the RAM and UART to work. In other words everything has to line up right before *anything* happens (easily) so it'll be tricky to bootstrap. The on-SOC ROM code does basic initialization, and searches for MLO code to get this initialization done. It can come from an SD card if it has an MBR and has a fat-formatted first partition (or other sources like UART). It is loaded into 128k of on-SOC RAM that is usable to do further initialization. One possible source of such MLO code is the so-called SPL build of U-Boot. It is just meant to be a small U-Boot that does initialization of the hardware, limited to 128kb, and then load the bigger U-Boot from MMC. |
| 320 | |
| 321 | The question is how to load RTEMS binaries without the help of an SD card. A very convenient and powerful setup is jtag, openocd and gdb, as Chris mentions above. However we want the target to be in a completely 'neutral' state, i.e. not be dependent on a particular loaded SD card with MLO on it. To accomplish this, one way is to initialize the SOC from JTAG (using openocd or gdb) so that after that the RAM is available, the uart clock is on, etc., and we can load and run RTEMS binaries. A clean solution would be, as happens for some other targets in openocd, to have an initialization sequence in the target config. |
| 322 | |
| 323 | I thought an 'easy' way to get started on finding a nice clean list of a minimal initialization sequence would be to record what U-Boot MLO does. Then perhaps decode all the addresses and find which ones are and aren't important to minimize the list. This is quite hard to do from within U-Boot itself because it takes quite along time, in short, before data works as you'd expect in a C program. |
| 324 | |
| 325 | However booting an SD-card with MLO and U-Boot on it from a qemu does let me record the i/o operations it does. I added this code to qemu: |
| 326 | |
| 327 | index aab4a31..2c357d1 100644 |
| 328 | --- a/memory.c |
| 329 | +++ b/memory.c |
| 330 | @@ -900,6 +900,18 @@ static uint64_t memory_region_dispatch_read(MemoryRegion *mr, |
| 331 | unsigned size) |
| 332 | { |
| 333 | uint64_t ret; |
| 334 | + uint32_t addroffset = addr, addrbase = mr->addr; |
| 335 | + |
| 336 | + if(size == 4) { |
| 337 | + fprintf(stderr, "mdw 0x%08lx ;# %s\n", |
| 338 | + addroffset + addrbase, mr->name); |
| 339 | + } else if(size == 2) { |
| 340 | + fprintf(stderr, "mdh 0x%08lx ;# %s\n", |
| 341 | + addroffset + addrbase, mr->name); |
| 342 | + } else if(size == 1) { |
| 343 | + fprintf(stderr, "mdb 0x%08lx ;# %s\n", |
| 344 | + addroffset + addrbase, mr->name); |
| 345 | + } else fprintf(stderr, "size %d??\n", size); |
| 346 | |
| 347 | ret = memory_region_dispatch_read1(mr, addr, size); |
| 348 | adjust_endianness(mr, &ret, size); |
| 349 | @@ -911,10 +923,23 @@ static void memory_region_dispatch_write(MemoryRegion *mr, |
| 350 | uint64_t data, |
| 351 | unsigned size) |
| 352 | { |
| 353 | + uint32_t addroffset = addr, addrbase = mr->addr; |
| 354 | + |
| 355 | if (!memory_region_access_valid(mr, addr, size, true)) { |
| 356 | return; /* FIXME: better signalling */ |
| 357 | } |
| 358 | |
| 359 | + if(size == 4) { |
| 360 | + fprintf(stderr, "mww 0x%08lx 0x%08lx ;# %s\n", |
| 361 | + addroffset + addrbase, (uint32_t) data, mr->name); |
| 362 | + } else if(size == 2) { |
| 363 | + fprintf(stderr, "mwh 0x%08lx 0x%08lx ;# %s\n", |
| 364 | + addroffset + addrbase, (uint32_t) data, mr->name); |
| 365 | + } else if(size == 1) { |
| 366 | + fprintf(stderr, "mwb 0x%08lx 0x%08lx ;# %s\n", |
| 367 | + addroffset + addrbase, (uint32_t) data, mr->name); |
| 368 | + } else fprintf(stderr, "size %d??\n", size); |
| 369 | + |
| 370 | adjust_endianness(mr, &data, size); |
| 371 | |
| 372 | if (!mr->ops->write) { |
| 373 | |
| 374 | and put the resulting commands in the reset-init hook of the openocd target config. I included the reads just in case the HW behaviour is affected by it. The list is unnecessarily long but I haven't bothered trimming it yet before I see it actually working. This gets very far in initializing the device. I can load an .exe now from gdb and the disassembly looks okay so I assume the RAM writing is working. But it has an exception on the first instruction. I haven't figured out why. I have seen hello.exe execute properly once so I'm sure it's close. |
| 375 | |
| 376 | Don't be confused by the u-boot banner being printed! This is a result of the u-boot spl (mlo) trace being executed very faithfully. After minimizing it should be a very small list if the other openocd configs are any indication. |
| 377 | |