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:
Doug Brown 2012-09-30 14:41:22 -07:00
parent ff1f213b6f
commit 667c2c5a2d
4 changed files with 101 additions and 11 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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 -------------------------

View File

@ -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();
}
}
}
}