As I previously mentioned, for my car, I am using the auxilary SPI1 module, and not the SPI0 peripheral which is used by many, and which is the only one implemented in the Linux drivers (or even by WiringPi). So I had to implement my own driver to be able to communicate with the dsPIC on my daughter board.
The problem I faced, and I already mentioned it in a previous post, is that the datasheet provided by broadcom has a lot of errors and “unclear” behaviors. I will try to detail all the problems I had faced.
There already is an errata page on eLinux.org, but until I can figure out how I can edit the page or tell them what I found, it will at least be here.
- p24 : AUXSPI0/1_CNTL1 Register table, the bit numbering is wrong, it should be 31:11
- p25 : AUXSPI0/1_STAT Register table, this one is important, it caused me a lot of troubles.
- 31:28 : TX FIFO Level (note that the maximum value is 4, so not all the 4 bits are needed)
- 23:20 : RX FIFO Level (same remark as above)
- 10 : TX full
- 9 : TX empty
- 8 : RX full
- 7 : RX empty
- 6 : busy
- 5:0 : no change, but not very usefull
Here is how I found it (after several guess and tries) : After boot and after starting the peripheral, the value of the STAT register is 0x00000280, which is only 2 bits high, so we can guess they are the empty status bits. Then, in a while loop, I write values in the IO buffer and I read the STAT register each time. After 4 loops, the TX buffer is full, and we read the value 0x40400540; so we still have 2 bits high in the lowest bytes, they must indicates a full status, because when we send frames, it is a SPI bus, so we receive at the same time, event if there is nothing really send on the other side, so we have a TX full and RX full bits high; and we can see on the highest bytes that we have two ‘4’ values, which is the size of the FIFOs, so this is just the TX and RX FIFO levels, as indicated in the datasheet, but with a different placement.
- p26 : PEEK register address is 0x7E21508C, but indicated 0x7e215094 on page 8; 0x7E21508C value is the correct one.
- p26 : IO register address is 0x7E2150A0, but indicated 0x7e215090 on page 8; 0x7E2150A0 value is the correct one.
- p26 : PEEK and IO registers show a width of only 16 bits of data, but the datasheet mentions that it is a 32 bits SPI peripheral, so I think this is wrong (I only use it in 16 bits mode, so I didn’t have the problem)
I think I also mentioned that in another post, but I had a problem when using the SPI in 16 bits mode. You can choose the bit length which is shifted out by settings bits 5 to 0 of CNTL0 register. You think this is it, and it’s working… no it would be too easy; because there also is a very strange behavior of this SPI peripheral : by default, it shifts out (in MASTER mode) the LSB first ! This is (at least I think) absolutely not conventional for a SPI peripheral. Fortunately for us you can change this, and set the bit 6 of CNTL0 register, and here we go … oh no, it doesn’t work …
What is happening here, you configured a length of 16 bits to shift out, and you tell the SPI peripheral to shift MSB first, so it does exactly what you asked, it shifts out the 16 highest bits of the IO register … which is a 32 bits register ! So the only thing we have to do to fix this, is to write in the 16 MSB of the IO register, and then our 16 bits wide data will be shifted MSB first out of the SPI master. (It took me some time to figure this out, so I hope it can help someone else).
I did not test each feature or each configuration of the peripheral, only the use case I needed, so there might be some other problems, but at least for a basic usage, I think this errata will help.
Stay in touch, I will post soon some news about the progress on my remote car project.