Skip to content

Commit

Permalink
STM32Device now has proper SerialNumberedDevice support
Browse files Browse the repository at this point in the history
  • Loading branch information
azonenberg committed Jul 10, 2018
1 parent 269a0d6 commit a80961a
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 37 deletions.
29 changes: 2 additions & 27 deletions JtagDevice.cpp
Expand Up @@ -401,33 +401,8 @@ void JtagDevice::PrintInfo()
if(!skipRead)
{
LogIndenter li;
int len = pserial->GetSerialNumberLength();
int bitlen = pserial->GetSerialNumberLengthBits();
unsigned char* serial = new unsigned char[len];
memset(serial, 0, len);
pserial->GetSerialNumber(serial);

LogNotice("Device has unique serial number (%d bits long)\n", bitlen);

string serial_binary;
for(int j=0; j<bitlen; j++)
{
if(PeekBit(serial, j))
serial_binary += "1";
else
serial_binary += "0";
}

string serial_hex;
char tmp[3];
for(int j=0; j<len; j++)
{
snprintf(tmp, sizeof(tmp), "%02x", 0xff & serial[j]);
serial_hex += tmp;
}
delete[] serial;

LogNotice("Device serial number is %s = 0x%s\n", serial_binary.c_str(), serial_hex.c_str());
LogNotice("Device has unique serial number (%d bits long)\n", pserial->GetSerialNumberLengthBits());
LogNotice("%s\n", pserial->GetPrettyPrintedSerialNumber().c_str() );
}
}
}
59 changes: 52 additions & 7 deletions STM32Device.cpp
Expand Up @@ -64,14 +64,14 @@ STM32Device::STM32Device(
"");
}

uint32_t id = m_dap->ReadMemory(0xe0042000);
LogDebug("id = %08x\n", id);
//uint32_t id = m_dap->ReadMemory(0xe0042000);
//LogDebug("id = %08x\n", id);

//Extract serial number fields
uint32_t serial[3];
serial[0] = m_dap->ReadMemory(0x1fff7a10); //xy
serial[1] = m_dap->ReadMemory(0x1fff7a14); //lot, wafnum
serial[2] = m_dap->ReadMemory(0x1fff7a18); //lot

serial[0] = m_dap->ReadMemory(0x1fff7a10);
serial[1] = m_dap->ReadMemory(0x1fff7a14);
serial[2] = m_dap->ReadMemory(0x1fff7a18);
m_waferX = serial[0] >> 16;
m_waferY = serial[0] & 0xffff;
m_waferNum = serial[1] & 0xff;
Expand All @@ -83,7 +83,13 @@ STM32Device::STM32Device(
m_waferLot[5] = (serial[2] >> 8) & 0xff;
m_waferLot[6] = (serial[2] >> 0) & 0xff;
m_waferLot[7] = 0;
LogDebug("WaferX/Y %d %d, wafer %d of lot %s\n", m_waferX, m_waferY, m_waferNum, m_waferLot);
m_serialRaw[0] = m_waferX >> 8;
m_serialRaw[1] = m_waferX & 0xff;
m_serialRaw[2] = m_waferY >> 8;
m_serialRaw[3] = m_waferY & 0xff;
m_serialRaw[4] = m_waferNum;
for(int i=0; i<7; i++)
m_serialRaw[5+i] = m_waferLot[i];

//Look up size of flash memory
m_flashKB = m_dap->ReadMemory(0x1fff7a20) >> 16; //F_ID, flash size in kbytes
Expand Down Expand Up @@ -114,6 +120,42 @@ JtagDevice* STM32Device::CreateDevice(
return new STM32Device(devid, stepping, idcode, iface, pos);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Device property queries

bool STM32Device::ReadingSerialRequiresReset()
{
return false;
}

int STM32Device::GetSerialNumberLength()
{
return 12;
}

int STM32Device::GetSerialNumberLengthBits()
{
return 96;
}

void STM32Device::GetSerialNumber(unsigned char* data)
{
for(int i=0; i<12; i++)
data[i] = m_serialRaw[i];
}

string STM32Device::GetPrettyPrintedSerialNumber()
{
char tmp[256];
snprintf(tmp, sizeof(tmp),
"Die (%d, %d), wafer %d, lot %s",
m_waferX, m_waferY,
m_waferNum,
m_waferLot);

return string(tmp);
}

string STM32Device::GetDescription()
{
string name = "(unknown STM32";
Expand Down Expand Up @@ -150,6 +192,9 @@ bool STM32Device::IsProgrammed()
return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programming

void STM32Device::Erase()
{
LogWarning("STM32Device::Erase() not implemented\n");
Expand Down
11 changes: 11 additions & 0 deletions STM32Device.h
Expand Up @@ -49,6 +49,7 @@
class STM32Device
: public STMicroMicrocontroller
, public JtagDevice
, public SerialNumberedDevice
{
public:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -81,6 +82,15 @@ class STM32Device

virtual void Program(FirmwareImage* image);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Serial numbering

virtual bool ReadingSerialRequiresReset();
virtual int GetSerialNumberLength();
virtual int GetSerialNumberLengthBits();
virtual void GetSerialNumber(unsigned char* data);
virtual std::string GetPrettyPrintedSerialNumber();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// No NoC interfaces

Expand All @@ -104,6 +114,7 @@ class STM32Device
uint32_t m_waferY;
int m_waferNum;
char m_waferLot[8];
uint8_t m_serialRaw[12];
};

#endif
34 changes: 34 additions & 0 deletions SerialNumberedDevice.cpp
Expand Up @@ -48,3 +48,37 @@ SerialNumberedDevice::~SerialNumberedDevice()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pretty-printing

string SerialNumberedDevice::GetPrettyPrintedSerialNumber()
{
int len = GetSerialNumberLength();
int bitlen = GetSerialNumberLengthBits();
unsigned char* serial = new unsigned char[len];
memset(serial, 0, len);
GetSerialNumber(serial);

/*
string serial_binary;
for(int j=0; j<bitlen; j++)
{
if(PeekBit(serial, j))
serial_binary += "1";
else
serial_binary += "0";
}
*/

string serial_hex;
char tmp[3];
for(int j=0; j<len; j++)
{
snprintf(tmp, sizeof(tmp), "%02x", 0xff & serial[j]);
serial_hex += tmp;
}
delete[] serial;

//LogNotice("Device serial number is %s = 0x%s\n", serial_binary.c_str(), serial_hex.c_str());
return string("Serial number is 0x") + serial_hex;
}
16 changes: 13 additions & 3 deletions SerialNumberedDevice.h
Expand Up @@ -55,21 +55,21 @@ class SerialNumberedDevice
virtual bool ReadingSerialRequiresReset() = 0;

/**
@brief Gets the length of the FPGA's unique serial number, in bytes (rounded up to the nearest whole byte).
@brief Gets the length of the device's unique serial number, in bytes (rounded up to the nearest whole byte).
@return Serial number length
*/
virtual int GetSerialNumberLength() =0;

/**
@brief Gets the length of the FPGA's unique serial number, in bits.
@brief Gets the length of the device's unique serial number, in bits.
@return Serial number length
*/
virtual int GetSerialNumberLengthBits() =0;

/**
@brief Gets the FPGA's unique serial number.
@brief Gets the device's unique serial number.
Note that some architectures, such as Spartan-6, cannot read the serial number over JTAG without erasing the
FPGA configuration. If this is the case, calling this function will automatically erase the FPGA.
Expand All @@ -82,6 +82,16 @@ class SerialNumberedDevice
GetSerialNumberLength().
*/
virtual void GetSerialNumber(unsigned char* data) =0;

/**
@brief Returns a pretty-printed serial number
Most serial numbers have no inherent meaning but some contain encoded lot numbers etc.
This function returns a human-readable version of the serial number, if such exists. Otherwise,
a hex encoding of GetSerialNumber() is returned.
*/
virtual std::string GetPrettyPrintedSerialNumber();
};

#endif
Expand Down

0 comments on commit a80961a

Please sign in to comment.