Bare-metal programming is a low-level method of programming that is specific to the hardware hence there is a need to understand how a hardware architecture works and what happens in the lowest levels of an operating system. Bare-metal programs run without OS beneath(e.g Linux Kernel) and are OSes themselves for you are forced to work directly with memory, pointers, and the underlying arrangement of the bits and bytes. Assembly language and C language are preferred in bare-metal programming for they are closer to the machine code. A good write up with great tutorials for writing bare programs in Assembly is available online from the University of Cambridge. Another great source that I heavily borrowed my OS template is from David Welch git-hub resource and both implementations are discussed in the bare-metal section of Rpi forums. where you can seek clarification in case you are stuck.
I have written a simple program for SPI driver which uses the polled method and the source is available here at bit-bucket. The steps of achieving this operation as described in page 158 of BCM2835 ARM Peripheral Datasheet are:
1 Set CS, CPOL, CPHA as required and set TA = 1 2 Poll TXD writing bytes to SPI_FIFO, RXD reading bytes from SPI_FIFO until all data written. 3 Poll DONE until it goes to 1 4 Set TA = 0.
The DONE bit of Control Register in step 3 did not change to 1 after writing to the FIFO transmit register and the program got stuck at this loop. I was forced to substitute it with a small delay as a temporary measure as I check into this issue.
To compile the program I used Codesourcery free version of the gcc tool-chain for ARM cores. Make sure that the path to the toolchain binaries is added to the PATH environment variable otherwise the make will not find the toolchains to compile the files. I have included a sample program test.c (video of the sample below) which send a byte of data to the spi port that is connected to 74HCT595 (shift register). 8 LEDs are connected to output of the shift register to generate a binary equivalent of the sent data byte looping through 1 to 255 decimal. Once the program has successfully compiled , copy the generated kernel.img (from the output directory) to the first FAT partition of the SD card replacing the existing kernel.img. The start.elf , boot-code.bin and loader.bin must be present(firmwares required by video core processor ,read here for rpi boot process) in the same partition for the system to successful boot. If you don’t have these files you can obtain them from raspberry pi firmware directory.
Enjoy!
I think step 3 should be:
while (!(var & (1 << SPI_C_DONE)))
var = *SPI0_CONTROL;
Also, I think there is no need to wait for TXD.
Cheers!