# Writing SPI driver (Read ID) command help

#### zazas321

Joined Nov 29, 2015
926
Hello. I am programming ESP32 device and trying to write my first SPI driver for the following EEPROM chip:

From the datasheet:

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
//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,
.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
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 = &reg;
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];
}

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);

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];
}
The result:
Code:
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
17,240
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
446
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

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

Last edited:

#### Kjeldgaard

Joined Apr 7, 2016
456
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:

#### mckenney

Joined Nov 10, 2018
122
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

#### zazas321

Joined Nov 29, 2015
926
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
17,240
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.