Skip to content

Commit 0a2d144

Browse files
authored
Merge pull request #9 from 1a2m3/1a2m3-patch-20211201
1a2m3 patch 20211206
2 parents 54f283f + d36895d commit 0a2d144

File tree

6 files changed

+141
-60
lines changed

6 files changed

+141
-60
lines changed

firmware/SpdReaderWriter.ino

Lines changed: 73 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <EEPROM.h>
1717
#include "SpdReaderWriterSettings.h" // Settings
1818

19-
#define VERSION 20211202 // Version number (YYYYMMDD)
19+
#define VERSION 20211206 // Version number (YYYYMMDD)
2020

2121
// RSWP RAM support bitmasks
2222
#define DDR5 (1 << 5) // Offline mode control
@@ -60,12 +60,12 @@
6060
#define RPS2 0x6B // Read SWP2 status (addresses 100h to 17Fh) (256-383) (DDR4)
6161
#define RPS3 0x61 // Read SWP3 status (addresses 180h to 1FFh) (384-511) (DDR4)
6262

63-
#define SWP0 0x62 // Set RSWP for block 0 (addresses 00h to 7Fh) ( 0-127) (DDR4/DDR3/DDR2)
63+
#define SWP0 0x62 // Set RSWP for block 0 (addresses 00h to 7Fh) ( 0-127) (DDR4/DDR3/DDR2) *
6464
#define SWP1 0x68 // Set RSWP for block 1 (addresses 80h to FFh) (128-255) (DDR4)
6565
#define SWP2 0x6A // Set RSWP for block 2 (addresses 100h to 17Fh) (256-383) (DDR4)
66-
#define SWP3 0x60 // Set RSWP for block 3 (addresses 180h to 1FFh) (384-511) (DDR4)
66+
#define SWP3 0x60 // Set RSWP for block 3 (addresses 180h to 1FFh) (384-511) (DDR4) *
6767

68-
#define CWP 0x66 // Clear RSWP (DDR4/DDR3/DDR2)
68+
#define CWP 0x66 // Clear RSWP (DDR4/DDR3/DDR2) *
6969
#pragma endregion
7070

7171
// EEPROM PSWP commands
@@ -123,11 +123,15 @@
123123
#define GET (char) '?' // Suffix added to commands to return current state
124124

125125
// Device responses
126-
#define SUCCESS (byte) 0x01
127-
#define ERROR (byte) 0xFF
128-
#define ZERO (byte) 0x00
129-
#define WELCOME (char) '!'
130-
#define UNKNOWN (char) '?'
126+
#define SUCCESS (byte) 0x01
127+
#define ENABLED (byte) 0x01
128+
#define ACK (byte) 0x01
129+
#define ZERO (byte) 0x00
130+
#define DISABLED (byte) 0x00
131+
#define NACK (byte) 0xFF
132+
#define ERROR (byte) 0xFF
133+
#define WELCOME (char) '!'
134+
#define UNKNOWN (char) '?'
131135

132136
// Device name settings
133137
#define NAMELENGTH 16
@@ -179,7 +183,7 @@ void setup() {
179183
while (!PORT) {}
180184

181185
// Send a welcome byte when the device is ready
182-
PORT.write(WELCOME);
186+
cmdTest();
183187
}
184188

185189
void loop() {
@@ -366,7 +370,11 @@ void cmdScanBus() {
366370
}
367371

368372
void cmdTest() {
373+
#ifdef __AVR__
369374
PORT.write(WELCOME);
375+
#else
376+
PORT.write(UNKNOWN);
377+
#endif
370378
}
371379

372380
void cmdRswpReport() {
@@ -483,13 +491,13 @@ void cmdRSWP() {
483491
if (state == ENABLE) {
484492
PORT.write(setRswp(block) ? SUCCESS : ERROR);
485493
}
486-
// clear RSWP (block number is ignored)
494+
// clear RSWP (all blocks)
487495
else if (state == DISABLE) {
488496
PORT.write(clearRswp() ? SUCCESS : ERROR);
489497
}
490498
// get RSWP status
491499
else if (state == GET) {
492-
PORT.write(getRswp(block) ? SUCCESS : ERROR);
500+
PORT.write(getRswp(block) ? ENABLED : DISABLED);
493501
}
494502
// unrecognized RSWP command
495503
else {
@@ -514,7 +522,7 @@ void cmdPSWP() {
514522
}
515523
// read PSWP
516524
else if (state == GET) {
517-
PORT.write(getPswp(address) ? SUCCESS : ERROR);
525+
PORT.write(getPswp(address) ? ENABLED : DISABLED);
518526
}
519527
// unknown state
520528
else {
@@ -553,7 +561,7 @@ void cmdPinControl() {
553561
// Toggle SA1 state
554562
if (state == ENABLE || state == DISABLE) {
555563
setConfigPin(pins[pin], state);
556-
PORT.write(digitalRead(pins[pin]) == state ? SUCCESS : ERROR);
564+
PORT.write(getConfigPin(pins[pin]) == state ? SUCCESS : ERROR);
557565
}
558566
// Get SA1 state
559567
else if (state == GET) {
@@ -658,9 +666,17 @@ bool setRswp(uint8_t block) {
658666
byte commands[] = { SWP0, SWP1, SWP2, SWP3 };
659667
byte cmd = (block > 0 || block <= 3) ? commands[block] : commands[0];
660668

669+
bool ddr4 = ddr4Detect();
670+
bool result;
671+
661672
if (setHighVoltage(ON)) {
662673
setConfigPin(SA1_EN, OFF); // Required for pre-DDR4
663-
bool result = probeDeviceTypeId(cmd);
674+
if (block > 0 && !ddr4) {
675+
result = false;
676+
}
677+
else {
678+
result = probeDeviceTypeId(cmd);
679+
}
664680
resetPins();
665681

666682
return result;
@@ -680,18 +696,22 @@ bool getRswp(uint8_t block) {
680696
setHighVoltage(ON);
681697
}
682698

683-
bool status = probeDeviceTypeId(cmd);
699+
bool status = probeDeviceTypeId(cmd); // true/ack = not protected
684700

685701
resetPins();
686702

687-
return status; // true = unprotected; false = protected or rswp not supported
703+
return !status; // true = protected or rswp not supported; false = unprotected
688704
}
689705

690706
// Clears reversible software write protection
691707
bool clearRswp() {
692708

693-
if (setHighVoltage(ON)) {
694-
setConfigPin(SA1_EN, ON); // Required for pre-DDR4
709+
if (!ddr4Detect()) {
710+
// Required for pre-DDR4
711+
setConfigPin(SA1_EN, ON);
712+
}
713+
714+
if (setHighVoltage(ON)) {
695715
bool result = probeDeviceTypeId(CWP);
696716
resetPins();
697717

@@ -761,7 +781,7 @@ bool setHighVoltage(bool state) {
761781

762782
// Returns HV status by reading HV_FB
763783
bool getHighVoltage() {
764-
return digitalRead(HV_EN) && digitalRead(HV_FB);
784+
return getConfigPin(HV_EN) && getConfigPin(HV_FB);
765785
}
766786

767787

@@ -771,7 +791,7 @@ bool getHighVoltage() {
771791
bool setPswp(uint8_t deviceAddress) {
772792

773793
if (ddr4Detect(deviceAddress) || ddr5Detect(deviceAddress)) {
774-
return ERROR;
794+
return false;
775795
}
776796

777797
// Keep address bits (SA0-SA2) intact and change bits 7-4 to '0110'
@@ -782,7 +802,6 @@ bool setPswp(uint8_t deviceAddress) {
782802
Wire.write(DNC);
783803
Wire.write(DNC);
784804
int status = Wire.endTransmission();
785-
delay(10);
786805

787806
return status == 0;
788807

@@ -800,8 +819,7 @@ bool getPswp(uint8_t deviceAddress) {
800819
// Write 1 DNC byte to force LSB to set to 1
801820
Wire.write(DNC);
802821
int status = Wire.endTransmission();
803-
delay(10);
804-
822+
805823
return status == 0; // returns true if PSWP is not set
806824

807825
//uint8_t cmd = (deviceAddress & 0b111) << 1 | (PWPB << 4);
@@ -818,7 +836,7 @@ uint8_t getPageAddress(bool lowLevel = false) {
818836
return eepromPageAddress;
819837
}
820838

821-
#ifdef __AVR__
839+
//#ifdef __AVR__
822840

823841
uint8_t status = ERROR;
824842

@@ -862,7 +880,7 @@ uint8_t getPageAddress(bool lowLevel = false) {
862880
default: return status;
863881
}
864882

865-
#endif
883+
//#endif
866884

867885
// Non-AVR response
868886
return ERROR;
@@ -882,10 +900,11 @@ bool setPageAddress(uint8_t pageNumber) {
882900
// Adjusts page address according to byte offset specified
883901
void adjustPageAddress(uint8_t address, uint16_t offset) {
884902

885-
// Assume DDR4 is present, do not call ddr4Detect() for performance reasons
886-
if (offset < 512) {
887-
// Get offset MSB to see if it is below 0x100 or above 0xFF
888-
uint8_t page = offset >> 8; // DDR4 page
903+
uint8_t page;
904+
905+
// Assume DDR4 is present
906+
if (offset <= 256) {
907+
page = offset >> 8; // DDR4 page
889908
if (getPageAddress() != page) {
890909
setPageAddress(page);
891910
}
@@ -897,7 +916,7 @@ void adjustPageAddress(uint8_t address, uint16_t offset) {
897916
setLegacyModeAddress(address, false);
898917

899918
// Write page address to MR11[2:0]
900-
uint8_t page = offset >> 7; // DDR5 page
919+
page = offset >> 7; // DDR5 page
901920

902921
writeByte((MEMREG & address), (uint8_t)(MR11), (byte)(page));
903922
// TODO: TBT
@@ -986,11 +1005,21 @@ byte scanBus() {
9861005
// Control config pins
9871006
bool setConfigPin(uint8_t pin, bool state) {
9881007
digitalWrite(pin, state);
989-
return digitalRead(pin) == state;
1008+
if (pin == SA1_SWITCH) {
1009+
delay(5);
1010+
}
1011+
1012+
return getConfigPin(pin) == state;
9901013
}
9911014

9921015
// Get config pin state
9931016
bool getConfigPin(uint8_t pin) {
1017+
// SA1 state check
1018+
if (pin == SA1_SWITCH) {
1019+
byte _a1 = 0b11001100; // valid addresses bitmask when SA1 is high: 82-83, 86-87
1020+
return (digitalRead(pin) ? ((scanBus() & _a1)) : (scanBus() & ~_a1));
1021+
}
1022+
9941023
return digitalRead(pin);
9951024
}
9961025

@@ -1003,7 +1032,12 @@ void resetPins() {
10031032

10041033
// Toggle DDR5 offline mode
10051034
bool ddr5SetOfflineMode(bool state) {
1006-
digitalWrite(OFF_EN, state);
1035+
setConfigPin(OFF_EN, state);
1036+
if (state) {
1037+
// Set SDR-DDR4 to address 82-83 to avoid conflicts
1038+
setConfigPin(SA1_EN, state);
1039+
}
1040+
10071041
return ddr5GetOfflineMode() == state;
10081042
}
10091043

@@ -1046,13 +1080,17 @@ bool probeDeviceTypeId(uint8_t deviceSelectCode) {
10461080

10471081
// DDR4 detection test (address)
10481082
bool ddr4Detect(uint8_t address) {
1083+
if (address == 0) {
1084+
return ddr4Detect();
1085+
}
1086+
10491087
return probeBusAddress(address) && ddr4Detect();
10501088
}
10511089

10521090
// DDR4 detection test (generic)
10531091
bool ddr4Detect() {
1054-
return ((setPageAddress(0) ^ getPageAddress(true)) !=
1055-
(setPageAddress(1) ^ getPageAddress(true)));
1092+
// Only SPA0 is tested, RPA returns NACK after SPA1 regardless of RAM type
1093+
return setPageAddress(0) && getPageAddress(true) == 0;
10561094
}
10571095

10581096
// DDR5 detection test

src/SpdReaderWriterDll/Device.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ private UInt8[] ScanPrivate() {
778778
lock (PortLock) {
779779
try {
780780
if (IsConnected) {
781-
byte _response = Scan(true);
781+
byte _response = ScanPrivate(true);
782782

783783
if (_response == Response.NULL) {
784784
return new byte[0];

src/SpdReaderWriterDll/Eeprom.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public static bool SetRswp(Device device) {
242242
public static bool GetRswp(Device device) {
243243
try {
244244
for (UInt8 i = 0; i <= 3; i++) {
245-
if (device.ExecuteCommand(new[] { RSWP, i, GET }) == Response.NACK) {
245+
if (device.ExecuteCommand(new[] { RSWP, i, GET }) == Response.ENABLED) {
246246
return true;
247247
}
248248
}
@@ -262,7 +262,7 @@ public static bool GetRswp(Device device) {
262262
/// <returns><see langword="true" /> if the block is write protected (or RSWP is not supported) or <see langword="false" /> when the block is writable</returns>
263263
public static bool GetRswp(Device device, UInt8 block) {
264264
try {
265-
return device.ExecuteCommand(new[] { RSWP, block, GET }) == Response.NACK;
265+
return device.ExecuteCommand(new[] { RSWP, block, GET }) == Response.ENABLED;
266266
}
267267
catch {
268268
throw new Exception($"Unable to get block {block} RSWP status on {device.PortName}");
@@ -304,7 +304,7 @@ public static bool SetPswp(Device device) {
304304
/// <returns><see langword="true" /> when PSWP is enabled or <see langword="false" /> if when PSWP has NOT been set and EEPROM is writable</returns>
305305
public static bool GetPswp(Device device) {
306306
try {
307-
return device.ExecuteCommand(new[] { PSWP, device.I2CAddress, GET }) == Response.NACK;
307+
return device.ExecuteCommand(new[] { PSWP, device.I2CAddress, GET }) == Response.ENABLED;
308308
}
309309
catch {
310310
throw new Exception($"Unable to get PSWP status on {device.PortName}");

src/SpdReaderWriterDll/Response.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@ namespace SpdReaderWriterDll {
33
/// Class describing different responses received from the device
44
/// </summary>
55
public struct Response {
6-
/// <summary>
7-
/// Indicates the operation was executed successfully
8-
/// </summary>
9-
public const byte SUCCESS = 0x01;
10-
/// <summary>
11-
/// Indicates the operation has failed
12-
/// </summary>
13-
public const byte ERROR = 0xFF;
146
/// <summary>
157
/// Boolean True response
168
/// </summary>
@@ -20,12 +12,20 @@ public struct Response {
2012
/// </summary>
2113
public const byte FALSE = 0x00;
2214
/// <summary>
15+
/// Indicates the operation has failed
16+
/// </summary>
17+
public const byte ERROR = 0xFF;
18+
/// <summary>
19+
/// Indicates the operation was executed successfully
20+
/// </summary>
21+
public const byte SUCCESS = 0x01;
22+
/// <summary>
2323
/// A response used to indicate an error when normally a numeric non-zero answer is expected if the operation was executed successfully
2424
/// </summary>
2525
public const byte NULL = 0;
2626
/// <summary>
2727
/// A response used to describe when SA pin is tied to VCC
28-
/// </summary>
28+
/// </summary>
2929
public const byte ON = 1;
3030
/// <summary>
3131
/// A response used to describe when SA pin is tied to GND
@@ -41,10 +41,12 @@ public struct Response {
4141
public const char UNKNOWN = '?';
4242

4343
// Aliases
44-
public const byte ACK = SUCCESS;
45-
public const byte NACK = ERROR;
46-
public const byte NOACK = ERROR;
47-
public const byte FAIL = ERROR;
48-
public const byte ZERO = NULL;
44+
public const byte ACK = SUCCESS;
45+
public const byte ENABLED = TRUE;
46+
public const byte DISABLED = FALSE;
47+
public const byte NACK = ERROR;
48+
public const byte NOACK = ERROR;
49+
public const byte FAIL = ERROR;
50+
public const byte ZERO = NULL;
4951
}
5052
}

src/SpdReaderWriterDll/Settings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ public class Settings {
77
/// <summary>
88
/// DLL version
99
/// </summary>
10-
public const int DLLVERSION = 20211202;
10+
public const int DLLVERSION = 20211206;
1111

1212
/// <summary>
1313
/// Minimum device's firmware version required
1414
/// </summary>
15-
public static int MINVERSION = 20211202;
15+
public static int MINVERSION = 20211206;
1616
}
1717
}

0 commit comments

Comments
 (0)