There are probably tens of combinations, so at some point I suggest you to quickly go through the reference manual to understand better what to do, and why you have to do it.
When booting form a SD card, the bootloader must contain an image vector table that must be placed at a certain offset: 0x400 = 1kB.
So, when doing a dd to program the u-boot, if bs=1k then seek=1, if bs=512 then seek=2 !
Also, I consider that the generated u-boot is always padded, and I won't bother much to use another non-padded version.
You can clearly identify the padded one with an od or hexdump command in Linux to identify the IVT header = 0xD1002040 at offset 0x400. Data from 0x4 -> 0x400 are likely zeros, with a 32-bit branch instruction at 0x0.
user@ubuntu:~/linux_bsp/uboot-imx$ hexdump u-boot.bin | more
0000000 01c6 ea00 0000 0000 0000 0000 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0000 0000
*
0000400 00d1 4020 0720 2780 0000 0000 042c 2780
The instruction at 0x0 is useless, it is a legacy from previous i.MX.
Therefore, the typical dd command is:
sudo dd if=u-boot.bin of=/dev/sdb bs=512 seek=2 skip=2; sync
The skip is to remove the first 1kB of zeros from u-boot, and the seek to preserve the MBR and related file system information usually contained in these first blocks of a SD card.
The small SPI_to_SD code does the same thing than the boundary device solution through a u-boot command line. if you disassemble the code, you'll see the same.