BRT Community

Please login or register.

Login with username, password and session length
Advanced search  

News:

Welcome to the Bridgetek Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ Bridgetek Support

Please refer to our website for detailed information on all our products - Bridgetek - Bridging Technology

Pages: [1] 2

Author Topic: why can't I read the Manufacturer/Device ID?  (Read 16548 times)

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
why can't I read the Manufacturer/Device ID?
« on: January 18, 2021, 09:44:37 PM »

Hello

I have a PCB with BT817 and W25Q128JVSIQ memory chip on it.
I'm trying to read the Manufacturer/Device ID of the memory chip using the command
I used
Code: [Select]
GD.cmd_flashread() to read the Manufacturer/Device ID into RAM_G of BT817 and then used
Code: [Select]
Serial.println(GD.rd(0x00),HEX);
on Arduino but I get FF instead of EF.
Does anyone know what am I doing wrong here?


The memory chip was tested using
Code: [Select]
Serial.println(GD.rd(REG_FLASH_SIZE)); and I get 16M as the size which is correct
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 733
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #1 on: January 19, 2021, 03:39:56 PM »

Hello,

Thank you for your question.
The W25Q128JVSIQ datasheet notes to read the Device ID of the flash chip, you must issue and instruction code to the IC “90h” followed by a 24-bit address (A23-A0) of 000000h. After which the Device/Manufacture ID is clocked out by the IC.

Unfortunately in this case it will not be possible to use the CMD_FLASHREAD and CMD_FLASHWRITE commands to access the Device/Manufacture ID of the flash IC. Currently it looks like your code is just reading a blank sector of flash.

I would suggest looking at the CMD_FLASHSPITX and CMD_FLASHSPIRX commands (only available after issuing a CMD_FLASHDETACH command), these should allow you to issue the correct opcode to the flash IC to retrieve the Device/Manufacture ID.

Best Regards,
BRT Community
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #2 on: January 19, 2021, 05:27:58 PM »

I tried the following code

 
Code: [Select]
GD.cmd_flashdetach();
  GD.cmd_flashspidesel();
  GD.cmd_flashspitx(4);
  GD.cmd32(0x90);

  GD.cmd_flashspirx(0,2);
  delay(20);
  Serial.println(GD.rd(0));

and
Code: [Select]
Serial.println(GD.rd(0)); is still reading FF or 255
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #3 on: January 19, 2021, 05:56:50 PM »

I might be wrong there but I believe there is no way to read any of the registers from the connected flash chip.
Yes, there are the commands CMD_FLASHSPITX and CMD_FLASHSPIRX but there is no way to control the chip-select line.

Well, there is CMD_FLASHSPIDESEL but there is no CMD_FLASHSPISEL.
I could not find anything in the documented registers to control SPIM_SS_N.

So without modifying the hardware (or maybe additional documentation) to allow control over the chip-select line it is only possible to read the content of the attached flash chip thru the flash driver with CMD_FLASHREAD.


Logged

pauljiao

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #4 on: January 20, 2021, 02:58:22 AM »

Here is an example code in python to access the registers of flash:
Code: [Select]
def bb(*b):
    return pad4(array.array('B', b).tostring())

def txrx(eve, txpart, n_rx):
    eve.cmd_flashspidesel()
    eve.cmd_flashspitx(len(txpart))
    eve.c(bb(*txpart))
    eve.cmd_flashspirx(0, n_rx)
    if n_rx:
        eve.finish()
        return array.array('B', eve.rdstr(0, n_rx))

def do_sfdp(eve):
    """ Dump the SFDP area in binary """
    eve.cmd_flashdetach()
    eve.cmd_flashspidesel()

    eve.cmd_flashspitx(1)
    eve.c(bb(0x9f))
    eve.cmd_flashspirx(0, 3)
    eve.finish()
    print repr(array.array('B', eve.rdstr(0, 3)).tolist())
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #5 on: January 20, 2021, 02:19:04 PM »

I might be wrong there but I believe there is no way to read any of the registers from the connected flash chip.
Yes, there are the commands CMD_FLASHSPITX and CMD_FLASHSPIRX but there is no way to control the chip-select line.

Well, there is CMD_FLASHSPIDESEL but there is no CMD_FLASHSPISEL.
I could not find anything in the documented registers to control SPIM_SS_N.

So without modifying the hardware (or maybe additional documentation) to allow control over the chip-select line it is only possible to read the content of the attached flash chip thru the flash driver with CMD_FLASHREAD.

I was thinking, CMD_FLASHSPITX and CMD_FLASHSPIRX, automatically drive the CS line low and CMD_FLASHSPIDESEL is used to drive it high, but just like you I couldn't find anything to confirm
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #6 on: January 20, 2021, 02:21:18 PM »

I have no experience with python. Can you provide code in c? preferably using the Gameduino library

Here is an example code in python to access the registers of flash:
Code: [Select]
def bb(*b):
    return pad4(array.array('B', b).tostring())

def txrx(eve, txpart, n_rx):
    eve.cmd_flashspidesel()
    eve.cmd_flashspitx(len(txpart))
    eve.c(bb(*txpart))
    eve.cmd_flashspirx(0, n_rx)
    if n_rx:
        eve.finish()
        return array.array('B', eve.rdstr(0, n_rx))

def do_sfdp(eve):
    """ Dump the SFDP area in binary """
    eve.cmd_flashdetach()
    eve.cmd_flashspidesel()

    eve.cmd_flashspitx(1)
    eve.c(bb(0x9f))
    eve.cmd_flashspirx(0, 3)
    eve.finish()
    print repr(array.array('B', eve.rdstr(0, 3)).tolist())
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 733
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #7 on: January 20, 2021, 04:43:51 PM »

Hello,

I believe what you have here is essentially correct:
I tried the following code

 
Code: [Select]
GD.cmd_flashdetach();
  GD.cmd_flashspidesel();
  GD.cmd_flashspitx(4);
  GD.cmd32(0x90);

  GD.cmd_flashspirx(0,2);
  delay(20);
  Serial.println(GD.rd(0));

and
Code: [Select]
Serial.println(GD.rd(0)); is still reading FF or 255

Could you just clarify is GD.cmd32 is writing to RAM_CMD (I believe it does)?
Also does the GD.rd function definitely read from RAM_G?
And could you try calling it with the address bytes also? (GD.cmd32(0x90000000))

Essentially the steps are as follows:
  • Call CMD_FLASHDETACH
  • Call CMD_FLASHSPIDESEL
  • Call CMD_FLAHSSPITX with the number of bytes you want to read
  • Write the desired bytes to be transmitted into RAM_CMD
  • Call CMD_FLASHSPIRX with the location in RAM_G you wish to read the data to, and the number of bytes to be read
  • Read the data from RAM_G

Best Regards,
BRT community
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #8 on: January 20, 2021, 10:38:44 PM »

The problem is that the flash memory is not getting detached.
I ran the following code to read the status of the flash memory
Code: [Select]
Serial.println(GD.rd(REG_FLASH_STATUS));
  GD.cmd_flashdetach();
  Serial.println(GD.rd(REG_FLASH_STATUS));

The output I'm getting is
2
2

It should be 2 and 1.
2 standing for BASIC and 1 standing for DETACHED

The layout of my cmd_flashdetach command is:
Code: [Select]
void GDClass::cmd_flashdetach() {
  cFFFFFF(0x48);
}

Running cmd_logo for example works and it has the same layout
Code: [Select]
void GDClass::cmd_logo(){
  cFFFFFF(0x31);
}

If I try to run
Code: [Select]
Serial.println(GD.rd(REG_FLASH_STATUS));
  GD.wr(REG_FLASH_STATUS,1);               //writes a byte to REG_FLASH_STATUS
  Serial.println(GD.rd(REG_FLASH_STATUS));
Then the status of the flash memory is correct and the output is as follows
2
1

Can you confirm that this is not an issue? because I tried using different PCBs

Hello,

I believe what you have here is essentially correct:
I tried the following code

 
Code: [Select]
GD.cmd_flashdetach();
  GD.cmd_flashspidesel();
  GD.cmd_flashspitx(4);
  GD.cmd32(0x90);

  GD.cmd_flashspirx(0,2);
  delay(20);
  Serial.println(GD.rd(0));

and
Code: [Select]
Serial.println(GD.rd(0)); is still reading FF or 255

Could you just clarify is GD.cmd32 is writing to RAM_CMD (I believe it does)?
Also does the GD.rd function definitely read from RAM_G?
And could you try calling it with the address bytes also? (GD.cmd32(0x90000000))

Essentially the steps are as follows:
  • Call CMD_FLASHDETACH
  • Call CMD_FLASHSPIDESEL
  • Call CMD_FLAHSSPITX with the number of bytes you want to read
  • Write the desired bytes to be transmitted into RAM_CMD
  • Call CMD_FLASHSPIRX with the location in RAM_G you wish to read the data to, and the number of bytes to be read
  • Read the data from RAM_G

Best Regards,
BRT community
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 733
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #9 on: January 21, 2021, 12:22:38 PM »

Hello,

Yes, the flash must be in a detached state before you can make use of the CMD_FLAHSSPITX and CMD_FLAHSSPIRX calls. I believe however the CMD_FLASHDETACH command must execute correctly in the first instance and it is not possible to simply rewrite the value stored in REG_FLASHSTATUS to alter the flash state.

If you add a delay between the detach call and the reading of the flash status register, does the value change accordingly:

The problem is that the flash memory is not getting detached.
Code: [Select]
Serial.println(GD.rd(REG_FLASH_STATUS));
  GD.cmd_flashdetach();
  Serial.println(GD.rd(REG_FLASH_STATUS));

Also do you have a logic analyser to hand? and would it be possible for you to take a SPI trace of CMD_FLASHDETACH command executing?

Best Regards,
BRT Community
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #10 on: January 21, 2021, 02:35:35 PM »

Hello

I took screenshots from a logic analyzer of the following code
Code: [Select]
  delay(100);
  Serial.println(GD.rd(REG_FLASH_STATUS));
  GD.cmd_flashdetach();
  Serial.println(GD.rd(REG_FLASH_STATUS));

In the attachments, GD.rd(REG_FLASH_STATUS).JPG shows the logic when I send   Serial.println(GD.rd(REG_FLASH_STATUS));

and GD.cmd_flashdetach().JPG shows the logic when I send GD.cmd_flashdetach() and Serial.println(GD.rd(REG_FLASH_STATUS)) after that.

I noticed there is some random logic after I send Serial.println(GD.rd(REG_FLASH_STATUS))
The logic analyzer reads B0 81 CC after reading the REG_FLASH_STATUS and I don't know why that is.

Here is the layout of my GD.rd() function
Code: [Select]
byte GDClass::rd(uint32_t addr) {
  return GDTR.rd(addr);
}

Code: [Select]
  byte rd(uint32_t addr)
  {
    __end(); // stop streaming
    __start(addr);
    SPI.transfer(0);  // dummy
    byte r = SPI.transfer(0);
    stream();
    return r;
  }

Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #11 on: January 21, 2021, 09:40:34 PM »

Okay, I just tried it instead of wondering about the documentation and it works.  :)

I have a W25Q64 on the display that I have on my desk right now.
So the answer to command 0x90 is: 0xef 0x16
And to make sure it is really working I also tried the JEDEC command 0x9f and it returns: 0xef 0x40 0x17
Which is also correct.

Here is my somewhat ugly test code:

Code: [Select]
EVE_cmd_flashdetach();
EVE_cmd_flashspidesel();
uint8_t tx_data[] = {0x90, 0, 0, 0, 0, 0};
EVE_cmd_flashspitx(4, tx_data);
EVE_cmd_flashspirx(0x000f5000, 2);
EVE_cmd_flashspidesel();

tx_data[0] = 0x9f;
EVE_cmd_flashspitx(1, tx_data);
EVE_cmd_flashspirx(0x000f5002, 3);

EVE_cmd_flashattach();

flash_data[0] = EVE_memRead8(0x000f5000);
flash_data[1] = EVE_memRead8(0x000f5001);
flash_data[2] = EVE_memRead8(0x000f5002);
flash_data[3] = EVE_memRead8(0x000f5003);
flash_data[4] = EVE_memRead8(0x000f5004);

Note the second EVE_cmd_flashspidesel() after the first command,
without this it is not working.

Edit: what I meant is that the second command is not working without it,
"this" as in this sequence of two commands, sorry.
The first command with cmd_flashspitx()/cmd_flashspirx() on its own is fine without it.

So cmd_flashspitx /  cmd_flashspirx automatically set the CS line to low and leave it there.
I believe this would be something worth mentioning in the programming manual.
But so far I never tried to use this.
And apparently nobody else did, at least not with my library as the EVE_cmd_flashspirx()
I implemented back in march 2019 was using CMD_FLASHREAD as I found out today - ouch. :-)


And I just displayed it with these lines:
Code: [Select]
EVE_cmd_text_var_burst(20, 100, 28, EVE_OPT_FORMAT, "Flash-Data 0x90: 0x%02x 0x%02x", 2, flash_data[0], flash_data[1]);
EVE_cmd_text_var_burst(20, 120, 28, EVE_OPT_FORMAT, "Flash-Data 0x9f: 0x%02x 0x%02x 0x%02x", 3, flash_data[2], flash_data[3], flash_data[4]);


Now I am not really sure what this is actually good for.
One thing that might come in handy is that these chips have a 64 bit ID that is at least unique within W25Q64JV.


https://github.com/RudolphRiedel/FT800-FT813
« Last Edit: January 22, 2021, 06:09:58 PM by Rudolph »
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 733
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #12 on: January 22, 2021, 05:08:10 PM »

Hello,

Hello

I took screenshots from a logic analyzer of the following code
Code: [Select]
  delay(100);
  Serial.println(GD.rd(REG_FLASH_STATUS));
  GD.cmd_flashdetach();
  Serial.println(GD.rd(REG_FLASH_STATUS));

In the attachments, GD.rd(REG_FLASH_STATUS).JPG shows the logic when I send   Serial.println(GD.rd(REG_FLASH_STATUS));

and GD.cmd_flashdetach().JPG shows the logic when I send GD.cmd_flashdetach() and Serial.println(GD.rd(REG_FLASH_STATUS)) after that.

I noticed there is some random logic after I send Serial.println(GD.rd(REG_FLASH_STATUS))
The logic analyzer reads B0 81 CC after reading the REG_FLASH_STATUS and I don't know why that is.

Here is the layout of my GD.rd() function
Code: [Select]
byte GDClass::rd(uint32_t addr) {
  return GDTR.rd(addr);
}

Code: [Select]
  byte rd(uint32_t addr)
  {
    __end(); // stop streaming
    __start(addr);
    SPI.transfer(0);  // dummy
    byte r = SPI.transfer(0);
    stream();
    return r;
  }

Thanks for the screenshots, it looks as if the registers is being read correctly.
And the CMD_FLASHDETACH command does also seem to being written correctly.

The B0 81 CC is the RAM_CMD address that the CMD_FLASHDETACH command is being written to (0x3081CC, with the write bit enabled). This would indicate you have sent several other co-processor commands before issuing the CMD_FLASH command. It also appears if you are writing some display list commands into RAM_CMD immediately after reading REG_FLASH_STATUS for the second time.

Would it be possible for you to minimise the number of co-processor calls before attempting to send the CMD_FLASHDETACH command? And if possible could you implement a method similar to below to await the command FIFO executing the command before attempting to read REG_FLASH_STATUS again?

Code: [Select]
uint8_t HAL_WaitCmdFifoEmpty(void)
{
uint32_t readCmdPointer;

// Wait until the two registers match
do
{
// Read the graphics processor read pointer
readCmdPointer = HAL_MemRead32(EVE_REG_CMD_READ);

} while ((writeCmdPointer != readCmdPointer) && (readCmdPointer != 0xFFF));


if(readCmdPointer == 0xFFF)
{
// Return 0xFF if an error occurred
return 0xFF;
}
else
{
// Return 0 if pointers became equal successfully
return 0;
}
}

This should ensure the command has executed in the co-processor before you attempt to read what hopefully should be an updated register.

Also thank you Rudolph for giving that a try, his suggestion of calling CMD_FLASHSPIDESEL may also be useful in your scenario.

Best Regards,
BRT Community
Logged

SpicyChef

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #13 on: January 25, 2021, 05:42:12 PM »

@Rudolph

Your library helped me understand what I was doing wrong.
I was sending CMD_FLASHDETACH() without the B0 25 78 in the screenshot attached.
Which references [ 302578h REG_CMDB_WRITE  ] in BT817. Doing this is not discussed in the programming manual, so how are programmers supposed to know?


Since I was reading the correct REG_FLASH_STATUS with your library, I decided to copy your code and try it.
I made some adjustments and here is the code I used

Code: [Select]
EVE_cmd_flashdetach();
EVE_cmd_flashspidesel();
uint8_t tx_data[] = {0x90, 0, 0, 0, 0, 0};
EVE_cmd_flashspitx(4, tx_data);
EVE_cmd_flashspirx(0x00, 2);
EVE_cmd_flashspidesel();

Serial.println(EVE_memRead8(0x00));

When I run it. The serial monitor doesn't show anything and It seems like the code is getting stuck at EVE_cmd_flashspirx(). This function keeps doing something and is preventing the rest of the code from executing.
When I comment it out, the rest of the code executes.
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: why can't I read the Manufacturer/Device ID?
« Reply #14 on: January 26, 2021, 08:15:58 PM »

I was sending CMD_FLASHDETACH() without the B0 25 78 in the screenshot attached.
Which references [ 302578h REG_CMDB_WRITE  ] in BT817. Doing this is not discussed in the programming manual, so how are programmers supposed to know?

Well, I am doing this for a couple of years now which makes it difficult to see this with the perspective
of someone who has not. :-)
It is all there in the programming guide but perhaps a bit much alltogether.


Okay, there are several layers and you probably got most of this sorted out already.
But maybe this will help you a litte bit and maybe a little more when others come across this.

At the very base EVE only has three functions, Host Memory Read, Host Memory Write and Host command.
The first two bits on the SPI tell EVE what is what.
00 - Read
10 - Write
01 - Command

Read and Write are followed by a 22-bit address with the most significant bit first.
Command is followed by 6 bits for the actual command and two bytes for parameters.

So apart from a handfull of basic commands like ACTIVE, CLKEXT, PINDRIVE and so on,
everything is done by writing to or reading from EVEs memory.

The memory map shows these regions and give a hint for their purpose.
The main regions are RAM_G, which is our graphics RAM, RAM_DL which is where the display-list commands are written to, RAM_REG for the registers and RAM_CMD to which coprocessor commands needs to be written so that the co-processor can execute them.

Chapter 1.4 of the BT81x programming guide has an API reference.
There are memory read/write functions.
The cmd() and cmd_*() functions write to RAM_CMD.
The dl() functions are the ones that are executed in RAM_DL.
And host_command() functions are just that.

So, my library is not writing the commands to RAM_CMD, it is writing all commands to REG_CMDB_WRITE instead.
This register was introduced with the FT81x and it really makes things less complicated.
In a nutshell everytime a 32 bit word is written to REG_CMDB_WRITE it is written to the next position in RAM_CMD.
The coprocessor commands written this way are executed automatically.
And you can write almost 4k, the size of RAM_CMD, as one stream of 32 bit words with only sending the address of REG_CMDB_WRITE at the beginning.

My library is also not writing to RAM_DL, it uses the coprocessor to do that.
Letting the coprocessor build the display list is a lot easier and quicker, all the widgets like CMD_TEXT or CMD_BUTTON are coprocessor commands and the coprocessor generates quite some amount of display list commands depending on the widget.

Quote
Since I was reading the correct REG_FLASH_STATUS with your library, I decided to copy your code and try it.
I made some adjustments and here is the code I used

Code: [Select]
EVE_cmd_flashdetach();
EVE_cmd_flashspidesel();
uint8_t tx_data[] = {0x90, 0, 0, 0, 0, 0};
EVE_cmd_flashspitx(4, tx_data);
EVE_cmd_flashspirx(0x00, 2);
EVE_cmd_flashspidesel();

Serial.println(EVE_memRead8(0x00));

When I run it. The serial monitor doesn't show anything and It seems like the code is getting stuck at EVE_cmd_flashspirx(). This function keeps doing something and is preventing the rest of the code from executing.
When I comment it out, the rest of the code executes.

What did you adjust and what does the rest of the SPI look like?

If you look at my basic example, I have this in TFT_init():
Code: [Select]
void TFT_init(void)
{
if(EVE_init() != 0)
{
tft_active = 1;

EVE_memWrite8(REG_PWM_DUTY, 0x30); /* setup backlight, range is from 0 = off to 0x80 = max */
touch_calibrate();

EVE_cmd_flashdetach();
EVE_cmd_flashspidesel();
uint8_t tx_data[] = {0x90, 0, 0, 0, 0, 0};
EVE_cmd_flashspitx(4, tx_data);
EVE_cmd_flashspirx(0x000f5000, 2);

So after EVE_init() the display is up and running with an mostly empty display list.
The next thing my code does is to fully initialize the flash and read from it,
follwed by writing image data to RAM_G.
Logged
Pages: [1] 2