Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By metalphreak
#15480 It works!

Well, I did forget an ending bracket } at the end of a function. Fixed that and pushed to Github.

Setup a breadboard with 16 leds on the output. Using the following code to get a binary counting clock.

Code: Select allmcp23s17_init();

mcp23s17_REG_SET(IODIR_CTRL, PORT0, 0x0000);

uint16 portval = 0x0000;

while(1) {

sGPIO_SET(PORT0, portval);

portval++;

os_delay_us(10000); //10ms delay so you can actually see it counting :D

}


Yes, there is an i2c version of this chip (8 and 16 pin GPIO versions). It would be a good alternative option if we had a hardware i2c controller on the ESP8266.

The downside to software (aka 'bit banging') i2c or SPI, is you have this 80MHz microprocessor core sitting there doing nothing while you have os_delay_us(10000) or something between you banging out the highs and lows of the i2c or SPI commands.

With this, you can write out the entire 16 GPIO pins in a matter of microseconds, letting the hardware SPI module in the ESP8266 do all the work, while the processor goes back to handling your other requirements (servicing Wifi/IP etc).
User avatar
By mculibrk
#15544 I'm loosing my mind with the HSPI module of the ESP MCU...

I need to continuously send data over SPI as constant as possible. Originally I used interrupt driver SPI transfers but giving all the problems I'm now trying to identify/fix the problem using busy loop SPI master transfers.

Originally I'm sending 512 bits worth of data in each transfer (but the problem is the same regardless of the transfer size). On transfer complete an interrupt is generated and the ISR re-starts the transfer.

The problem is that the SPI transfer is restarted only after 10uS or more (on 2MHz SPi CLK). I thought that was some interrupt latency problem but the same behavior is seen without interrupts using a busy-loop to wait for the spi transfer compete.

Here is the code I'm using or testing:

Code: Select allvoid ICACHE_RAM_ATTR esp_spi_test(uint32 cycles, uint32 clock){
      // pin config
      WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //Set bit 9 if 80MHz sysclock required
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); //GPIO12 is HSPI MISO pin (Master Data In)
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); //GPIO13 is HSPI MOSI pin (Master Data Out)
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); //GPIO14 is HSPI CLK pin (Clock)
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); //GPIO15 is HSPI CS pin (Chip Select / Slave Select)

      // clock
      if (clock)
         WRITE_PERI_REG(SPI_CLOCK(ESP_SPI_HSPI), clock);
      else
         WRITE_PERI_REG(SPI_CLOCK(ESP_SPI_HSPI), (0<<SPI_CLKDIV_PRE_S) | (39<<SPI_CLKCNT_N_S) | (19<<SPI_CLKCNT_H_S) | (0<<SPI_CLKCNT_L_S));

      // little endian byte order
      SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_WR_BYTE_ORDER);

      // other config - CS setup, disable flash mode
      SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_CS_SETUP|SPI_CS_HOLD);
      CLEAR_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_FLASH_MODE);

      // start transaction
      CLEAR_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_USR_MOSI|SPI_USR_MISO|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_DUMMY);

      // transaction length
      WRITE_PERI_REG(SPI_USER1(ESP_SPI_HSPI), (511)<<SPI_USR_MOSI_BITLEN_S);

      SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_USR_MOSI);

      // prepare data buffer, bit MSB order, bytes LE order
      WRITE_PERI_REG(SPI_W0(ESP_SPI_HSPI),  0x67452301);
      WRITE_PERI_REG(SPI_W1(ESP_SPI_HSPI),  0xEFCDAB89);
      WRITE_PERI_REG(SPI_W2(ESP_SPI_HSPI),  0x67452301);
      WRITE_PERI_REG(SPI_W3(ESP_SPI_HSPI),  0xEFCDAB89);
      WRITE_PERI_REG(SPI_W4(ESP_SPI_HSPI),  0x67452301);
      WRITE_PERI_REG(SPI_W5(ESP_SPI_HSPI),  0xEFCDAB89);
      WRITE_PERI_REG(SPI_W6(ESP_SPI_HSPI),  0x67452301);
      WRITE_PERI_REG(SPI_W7(ESP_SPI_HSPI),  0xEFCDAB89);
      WRITE_PERI_REG(SPI_W8(ESP_SPI_HSPI),  0x67452301);
      WRITE_PERI_REG(SPI_W9(ESP_SPI_HSPI),  0xEFCDAB89);
      WRITE_PERI_REG(SPI_W10(ESP_SPI_HSPI), 0x67452301);
      WRITE_PERI_REG(SPI_W11(ESP_SPI_HSPI), 0xEFCDAB89);
      WRITE_PERI_REG(SPI_W12(ESP_SPI_HSPI), 0x67452301);
      WRITE_PERI_REG(SPI_W13(ESP_SPI_HSPI), 0xEFCDAB89);
      WRITE_PERI_REG(SPI_W14(ESP_SPI_HSPI), 0x67452301);
      WRITE_PERI_REG(SPI_W15(ESP_SPI_HSPI), 0xEFCDAB89);

      while (cycles--) {
         while (READ_PERI_REG(SPI_CMD(ESP_SPI_HSPI)) & SPI_USR) {
            asm volatile ("nop");
         }
         // begin transaction
         SET_PERI_REG_MASK(SPI_CMD(ESP_SPI_HSPI), SPI_USR);
         clrwdt();
      }
}


Attached is a "grab" ob SPI CLK/DATA/CS signals when the SPI CLK is running at 7,12MHz

SPI gap during continuos send.png


As you can see, the CS signal is not being toggled/asserted whatsoever and I do not understand why. (I really don't need the CS but just for reference)

Any hint/suggestion is more then welcome!

Regards,
MCulibrk
You do not have the required permissions to view the files attached to this post.
User avatar
By metalphreak
#15567 Chip Select is GPIO15 which you must have pulled low for normal SPI flash boot OR UART flashing. You probably have this pin pulled directly to ground as part of the normal bootup strapping. If you have it directly connected to ground, then the CS pin can never be driven high by the microcontroller! Make sure you use a high value pull-down resistor instead (4.7k - 10k).

Which ESP module are you using?


As for the 10uS delay, the actual commands to load up the data into the SPI_Wx registers and sending the SPI start command will take some time. You can't write data into the SPI_Wx registers while it's running, so there'll always be a small gap between the 512bit data packets. But since it's SPI, which has the synchronous clock, the slave device shouldn't care.

For what it's worth, I looked through your code, and I don't see anything wrong with it that could be affecting the CS.