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

User avatar
By fplanel
#7754 Hello,

I try to implement a SPI send / receive function using HSPI interface. Here is my non working code :

Code: Select alluint8_t ICACHE_FLASH_ATTR spi_master_send_recv(uint8 data_out)
 {
   uint32_t regvalue;
   uint8_t data_in;

   while(READ_PERI_REG(SPI_FLASH_CMD(HSPI))&SPI_FLASH_USR);
    regvalue = READ_PERI_REG(SPI_FLASH_USER(HSPI));
    // We want to send & receive data, so no command, address. DOUT and SPI_DOUTDIN set
    regvalue = regvalue | SPI_CS_SETUP | SPI_CS_HOLD  | SPI_FLASH_DOUT | SPI_DOUTDIN;
    // BIT2 is undocumented bit, example code wants it cleared
    regvalue = regvalue & (~(BIT2 | SPI_USR_COMMAND | SPI_FLASH_USR_DIN | SPI_FLASH_USR_ADDR ));
    WRITE_PERI_REG(SPI_FLASH_USER(HSPI), regvalue);

    // Send / Receive 8 bits
    SET_PERI_REG_BITS(SPI_FLASH_USER1(HSPI),SPI_USR_OUT_BITLEN,7,SPI_USR_OUT_BITLEN_S);
    WRITE_PERI_REG(SPI_FLASH_C0(HSPI), data_out);

    SET_PERI_REG_MASK(SPI_FLASH_CMD(HSPI), SPI_FLASH_USR);      //transmission start
    while (READ_PERI_REG(SPI_FLASH_CMD(HSPI))&SPI_FLASH_USR);         //waiting for spi module available again

    //os_printf("SPI_FLASH_C0 0x%08x\r\n", READ_PERI_REG(SPI_FLASH_C0(HSPI)));
    data_in = (uint8_t)(READ_PERI_REG(SPI_FLASH_C0(HSPI)));
    return data_in;
 }


What is wrong with it ?

Thanks for your help

Frantz
User avatar
By john
#7790 here's some code fragments with comments:

uint32 regvalue;
static uint32 t1 = 0;
static uint32 t2 = 0;
t1 = system_get_time();
if (READ_PERI_REG(0x3ff00020) & BIT4) { // Bit 4 is SPI interrupt
// The following 3 lines are to clear ISR signal
CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff);
} else if (READ_PERI_REG(0x3ff00020) & BIT7) { // Bit 7 is HSPI interrupt
regvalue = READ_PERI_REG(SPI_SLAVE(HSPI)); // Record the interrupt type


// Disable the interrupt
CLEAR_PERI_REG_MASK(
SPI_SLAVE(HSPI),
SPI_TRANS_DONE_EN | SPI_SLV_WR_STA_DONE_EN |
SPI_SLV_RD_STA_DONE_EN | SPI_SLV_WR_BUF_DONE_EN |
SPI_SLV_RD_BUF_DONE_EN
);
// Reset the SPI slave to communication mode
SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SYNC_RESET);


// Clear the interrupts
CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
SPI_TRANS_DONE | SPI_SLV_WR_STA_DONE |
SPI_SLV_RD_STA_DONE | SPI_SLV_WR_BUF_DONE |
SPI_SLV_RD_BUF_DONE
);


// Enable SPI interrupt
SET_PERI_REG_MASK(SPI_SLAVE(HSPI),
SPI_TRANS_DONE_EN | SPI_SLV_WR_STA_DONE_EN|
SPI_SLV_RD_STA_DONE_EN | SPI_SLV_WR_BUF_DONE_EN|
SPI_SLV_RD_BUF_DONE_EN
);



// Master output, slave input function
if (regvalue & SPI_SLV_WR_BUF_DONE) {
GPIO_OUTPUT_SET(0, 0); // GPIO0 set to 0
idx = 0;
// Reads data
while (idx<8) {
recv_data = READ_PERI_REG(SPI_W0(HSPI) + 4*idx);
spi_data[4*idx+0] = recv_data & 0xff;
spi_data[4*idx+1] = (recv_data>>8) & 0xff;
spi_data[4*idx+2] = (recv_data>>16) & 0xff;
spi_data[4*idx+3] = (recv_data>>24) & 0xff;
idx++;
}
system_os_post(USER_TASK_PRIO_1, MOSI, 0); // Post receive is done
GPIO_OUTPUT_SET(0, 1); // Set GPIO0 to 1
SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SLV_WR_BUF_DONE_EN);


// Master Input, Slave Output Function
if(regvalue & SPI_SLV_RD_BUF_DONE) {
GPIO_OUTPUT_SET(2, 0); // Set GPIO2 to 0
}
}
else if (READ_PERI_REG(0x3ff00020) & BIT9) { } // Bit 9 is I2S interrupt
}
User avatar
By john
#7791 and here's for the host device:
Implementation of the SPI Protocol in the Host Device
Below are some commented code fragments to illustrate the implementation of communication protocol:
// wr_rdy==1: ESP8266 can proceed with SPI write
// rd_rdy==1: ESP8266 can proceed with SPI read
unsigned char wr_rdy=1,rd_rdy=0;
void spi_read_func(….) {
// Before communication starts, we need to check that there is no data
// from the host, i.e. rd_rdy==1.
// Besides this, we also need to check if the last write operation
// has been completed, i.e. (wr_rdy==1 or GPIO0==0)
if(rd_rdy&&((GPIO0= =0)||wr_rdy)){
rd_rdy=0; // This clears the rd_rdy flag, i.e. we cannot read again
spi_transmit(0x03,0,*read_buff); // Starts the SPI receive process
...
}
}

void spi_write_func(…) {
// Before communication starts, we need to check if the slave device can
// write data to the host, i.e. wr_rdy==1.
// Besides this, we also need to check if the last read operation
// has been completed, i.e. (rd_rdy==1 or GPIO2==0)
if(wr_rdy && ((GPIO2==0) || rd_rdy)) {
wr_rdy=0; // This clears the wr_rdy flag, i.e. we cannot write again
spi_transmit(0x02,0,*write_buff); // Starts the SPI transmit process
...
}
}

GPIO0_Raising_Edge_ISR() {
// For things related to GPIO0 rising edge triggered interrupt
wr_rdy=1; // After the host sends the data, we can enter the write cycle
}

GPIO2_Raising_Edge_ISR() {
// For things related to GPIO2 rising edge triggered interrupt
rd_rdy=1; // After the host receives the data, we can enter the read cycle
}