Use of buffered IO

If you have a simple question and just want an answer.
JohnRed
Junior Member
Posts: 5
Joined: Wed Oct 31, 2018 6:25 pm

Use of buffered IO

Post by JohnRed »

I am modifying the sc_flash library to add functions for reading the manufactures ID, and device ID from the flash device on the eXplorer development kit.

I find that I do not understand how and when a buffered read occurs and why I need to do a 'dummy read' please see details below.

The code listed at the bottom of this txt is intended to help to illustrate the question.

I am driving the leds output (purely to help to debug the code), at the same clock counts as the p.DQ input is being executed but it appears that a read occurs later than a write.

The scope image Read data 1.JPG shows the Flash chip Serial out line p.DQ bit 1 on channel 1 and the leds bit0 line on channel 2.

You will see that the code:
leds @ time + 31 <: 0x0f;
p.DQ @ time + 31 :> int;
Drives the leds line high at the same time as the p.DQ read is triggered.

The strange thing is that this read is thrown away and its not until the next read cycle that the byte 0x9D is read which occurs on the following lines:
leds @ time + 8 + 31 <: 0x00;
p.DQ @ time + 8 + 31 :> data_in[0];

QUESTION 1
Does this instruction p.DQ @ time +8+ 31 :> data_in[0]; transfer the last 32 bits of data captured on p.DQ into the variable data_in[0]?

QUESTION 2
As the buffer stores 32 bits from a 4bit port does this mean that the capture actually starts 8 clock cycle before time + 8+ 31?

QUESTION 3
If I delete the line p.DQ @ time + 31 :> int ; Why does the line p.DQ @ time + 8 + 31 :> data_in[0]; then fail to correctly capture the first word correctly? (It actually captures 0x1 rather than 0x9D after relevant bit transformations are made.)


Read data 1.JPG

Below is the relevant code from quad_spi_flash.xc based on the code taken from the sc_flash repository.

typedef struct {
out port CS;
out port CLK;
buffered port:32 DQ;
clock cb;
int initialised;
} quad_spi_ports;

out buffered port:4 leds = XS1_PORT_4F;
quad_spi_ports p = {XS1_PORT_1B, XS1_PORT_1C, XS1_PORT_4B, XS1_CLKBLK_1, 0};

unsigned char temp = 0;
unsigned char byte = 0;
unsigned char un_zip(unsigned x){
temp = (x>>(1-0) ) & 0x01;
temp += (x>>(5-1) ) & 0x02;
temp += (x>>(9-2) ) & 0x04;
temp += (x>>(13-3)) & 0x08;
temp += (x>>(17-4)) & 0x10;
temp += (x>>(21-5)) & 0x20;
temp += (x>>(25-6)) & 0x40;
temp += (x>>(29-7)) & 0x80;
byte = (temp&0x01)<<7;
byte += (temp&0x02)<<5;
byte += (temp&0x04)<<3;
byte += (temp&0x08)<<1;
byte += (temp&0x10)>>1;
byte += (temp&0x20)>>3;
byte += (temp&0x40)>>5;
byte += (temp&0x80)>>7;
return byte;
}


void quad_spi_flash_init(quad_spi_ports &p){
if (!p.initialised){
configure_clock_ref(p.cb, 2);
configure_out_port(p.DQ, p.cb, 0x0F);
configure_out_port(p.CS, p.cb, CS_HI);
configure_out_port(leds, p.cb, 0); // JP LED output buffered to QSPI clock for debugging
configure_port_clock_output(p.CLK, p.cb);
start_clock(p.cb);
p.initialised = ~0;
}
quad_spi_flash_write_enable(p);
quad_spi_flash_quad_enable(p);
quad_spi_wait_until_idle(p);
}


unsigned index = 0;
void quad_spi_flash_read_manufacturer_and_product_ids(quad_spi_ports &p, unsigned char *manufacturer_id, unsigned char *product_id){
unsigned time;
unsigned data_in[3];

p.CS <: CS_HI @ time;
time += 10;
p.CS @ time <: CS_LO;
p.DQ @ time <: (unsigned) ZIP(0x90);
p.CS @ time + 32 + (2 * 8) <: CS_HI ;

leds @ time + 31 <: 0x0f;
p.DQ @ time + 31 :> int ;

leds @ time + 8 + 31 <: 0x00;
p.DQ @ time +8+ 31 :> data_in[0];

leds @ time + 16 + 31 <: 0x0f;
p.DQ @ time +16+ 31 :> data_in[1];
leds @ time + 32 + 16 <: 0x00;

*manufacturer_id = un_zip(data_in[0]);
*product_id = un_zip(data_in[1]);
}

Note - To make the code work on my eXplorer dev board for the functions used in app_quad_spi_flash_demo.xc, I made the following changes:
1. Modify the makefile to change the Target to xCORE-200 Explorer Kit
2. Deselect the Used Modules, module_slicekit_support in the makefile.
3. Modify the application code to map the correct ports.
4. Modify quad_spi_flash.xc to change CS_LO to 0 and CS_HI to 1 (as the explorer board uses a 1 bit port for CS).
You do not have the required permissions to view the files attached to this post.


User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

While this post may not answer your question, the solution to read out the IDs is relatively simple using standard SPI mode commands.

Please review my last post on page #2 here with source code - we used this same code to perform the same task and also to ENABLE / DISABLE the QSPI bit inside the flash device:

https://www.xcore.com/viewtopic.php?f=2 ... t&start=10