Writing SPI driver (Read ID) command help

Thread Starter

zazas321

Joined Nov 29, 2015
936
Hello. I am programming ESP32 device and trying to write my first SPI driver for the following EEPROM chip:
http://www.datasheet-pdf.com/PDF/GD5F1GQ4UAY-Datasheet-GigaDevice-791680

From the datasheet:
1634624410732.png
1634624434420.png


I have been trying to read the device id but unsucsefully.

I am not able to fully understand the structure of the SPI data needed. Please explain if below is correct:


In order to read the ID, I need to transmit 2 bytes of data:
Byte1 - Command ( 0x9F)
Byte2 - Address ( I do not understand what I need to send here since the documentation is not very clear to me). From what I understand, If I send 0x00, then the device should respond if Manufacture ID and Device ID.


After I have sent 2 bytes, I can start reading the data. I only need to read 2 bytes.

My code:


Code:
#include "GD5F1GQ4UEYIG.h"
spi_device_handle_t external_flash;



static void cs_gpio_setup()
{
    gpio_config_t io_conf;
  
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = GPIO_SPI_OUTPUT_PIN_SEL;
    //disable pull-down mode
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    //disable pull-up mode
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    //configure GPIO with the given settings
    gpio_config(&io_conf);
}
void cs_low(){
    gpio_set_level(PIN_NUM_CS, false);
}
void cs_high(){
    gpio_set_level(PIN_NUM_CS, true);
}





void SPI_init(){
    esp_err_t ret;
    //spi_device_handle_t spi;
    spi_bus_config_t buscfg={
        .miso_io_num=PIN_NUM_MISO,
        .mosi_io_num=PIN_NUM_MOSI,
        .sclk_io_num=PIN_NUM_CLK,
        .quadwp_io_num=-1,
        .quadhd_io_num=-1,
        .max_transfer_sz=PARALLEL_LINES*320*2+8
    };
    spi_device_interface_config_t devcfg={
        .clock_speed_hz=10*1000*1000,           //Clock out at 10 MHz
        .mode=0,                                //SPI mode 0
        .spics_io_num=PIN_NUM_CS,               //CS pin
        .queue_size=7,                          //We want to be able to queue 7 transactions at a time
        //.pre_cb=lcd_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
    };
    //Initialize the SPI bus
    ret=spi_bus_initialize(EEPROM_HOST, &buscfg, DMA_CHAN);
    ESP_ERROR_CHECK(ret);
    //Attach the LCD to the SPI bus
    ret=spi_bus_add_device(EEPROM_HOST, &devcfg, &external_flash);
    ESP_ERROR_CHECK(ret);
    cs_gpio_setup();
}

void GD5F1_read_reg(spi_device_handle_t spi, uint8_t reg, uint8_t* data){
    spi_transaction_t t;
    
    cs_low();
    memset(&t,0,sizeof(t));
    t.length = 8;
    t.tx_buffer = ®
    spi_device_transmit(spi,&t);
    memset(&t,0,sizeof(t));
    t.length = 8;
    t.flags = SPI_TRANS_USE_RXDATA;
    spi_device_transmit(spi,&t);
    cs_high();
    *data = t.rx_data[0];
}

void GD5F1_read_id(spi_device_handle_t spi,uint8_t* data){
    spi_transaction_t t;
    uint16_t reg2 = 0x9f00;
    cs_low();
    memset(&t,0,sizeof(t));
    t.length = 16;
    t.tx_buffer = &reg2;
    spi_device_transmit(spi,&t);

// start reading here
    memset(&t,0,sizeof(t));
    t.length = 16;
    t.flags = SPI_TRANS_USE_RXDATA;
    spi_device_transmit(spi,&t);
    cs_high();
    *data = t.rx_data;
   
}

And in my main.c

Code:
    while(1)
    {

        uint8_t id[2];
        GD5F1_read_id(external_flash,id);
        printf("ID[0] read = %02X \n",id[0]);
        printf("ID[1] read = %02X \n",id[1]);
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
The result:
Code:
ID[0] read = 30
ID[1] read = 48
ID[0] read = 30 
ID[1] read = 48 
ID[0] read = 30 
ID[1] read = 48 
ID[0] read = 30 
ID[1] read = 48 
ID[0] read = 30 
ID[1] read = 48 
ID[0] read = 30 
ID[1] read = 48

I cannot get my head around how to get this to work. Any advice is highly appreciated.
 

Papabravo

Joined Feb 24, 2006
21,157
You are either transmitting garbage or you are reading garbage.
You are not giving t.tx_buffer a value before the second 16 bit transmission. What do you think is actually going out on the SPI bus?

Recommendation: Write explicit inline code to do what you want to test your understanding of SPI before fooling around with pointers, structures and calls to memset()
Yeech!
 

click_here

Joined Sep 22, 2020
548
In order to read the ID, I need to transmit 2 bytes of data:
Byte1 - Command ( 0x9F)
Byte2 - Address ( I do not understand what I need to send here since the documentation is not very clear to me). From what I understand, If I send 0x00, then the device should respond if Manufacture ID and Device ID.
It looks like you have to transmit 9F - A[7..0]-C8-10

The last 2 bytes are the "mid" and "did" as stated in the notes below the table

[edit] sorry, I missed the line below about A[7..0] = 0 - You appear to be right[/edit]
 
Last edited:

Kjeldgaard

Joined Apr 7, 2016
476
I can not completely follow the program code, but reading the ID must be handled as one 32 bit session.

Ie set CS low, write / read the 32 bits and set CS high again.

I have cut a little in the time sequence chart from further up in the thread:

32BitSpiCom.jpg
 

mckenney

Joined Nov 10, 2018
125
Code:
   uint16_t reg2 = 0x9f00;
As far as I know the ESP32 is little-endian, so this will send {0x00, 0x9F}. What I would do is use a two-byte array (so I never have to wonder), but it probably suffices to do:
Code:
   uint16_t reg2 = 0x009f;  // {0x9F, 0x00} little-endian
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Thank you all for the suggestions. I have managed to get it to work. I have tried to used HALF_DUPLEX and it seemed to work
 

Papabravo

Joined Feb 24, 2006
21,157
Thank you all for the suggestions. I have managed to get it to work. I have tried to used HALF_DUPLEX and it seemed to work
I'm confused. How does HALF DUPLEX apply to an SPI transaction? By definition all SPI transactions are FULL DUPLEX because on every clock edge a bit goes out and another one comes in. It is true that on any given bit either the bit going out or the bit coming in might be ignored.
 
Top