mirror of
https://github.com/dougg3/mac-rom-simm-programmer.git
synced 2024-12-27 06:29:22 +00:00
Added untested support for erasing a specific portion of the SIMM
(in 256 KB increments). Won't be able to test it until I implement it in the control software as well, but I think it should work.
This commit is contained in:
parent
d484d126e5
commit
3252f66749
@ -256,6 +256,91 @@ void ExternalMem_EraseChips(uint8_t chipsMask)
|
||||
ExternalMem_WaitCompletion(chipsMask);
|
||||
}
|
||||
|
||||
bool ExternalMem_EraseSectors(uint32_t address, uint32_t length, uint8_t chipsMask)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Make sure the area requested to be erased is on 64 KB boundaries.
|
||||
// True, the 2 MB SIMM doesn't require 64 KB boundaries, but I'm going to
|
||||
// keep it to 2 MB boundaries to simplify everything.
|
||||
#define ERASABLE_SECTOR_SIZE (64*1024UL*1024UL)
|
||||
if ((address & ERASABLE_SECTOR_SIZE) ||
|
||||
(length & ERASABLE_SECTOR_SIZE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're good to go. Let's do it.
|
||||
|
||||
if (curChipType == ChipType8BitData_4MBitSize)
|
||||
{
|
||||
#define SECTOR_SIZE_4MBIT (128)
|
||||
// This chip sucks because you have to erase each sector with its own
|
||||
// complete erase unlock command, which can take a while. At least
|
||||
// individual erase operations are much faster on this chip...
|
||||
while (length)
|
||||
{
|
||||
// Start the erase command
|
||||
ExternalMem_UnlockChips(chipsMask);
|
||||
ExternalMem_WriteCycle(0x55555555UL, 0x80808080UL);
|
||||
ExternalMem_UnlockChips(chipsMask);
|
||||
|
||||
// Now provide a sector address, but only one. Then the whole
|
||||
// unlock sequence has to be done again after this sector is done.
|
||||
ExternalMem_WriteCycle(address, 0x20202020UL);
|
||||
|
||||
address += SECTOR_SIZE_4MBIT;
|
||||
length -= SECTOR_SIZE_4MBIT;
|
||||
|
||||
// Wait for completion of this individual erase operation before
|
||||
// we can start a new erase operation.
|
||||
ExternalMem_WaitCompletion(chipsMask);
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
else if (curChipType == ChipType8Bit16BitData_16MBitSize)
|
||||
{
|
||||
#define SECTOR_SIZE_16MBIT (64*1024UL*1024UL)
|
||||
// This chip is nicer because it can take all the sector addresses at
|
||||
// once and then do the final erase operation in one fell swoop.
|
||||
|
||||
// Start the erase command
|
||||
ExternalMem_UnlockChips(chipsMask);
|
||||
ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x80808080UL);
|
||||
ExternalMem_UnlockChips(chipsMask);
|
||||
|
||||
// Now provide as many sector addresses as needed to erase.
|
||||
|
||||
// The first address is a bit of a special case because the boot sector
|
||||
// actually has finer granularity for sector sizes.
|
||||
if (address == 0)
|
||||
{
|
||||
ExternalMem_WriteCycle(0x00000000UL, 0x30303030UL);
|
||||
ExternalMem_WriteCycle(0x00004000UL, 0x30303030UL);
|
||||
ExternalMem_WriteCycle(0x00006000UL, 0x30303030UL);
|
||||
ExternalMem_WriteCycle(0x00008000UL, 0x30303030UL);
|
||||
address += SECTOR_SIZE_16MBIT;
|
||||
length -= SECTOR_SIZE_16MBIT;
|
||||
}
|
||||
|
||||
// The remaining sectors can use a more generic algorithm
|
||||
while (length)
|
||||
{
|
||||
ExternalMem_WriteCycle(address, 0x30303030UL);
|
||||
address += SECTOR_SIZE_16MBIT;
|
||||
length -= SECTOR_SIZE_16MBIT;
|
||||
}
|
||||
|
||||
// Wait for completion of the entire erase operation
|
||||
ExternalMem_WaitCompletion(chipsMask);
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExternalMem_WaitCompletion(uint8_t chipsMask)
|
||||
{
|
||||
// Mark the chips not requested as already completed,
|
||||
@ -408,3 +493,8 @@ void ExternalMem_SetChipType(ChipType type)
|
||||
{
|
||||
curChipType = type;
|
||||
}
|
||||
|
||||
ChipType ExternalMem_GetChipType(void)
|
||||
{
|
||||
return curChipType;
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ void ExternalMem_IdentifyChips(struct ChipID *chips);
|
||||
|
||||
// Erases the chips requested
|
||||
void ExternalMem_EraseChips(uint8_t chipsMask);
|
||||
bool ExternalMem_EraseSectors(uint32_t address, uint32_t length, uint8_t chipsMask);
|
||||
|
||||
// Writes a byte to the chips requested at the specified address
|
||||
void ExternalMem_WriteByteToChips(uint32_t address, uint32_t data, uint8_t chipsMask);
|
||||
@ -107,5 +108,6 @@ uint8_t ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, ui
|
||||
|
||||
// Tells which flash command protocol to use
|
||||
void ExternalMem_SetChipType(ChipType type);
|
||||
ChipType ExternalMem_GetChipType(void);
|
||||
|
||||
#endif /* EXTERNAL_MEM_H_ */
|
||||
|
@ -45,7 +45,8 @@ typedef enum ProgrammerCommand
|
||||
SetSIMMTypePLCC32_2MB,
|
||||
SetSIMMTypeLarger,
|
||||
SetVerifyWhileWriting,
|
||||
SetNoVerifyWhileWriting
|
||||
SetNoVerifyWhileWriting,
|
||||
ErasePortion
|
||||
} ProgrammerCommand;
|
||||
|
||||
// After a command is sent, the programmer will always respond with
|
||||
@ -166,4 +167,21 @@ typedef enum ComputerBootloaderEraseWriteRequest
|
||||
ComputerBootloaderCancel
|
||||
} ComputerBootloaderEraseWriteRequest;
|
||||
|
||||
// ------------------------- ERASE PORTION OF CHIP PROTOCOL -------------------------
|
||||
// If the command is ErasePortion, the programmer will reply CommandReplyOK.
|
||||
// Next, the program will send the beginning position to erase as a 4-byte little
|
||||
// endian integer, followed by the length to erase as a 4-byte little endian
|
||||
// integer. The programmer will reply with ProgrammerErasePortionOK to signify
|
||||
// that the erase is beginning, followed by ProgrammerErasePortionFinished when
|
||||
// everything is done.
|
||||
// The length and position to erase must be on 256 KB boundaries and shouldn't
|
||||
// go past the end of the selected type of chip. If any error occurs, it will
|
||||
// reply with ProgrammerErasePortionError instead.
|
||||
typedef enum ProgrammerErasePortionOfChipReply
|
||||
{
|
||||
ProgrammerErasePortionOK = 0,
|
||||
ProgrammerErasePortionError,
|
||||
ProgrammerErasePortionFinished
|
||||
} ProgrammerErasePortionOfChipReply;
|
||||
|
||||
#endif /* PROGRAMMER_PROTOCOL_H_ */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define MAX_CHIP_SIZE (2UL * 1024UL * 1024UL)
|
||||
#define READ_CHUNK_SIZE_BYTES 1024UL
|
||||
#define WRITE_CHUNK_SIZE_BYTES 1024UL
|
||||
#define ERASE_SECTOR_SIZE_BYTES (256UL * 1024UL)
|
||||
#if ((READ_CHUNK_SIZE_BYTES % 4) != 0)
|
||||
#error Read chunk size should be a multiple of 4 bytes
|
||||
#endif
|
||||
@ -54,7 +55,8 @@ typedef enum ProgrammerCommandState
|
||||
ReadingChipsReadLength,
|
||||
ReadingChips,
|
||||
ReadingChipsUnableSendError,
|
||||
WritingChips
|
||||
WritingChips,
|
||||
ErasePortionReadingPosLength
|
||||
} ProgrammerCommandState;
|
||||
static ProgrammerCommandState curCommandState = WaitingForCommand;
|
||||
|
||||
@ -66,6 +68,8 @@ static uint8_t readLengthByteIndex;
|
||||
static int16_t writePosInChunk = -1;
|
||||
static uint16_t curWriteIndex = 0;
|
||||
static bool verifyDuringWrite = false;
|
||||
static uint32_t erasePosition;
|
||||
static uint32_t eraseLength;
|
||||
|
||||
// Private functions
|
||||
void USBSerial_HandleWaitingForCommandByte(uint8_t byte);
|
||||
@ -74,6 +78,7 @@ void USBSerial_HandleReadingChipsReadLengthByte(uint8_t byte);
|
||||
void USBSerial_SendReadDataChunk(void);
|
||||
void USBSerial_HandleWritingChipsByte(uint8_t byte);
|
||||
void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2);
|
||||
void USBSerial_HandleErasePortionReadPosLengthByte(uint8_t byte);
|
||||
|
||||
// Read/write to USB serial macros -- easier than retyping
|
||||
// CDC_Device_XXX(&VirtualSerial_CDC_Interface...) every time
|
||||
@ -107,6 +112,9 @@ void USBSerial_Check(void)
|
||||
case WritingChips:
|
||||
USBSerial_HandleWritingChipsByte((uint8_t)recvByte);
|
||||
break;
|
||||
case ErasePortionReadingPosLength:
|
||||
USBSerial_HandleErasePortionReadPosLengthByte((uint8_t)recvByte);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,6 +235,13 @@ void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
|
||||
verifyDuringWrite = false;
|
||||
SendByte(CommandReplyOK);
|
||||
break;
|
||||
case ErasePortion:
|
||||
readLengthByteIndex = 0;
|
||||
eraseLength = 0;
|
||||
erasePosition = 0;
|
||||
curCommandState = ErasePortionReadingPosLength;
|
||||
SendByte(CommandReplyOK);
|
||||
break;
|
||||
// We don't know what this command is, so reply that it was invalid.
|
||||
default:
|
||||
SendByte(CommandReplyInvalid);
|
||||
@ -416,6 +431,76 @@ void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2)
|
||||
SendByte(index2);
|
||||
}
|
||||
|
||||
// If we're figuring out the position/length to erase, parse it here.
|
||||
void USBSerial_HandleErasePortionReadPosLengthByte(uint8_t byte)
|
||||
{
|
||||
// Read in the position and length to erase
|
||||
if (readLengthByteIndex < 4)
|
||||
{
|
||||
erasePosition |= (((uint32_t)byte) << (8*readLengthByteIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
eraseLength |= (((uint32_t)byte) << (8*(readLengthByteIndex - 4)));
|
||||
}
|
||||
|
||||
if (++readLengthByteIndex >= 8)
|
||||
{
|
||||
ChipType chipType = ExternalMem_GetChipType();
|
||||
bool eraseSuccess = false;
|
||||
|
||||
// Ensure they are both within limits of sector size erasure
|
||||
if (((erasePosition & ERASE_SECTOR_SIZE_BYTES) == 0) &&
|
||||
((eraseLength & ERASE_SECTOR_SIZE_BYTES) == 0))
|
||||
{
|
||||
uint32_t boundary = eraseLength + erasePosition;
|
||||
|
||||
// Ensure they are within the limits of the chip size too
|
||||
if (chipType == ChipType8BitData_4MBitSize)
|
||||
{
|
||||
if (boundary <= (2 * 1024UL * 1024UL))
|
||||
{
|
||||
// OK! We're erasing certain sectors of a 2 MB SIMM.
|
||||
SendByte(ProgrammerErasePortionOK);
|
||||
CDC_Device_Flush(&VirtualSerial_CDC_Interface);
|
||||
if (ExternalMem_EraseSectors(erasePosition/NUM_CHIPS,
|
||||
eraseLength/NUM_CHIPS, ALL_CHIPS))
|
||||
{
|
||||
eraseSuccess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (chipType == ChipType8Bit16BitData_16MBitSize)
|
||||
{
|
||||
if (boundary <= (8 * 1024UL * 1024UL))
|
||||
{
|
||||
// OK! We're erasing certain sectors of an 8 MB SIMM.
|
||||
SendByte(ProgrammerErasePortionOK);
|
||||
CDC_Device_Flush(&VirtualSerial_CDC_Interface);
|
||||
if (ExternalMem_EraseSectors(erasePosition/NUM_CHIPS,
|
||||
eraseLength/NUM_CHIPS, ALL_CHIPS))
|
||||
{
|
||||
eraseSuccess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eraseSuccess)
|
||||
{
|
||||
// Not on a sector boundary for erase position and/or length
|
||||
SendByte(ProgrammerErasePortionFinished);
|
||||
curCommandState = WaitingForCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not on a sector boundary for erase position and/or length
|
||||
SendByte(ProgrammerErasePortionError);
|
||||
curCommandState = WaitingForCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LUFA event handler for when the USB configuration changes.
|
||||
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user