I cut the traces going to the SPI RAM that I figured out were wrong last week. On the PCB at U3 Pin3, and Pin5 I cut one trace each and on Pin6 I cut two traces. Most of these cuts are under the chip so I made them before re-soldering the chip to the board. Of course then I added wire jumpers to route the signals to match the schematic. I then added pins to connect the logic analyzer to.
Last week I was looking at the the SPI driver code by MetalPhreak on Github as well as his blog to figure out how to send commands and data out and receive back over SPI. The register SPI_USER is used to configure the SPI, SPI_USER1 sets up data length, SPI_USER2 sets up the command length and Command data. Additionally, there is an SPI_Address Register that I can use to select an address in the RAM. Finally SPI_W0 to SPI_W15 are the data packet working registers — This is where I will put my “Hello World”. I can write or read up to sixteen 4 byte words. My RAM is organized in bytes so I will be putting bytes of data into the working registers.
So for initial setup I think the following should work for writing data.
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MISO);
The following should work for reading data:
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MISO);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MOSI);
The CS_SETUP and CS_HOLD parameters affect chip select timing. Setup is before clocking out data, hold is after. Some chips need extra set up or hold time. It will not affect performance significantly so I just turned each on by default so I don’t have to wonder if this RAM chip needs them. USR_COMMAND tells it to send the data in the command register. Likewise USR tells it to send the data in the Address Register. USR_MOSI tells the hardware that there is data in the Working registers to be sent out. USR_MISO tells the hardware that I want to receive data into the working registers.
For the SPI RAM I want to send a command(Write), An Address(0), and 12 Bytes of data(“Hello World”). This totals 16 bytes of data to be sent on the SPI bus:
1 byte for the command: 0x02
3 bytes for the address: 0x000000 and
12 bytes of data: “Hello World” including 1 trailing NULL.
For my first attempt to write to RAM I chose to hard code the instructions.
In my SPIRam.c File I had already created a function called writeRam. I deleted it’s contents, and added the stuff to make this work.
void writeRam(char data[], int length){
SET_PERI_REG_MASK(SPI_USER(HSPI),
SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MISO);
WRITE_PERI_REG(SPI_USER1(HSPI), (((12*8-1)&SPI_USR_MOSI_BITLEN)<<SPI_USR_MOSI_BITLEN_S)| //12 Bytes of data out
((7&SPI_USR_MISO_BITLEN)<<SPI_USR_MISO_BITLEN_S)| //Ignored for write
((23&SPI_USR_ADDR_BITLEN)<<SPI_USR_ADDR_BITLEN_S)); //address is 24 bits A0-A8
WRITE_PERI_REG(SPI_ADDR(HSPI),(uint32) 0x000000<<(32-24)); //write 24-bit address
WRITE_PERI_REG(SPI_USER2(HSPI),
(((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S) | 0x02)); // Write Command
WRITE_PERI_REG(SPI_W0(HSPI),0x48656C6C); //"Hell"
WRITE_PERI_REG(SPI_W1(HSPI),0x6F20576F); //"o Wo"
WRITE_PERI_REG(SPI_W2(HSPI),0x6C6400); //"rld",NULL,NULL
SET_PERI_REG_MASK(SPI_CMD(HSPI), SPI_USR);// Tell hardware to do it.
}
After fixing my typos, I compiled and loaded the code. The system booted without hanging. then I hooked up the logic analyzer to look for the data being transferred and it didn’t work. The Chip select line(U3 Pin1 ) doesn’t go low for a frame of data. This means the chip never gets selected to write to.
With several hours of tinkering, I finally have it close, but it is still not working correctly. The CS0 pin is being activated when the HSPI CS pin is being activated. So I am getting the correct sequence of bytes when HSPI CS is low, but CS0 is low at the same time.
I have not posted a new copy of the software, I don’t believe it is useful to anyone yet. It isn’t even useful to learn from.
Have you had similar frustrations? Have you gotten the HSPI to work in overlap mode?
Please leave a comment below.