This article follows from part 1. I did some more probing and reading to come up with better ideas to get the HSPI on the ESP8266 working. Also, I put a logic analyzer to see if the main SPI interface is usable (the one used with the main flash memory). But it seems that the main SPI interface is way too busy to be useful for other purposes. Therefore, the focus here will be on the HSPI interface only for ESP8266 SD card interfacing. In this article, I list the general method of initializing the HSPI interface and initiating a data transfer (examples of 1-byte transmit and receive routines).
The HSPI architecture is fairly simple but very versatile. To initialize the interface, you may want to use the standard functions defined in the Espressif RTOS (or nonRTOS) SDK example. That is definitely a good starting point to set things to a working default state. After this, the typical way to initialize the interface to suit your own way is to modify the registers that actually effect the data transmission parameters such as the number of bytes sent, the polarity and phase of clock signal, etc.
In general, the HSPI interface of the ESP8266 can send data in a continuous block made of the following data blocks (in sequence):
- Command (max 2 bytes)
- Address (max 4 bytes)
- Dummy cycles
- Data (max 64 bytes)
The length of all these blocks are configurable to any bit number you want (BRILLIANT feature, really!). For example, you may want to send a byte of command + 4 byte parametes and a CRC byte (which is used in SD cards), you may do that using the HSPI hardware.
Initialize ESP8266 HSPI interface
Now that you have used the initialization function provided in the Espressif ESP8266 SPI example as follows:
SpiAttr slow_spi; // HSPI attributes structure
// Wait for last send operation to finish, if any
while (READ_PERI_REG (SPI_CMD(1)) & (1<<18));
slow_spi.bitOrder = SpiBitOrder_MSBFirst;
slow_spi.speed = SpiSpeed_0_5MHz;
slow_spi.mode = SpiMode_Master; // HSPI master mode
slow_spi.subMode = SpiSubMode_0; // CPLO = CPHA = 0
You will now have a working configuration for the SPI interface, you may modify the following registers before initiating any data transfer:
- SPI_USER: Enable/disable phases of SPI transfer (command, data, addr, dummy, etc), select normal/DIO/QIO modes, etc.
- SPI_USER1: Bit length of address, data out, data in, dummy clocks.
- SPI_USER2: Bit length and content of command phase
- SPI_W0 – SPI_W15: Data buffer from where data bytes are sent out/received into.
- SPI_CMD: Initiate a new transfer or check status of SPI hardware.
Here is an example waveform of what the data transfer looks like when done in bytes:
Data transfer from HSPI port (MOSI and SCK signals)
In the next post on this topic, I will share the code used to write a byte or read a byte from the HSPI hardware. Soon, it will be going all the way to SD card interfacing and file read/write operations. However, I faced a strange problem of high current consumption in ESP-12 module on startup and also spurious reset of CH340 serial driver. Once that is sorted, I can try out some more ESP8266 SD card interfacing related code.
Please subscribe to stay updated on further development. 🙂
Feel free to leave your questions in comments below…