Hacker News new | past | comments | ask | show | jobs | submit login

On physical hardware, it helps a lot to have at least one simple GPIO which you can control by writing to a memory location or I/O port, or even better a UART output.

Then you can toggle the GPIO output to see if some code was reached and/or a condition was met.

If you have subroutines (or macros if you don't have a stack, or use a register to hold the return address), you can toggle a GPIO repeatedly to output characters, doing a UART in software if you don't have one already on the chip.

It's a lot like "printf" debugging. You repeatedly compile and run the boot code, testing how it went using this basic output.

To run the boot code might need a tool that lets you load it into memory beforehand.

Some boards will only have flash EEPROM to boot from. There you run the boot code by repeatedly flashing your code into it. Until your CPU is running useful software, the flashing tool runs outside the chip you're coding for.

Typically it doesn't take a large number of efforts to get something useful running.

But to boot up fully, there might be tricky or subtle issues around initialising clocks, PLLs, even voltages, enabling a cache, switching from cache-as-RAM to using external RAM, initialising DRAM, bus signal training, negotiating protocols with other devices, that sort of thing. Some CPUs boot into a special state where some features don't work normally yet, a state that only exists during boot. Some are executing direct from flash, slowly, and need RAM initialised before they can start running from it.

That kind of stuff is very similar to writing device drivers: There may be "mystical incantations" with magic numbers and particular instruction sequences, that you just have to find out from somewhere because they aren't obvious, or even because trial-and-error doesn't guarantee you reliable behaviour. For example some PLLs require a set of magic values to be loaded into registers. You could find the values experimentally, but you wouldn't have the same behaviour guarantees in all environmental conditions that you get from using values from the manufacturer.

In practice, most boards come with a "BSP" (board support package) already from the manufacturer, so the tricky essentials are done already. Also, many of them have a boot loader which can "chain" to a second bootloader, which you can write or change as you wish without having to get the chip initialisation right, and sometimes you can load the second bootloader into RAM with an external tool, or over a UART, so no flashing required.

There is also simulation. Many CPUs have simulators, so you can debug the boot loader step by step, stop it and inspect the program state, much like any other program. However, some simulators only simulate a device after the tricky stuff mentioned above is done and the CPU+memory is running "normally". The early boot state might not be simulated accurately or at all.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: