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
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
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
185189void loop () {
@@ -366,7 +370,11 @@ void cmdScanBus() {
366370}
367371
368372void cmdTest () {
373+ #ifdef __AVR__
369374 PORT.write (WELCOME);
375+ #else
376+ PORT.write (UNKNOWN);
377+ #endif
370378}
371379
372380void 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
691707bool 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
763783bool 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() {
771791bool 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
883901void 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
9871006bool 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
9931016bool 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
10051034bool 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)
10481082bool 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)
10531091bool 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
0 commit comments