mirror of
https://github.com/dougg3/mac-rom-simm-programmer.git
synced 2025-01-03 06:30:33 +00:00
Added verify during write. It seems to mostly work except when the chip
is completely removed from the SIMM -- in that case, the verification still passes for some reason. I'm still debugging this one. Maybe the data I had just written is still essentially on the bus because of the floating pins and it reads it too fast? Maybe turning on pull-ups would help with that?
This commit is contained in:
parent
ff1f213b6f
commit
667c2c5a2d
@ -336,12 +336,69 @@ void ExternalMem_WriteByteToChips(uint32_t address, uint32_t data, uint8_t chips
|
||||
ExternalMem_WaitCompletion(chipsMask);
|
||||
}
|
||||
|
||||
void ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, uint8_t chipsMask)
|
||||
uint8_t ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, uint8_t chipsMask, bool doVerify)
|
||||
{
|
||||
// Use a mask so we don't worry about chips we don't want to talk with
|
||||
uint32_t mask = ExternalMem_MaskForChips(chipsMask);
|
||||
|
||||
while (len--)
|
||||
{
|
||||
ExternalMem_WriteByteToChips(startAddress++, *buf++, chipsMask);
|
||||
ExternalMem_WriteByteToChips(startAddress, *buf, chipsMask);
|
||||
if (doVerify)
|
||||
{
|
||||
#define VERIFY_EXTRA_READ_TRIES 2
|
||||
|
||||
// Read back the word we just wrote to make sure it's OK...
|
||||
uint32_t readback = ExternalMem_ReadCycle(startAddress) & mask;
|
||||
if (readback != (*buf & mask))
|
||||
{
|
||||
// We found a failure, but don't despair yet. Let's try reading
|
||||
// two more times in case it a fluke of the data toggle polling
|
||||
// algorithm.
|
||||
bool secondFailureFound = false;
|
||||
int try = 0;
|
||||
|
||||
while ((try < VERIFY_EXTRA_READ_TRIES) && !secondFailureFound)
|
||||
{
|
||||
try++;
|
||||
readback = ExternalMem_ReadCycle(startAddress) & mask;
|
||||
if (readback != (*buf & mask))
|
||||
{
|
||||
secondFailureFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we re-read it a few times and it failed again, the write
|
||||
// failed. Otherwise, it was probably just the data toggle
|
||||
// polling algorithm giving us fits.
|
||||
if (secondFailureFound)
|
||||
{
|
||||
uint8_t failMask = 0;
|
||||
// Figure out the mask of chip(s) acting up
|
||||
int x;
|
||||
for (x = 0; x < NUM_CHIPS; x++)
|
||||
{
|
||||
// Is this a chip we're working with?
|
||||
if (chipsMask & (1 << x))
|
||||
{
|
||||
if ((readback & (0xFFUL << (8*x))) != (*buf & (0xFFUL << (8*x))))
|
||||
{
|
||||
// Save the failMask in reverse order
|
||||
// (so bit 0 refers to IC1 rather than IC4)
|
||||
failMask |= (1 << ((NUM_CHIPS - 1) - x));
|
||||
}
|
||||
}
|
||||
}
|
||||
return failMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startAddress++;
|
||||
buf++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExternalMem_SetChipType(ChipType type)
|
||||
|
@ -101,7 +101,9 @@ void ExternalMem_WriteByteToChips(uint32_t address, uint32_t data, uint8_t chips
|
||||
// Writes a buffer to the requested chips simultaneously
|
||||
// (each uint32_t contains an 8-bit portion for each chip,
|
||||
// which is masked away if the chip is not requested)
|
||||
void ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, uint8_t chipsMask);
|
||||
// returns a mask representing the chips acting up (if requested with doVerify)
|
||||
// or 0 on success (or if verification was not requested)
|
||||
uint8_t ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, uint8_t chipsMask, bool doVerify);
|
||||
|
||||
// Tells which flash command protocol to use
|
||||
void ExternalMem_SetChipType(ChipType type);
|
||||
|
@ -43,7 +43,9 @@ typedef enum ProgrammerCommand
|
||||
EnterProgrammer,
|
||||
BootloaderEraseAndWriteProgram,
|
||||
SetSIMMTypePLCC32_2MB,
|
||||
SetSIMMTypeLarger
|
||||
SetSIMMTypeLarger,
|
||||
SetVerifyWhileWriting,
|
||||
SetNoVerifyWhileWriting
|
||||
} ProgrammerCommand;
|
||||
|
||||
// After a command is sent, the programmer will always respond with
|
||||
@ -115,6 +117,11 @@ typedef enum ComputerReadReply
|
||||
// this one, and then the computer can send a 1024-byte chunk of data.
|
||||
// The programmer will reply with ProgrammerWriteOK, and then the cycle can
|
||||
// continue (the computer sends another request in this enum)
|
||||
//
|
||||
// If the programmer was asked to verify while writing and a verification error
|
||||
// occurs, it will respond with ProgrammerWriteVerificationError ORed with a bit
|
||||
// mask of chips that are acting up (so it could be 0x81 if IC1 is acting up,
|
||||
// for example)
|
||||
typedef enum ComputerWriteRequest
|
||||
{
|
||||
ComputerWriteMore = 0,
|
||||
@ -126,7 +133,8 @@ typedef enum ProgrammerWriteReply
|
||||
{
|
||||
ProgrammerWriteOK = 0,
|
||||
ProgrammerWriteError,
|
||||
ProgrammerWriteConfirmCancel
|
||||
ProgrammerWriteConfirmCancel,
|
||||
ProgrammerWriteVerificationError = 0x80 /* high bit signifies verify error, low bits signify which chips are bad */
|
||||
} ProgrammerWriteReply;
|
||||
|
||||
// ------------------------- BOOTLOADER STATE PROTOCOL -------------------------
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../tests/simm_electrical_test.h"
|
||||
#include "../programmer_protocol.h"
|
||||
#include "../led.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_CHIP_SIZE (2UL * 1024UL * 1024UL)
|
||||
#define READ_CHUNK_SIZE_BYTES 1024UL
|
||||
@ -64,6 +65,7 @@ static uint32_t readLength;
|
||||
static uint8_t readLengthByteIndex;
|
||||
static int16_t writePosInChunk = -1;
|
||||
static uint16_t curWriteIndex = 0;
|
||||
static bool verifyDuringWrite = false;
|
||||
|
||||
// Private functions
|
||||
void USBSerial_HandleWaitingForCommandByte(uint8_t byte);
|
||||
@ -217,6 +219,14 @@ void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
|
||||
ExternalMem_SetChipType(ChipType8Bit16BitData_16MBitSize);
|
||||
SendByte(CommandReplyOK);
|
||||
break;
|
||||
case SetVerifyWhileWriting:
|
||||
verifyDuringWrite = true;
|
||||
SendByte(CommandReplyOK);
|
||||
break;
|
||||
case SetNoVerifyWhileWriting:
|
||||
verifyDuringWrite = false;
|
||||
SendByte(CommandReplyOK);
|
||||
break;
|
||||
// We don't know what this command is, so reply that it was invalid.
|
||||
default:
|
||||
SendByte(CommandReplyInvalid);
|
||||
@ -373,12 +383,25 @@ void USBSerial_HandleWritingChipsByte(uint8_t byte)
|
||||
{
|
||||
// We filled up the chunk, write it out and confirm it, then wait
|
||||
// for the next command from the computer!
|
||||
ExternalMem_Write(curWriteIndex * (WRITE_CHUNK_SIZE_BYTES/4),
|
||||
chunks.writeChunks, WRITE_CHUNK_SIZE_BYTES/4, ALL_CHIPS);
|
||||
SendByte(ProgrammerWriteOK);
|
||||
curWriteIndex++;
|
||||
writePosInChunk = -1;
|
||||
LED_Toggle();
|
||||
uint8_t writeResult = ExternalMem_Write(curWriteIndex * (WRITE_CHUNK_SIZE_BYTES/4),
|
||||
chunks.writeChunks, WRITE_CHUNK_SIZE_BYTES/4, ALL_CHIPS, verifyDuringWrite);
|
||||
|
||||
// But if we asked to verify, make sure it came out OK.
|
||||
if (verifyDuringWrite && (writeResult != 0))
|
||||
{
|
||||
// Uh oh -- verification failure.
|
||||
LED_Off();
|
||||
// Send the fail bit along with a mask of failed chips.
|
||||
SendByte(ProgrammerWriteVerificationError | writeResult);
|
||||
curCommandState = WaitingForCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendByte(ProgrammerWriteOK);
|
||||
curWriteIndex++;
|
||||
writePosInChunk = -1;
|
||||
LED_Toggle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user