I recently started by going through the tutorials at: http://www.valvers.com/open-software/ra ... g-in-cpt1/
. I've seen this link in several places on this forum.
At the end of those tutorials, the author indicates that the next thing is to setup J-TAG to avoid plugging/unplugging the SDRAM card. Instead of that, I recommend writing a bootstrap loader that boots the CPU, but then can accept a generic program image via the UART which can then be executed. So the SDRAM card only contains the bootstrap loader. The bootstrap loader initializes the UART so that you can communicate via a Terminal program (such as TeraTerm). After booting, it displays a boot message and accepts the following ASCII commands:
1. "A" - Prompt for a hex value and set the address pointer to the value returned from the prompt
2. "R" - Read the byte pointed to by the address pointer, display it on the terminal, and auto-increment the address pointer
3. "W" - Prompt for a byte and write it to the address pointed to by the address pointer and auto-increment the address pointer
4. "G" - Create a function pointer that points to the address pointed to by the address pointer and call that function pointer. When that function "returns" it will return back to the bootstrap loader which will be ready to accept the next command.
This very basic peek/poke machine should allow you to load/run very simple sequences of instructions. Next, I added support for a command that reads and processes Intel Hex records. Those records start with the ":" character, so that's the "command" for my bootstrap loader. After receiving the ":" command, process the rest of the hex record. (dwelch has an example of this in some of his bootstrap loaders) This allows you to compile/link code to an address range and generate Intel Hex records for that program. Then you can use your Terminal software to send the series of Intel Hex records to your Pi. Those records will also contain an entry point, so when you receive that record, set the address pointer (from above) to that address so that when the hex records have all been sent, you can just use the "G" command to execute the program that you just loaded.
This will allow you to debug and develop your new code. If/when something goes wrong, just cycle power which will get you back to your bootstrap loader again.
This also allows you to write "utility" programs that do a small task, then return back to the bootstrap loader so that you can perform some other task such as loading/executing a different program. One useful "utility" program would be to prompt for an address and length, then dump that range of bytes (16 bytes per row, followed by the ASCII representation of each byte if it is a printable character). Now you have a memory inspector utility.
Teaser - Once you are able to process Intel hex records, if you need to load very large code images, you could create a utility program (loaded via hex records) that understands how to perform an X-modem data transfer which will be much faster.
Finally, my bootstrap loader required that I have some functions available for getting a character from the terminal, printing a character to the terminal, printing a null terminated string, printing a hex value to the terminal etc..... Those functions are typically required by all of my utility programs. Therefore, I created a "Jump table" in my bootstrap loader with jump instructions to each of those utility functions. If I link the jump table to a fixed address (such as the fixed address that the Pi boots to), I can use those functions in my utility programs without having to have them in the utility program image. Just tell the linker their address in the jump table so that when the utility program calls "OutString" (for example), the linker inserts the address of the jump table entry that jumps to the OutString function in the bootstrap loader image. When OutString() is done, it will return control back to the caller. This mechanism is very similar to the way that PC BIOS functions work. So ultimately, the image that I have permanently stored in SDRAM serves these BIOS functions too.
At that point, you might be ready to start looking at RTOS kernels for embedded systems such as uCOS-II or FreeRTOS. I believe the fundamental building blocks there include:
1. Code to perform a context switch to switch between tasks
2. Some type of supervisor that ensures that the highest priority task that is ready to run is activated and run
3. Some sort of messaging system so that a task can wait for an event to be posted to it from an interrupt or some other task
4. Code to create and keep track of a timer tick so that tasks can be scheduled to run based on the passage of time