- Fri Apr 24, 2015 6:43 pm
#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.