Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8cb296c6fee0
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 78f3629a8f37
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Sep 4, 2020

  1. Copy the full SHA
    78f3629 View commit details
Showing with 157 additions and 7 deletions.
  1. +142 −7 scopeprotocols/SPIFlashDecoder.cpp
  2. +15 −0 scopeprotocols/SPIFlashDecoder.h
149 changes: 142 additions & 7 deletions scopeprotocols/SPIFlashDecoder.cpp
Original file line number Diff line number Diff line change
@@ -195,7 +195,8 @@ void SPIFlashDecoder::Refresh()
//Read the IDCODE
case 0x9f:
current_cmd = SPIFlashSymbol::CMD_READ_JEDEC_ID;
state = STATE_READ_DATA;
state = STATE_DUMMY_BEFORE_DATA;
data_type = SPIFlashSymbol::TYPE_VENDOR_ID;
break;

//Read the status register
@@ -409,25 +410,61 @@ void SPIFlashDecoder::Refresh()
{
//At the end of a read command, crack status registers if needed
if(data_type != SPIFlashSymbol::TYPE_DATA)
pack->m_headers["Info"] = GetText(cap->m_samples.size()-1);
{
//If ID code, crack both
if(data_type == SPIFlashSymbol::TYPE_PART_ID)
{
pack->m_headers["Info"] +=
GetText(cap->m_samples.size()-2) +
" " +
GetText(cap->m_samples.size()-1);
}
else
pack->m_headers["Info"] = GetText(cap->m_samples.size()-1);
}

state = STATE_IDLE;
}
else
{
cap->m_offsets.push_back(dout->m_offsets[iin]);
cap->m_durations.push_back(dout->m_durations[iin]);
cap->m_samples.push_back(SPIFlashSymbol(
data_type, SPIFlashSymbol::CMD_UNKNOWN, dout->m_samples[iin].m_data));
//See what the last sample we produced was
//If it was a part ID, just append to it
size_t pos = cap->m_samples.size() - 1;
if( (data_type == SPIFlashSymbol::TYPE_PART_ID) &
(cap->m_samples[pos].m_type == SPIFlashSymbol::TYPE_PART_ID) )
{
cap->m_samples[pos].m_data = (cap->m_samples[pos].m_data << 8) | dout->m_samples[iin].m_data;
}

//Normal data
else
{
cap->m_offsets.push_back(dout->m_offsets[iin]);
cap->m_durations.push_back(dout->m_durations[iin]);
cap->m_samples.push_back(SPIFlashSymbol(
data_type, SPIFlashSymbol::CMD_UNKNOWN, dout->m_samples[iin].m_data));
}

//Extend the packet
pack->m_data.push_back(dout->m_samples[iin].m_data);
pack->m_len = dout->m_offsets[iin] + dout->m_durations[iin] - pack->m_offset;
char tmp[128];
snprintf(tmp, sizeof(tmp), "%zu", pack->m_data.size());
pack->m_headers["Len"] = tmp;

//If reading multibyte special value (vendor ID etc), handle that
switch(data_type)
{
case SPIFlashSymbol::TYPE_VENDOR_ID:
data_type = SPIFlashSymbol::TYPE_PART_ID;
break;

default:
break;
}
}
break;

break; //STATE_READ_DATA

//Read data in quad mode
case STATE_READ_QUAD_DATA:
@@ -526,6 +563,8 @@ Gdk::Color SPIFlashDecoder::GetColor(int i)
return m_standardColors[COLOR_ADDRESS];

case SPIFlashSymbol::TYPE_DATA:
case SPIFlashSymbol::TYPE_VENDOR_ID:
case SPIFlashSymbol::TYPE_PART_ID:
case SPIFlashSymbol::TYPE_W25N_SR_CONFIG:
case SPIFlashSymbol::TYPE_W25N_SR_PROT:
case SPIFlashSymbol::TYPE_W25N_SR_STATUS:
@@ -552,6 +591,26 @@ string SPIFlashDecoder::GetText(int i)
case SPIFlashSymbol::TYPE_DUMMY:
return "Wait state";

case SPIFlashSymbol::TYPE_VENDOR_ID:
switch(s.m_data)
{
case VENDOR_ID_CYPRESS:
return "Cypress";
case VENDOR_ID_MICRON:
return "Micron";
case VENDOR_ID_WINBOND:
return "Winbond";

default:
snprintf(tmp, sizeof(tmp), "0x%x", s.m_data);
break;
}
break;

//Part ID depends on vendor ID
case SPIFlashSymbol::TYPE_PART_ID:
return GetPartID(capture, s, i);

case SPIFlashSymbol::TYPE_COMMAND:
switch(s.m_cmd)
{
@@ -677,3 +736,79 @@ string SPIFlashDecoder::GetText(int i)
}
return "";
}

string SPIFlashDecoder::GetPartID(SPIFlashWaveform* cap, const SPIFlashSymbol& s, int i)
{
char tmp[128];

//Look up the vendor ID
auto ivendor = cap->m_samples[i-1];
switch(ivendor.m_data)
{
case VENDOR_ID_CYPRESS:
switch(s.m_data)
{
//QSPI NOR
case 0x0217:
return "S25FS064x";

default:
snprintf(tmp, sizeof(tmp), "%x", s.m_data);
return tmp;
}
break;

case VENDOR_ID_MICRON:
switch(s.m_data)
{
//(Q)SPI NOR
case 0x2014:
return "M25P80";
case 0x2018:
return "M25P128";
case 0x7114:
return "M25PX80";
case 0x8014:
return "M25PE80";
case 0xba19:
return "N25Q256x";
case 0xbb18:
return "N25Q128x";

default:
snprintf(tmp, sizeof(tmp), "%x", s.m_data);
return tmp;
}
break;

case VENDOR_ID_WINBOND:
switch(s.m_data)
{
//QSPI NOR
case 0x4014:
return "W25Q80xx";
case 0x4018:
return "W25Q128xx";
case 0x6015:
return "W25Q16xx";
case 0x6016:
return "W25Q32xx";
case 0x6018:
return "W25Q128xx (QPI mode)";

//QSPI NAND
case 0xaa21:
return "W25N01GV";

default:
snprintf(tmp, sizeof(tmp), "%x", s.m_data);
return tmp;
}
break;

//Unknown vendor, print part number as hex
default:
snprintf(tmp, sizeof(tmp), "%x", s.m_data);
return tmp;
}
}
15 changes: 15 additions & 0 deletions scopeprotocols/SPIFlashDecoder.h
Original file line number Diff line number Diff line change
@@ -43,12 +43,17 @@ class SPIFlashSymbol

enum FlashType
{
//Generic
TYPE_COMMAND,
TYPE_ADDRESS,
TYPE_DATA,

TYPE_DUMMY,

//ID codes
TYPE_VENDOR_ID,
TYPE_PART_ID,

//Winbond W25N specific
TYPE_W25N_BLOCK_ADDR,
TYPE_W25N_SR_ADDR, //address of a status register
@@ -113,7 +118,17 @@ class SPIFlashDecoder : public PacketDecoder

virtual bool ValidateChannel(size_t i, StreamDescriptor stream);

enum VendorIDs
{
VENDOR_ID_CYPRESS = 0x01,
VENDOR_ID_MICRON = 0x20,
VENDOR_ID_WINBOND = 0xef
};

PROTOCOL_DECODER_INITPROC(SPIFlashDecoder)

protected:
std::string GetPartID(SPIFlashWaveform* cap, const SPIFlashSymbol& s, int i);
};

#endif