diff --git a/external_mem.c b/external_mem.c index e3fa69e..15ce360 100644 --- a/external_mem.c +++ b/external_mem.c @@ -29,6 +29,9 @@ #define HIGHEST_ADDRESS_LINE 20 +// Default setup +static ChipType curChipType = ChipType8BitData_4MBitSize; + // Private functions uint32_t ExternalMem_MaskForChips(uint8_t chips); void ExternalMem_WaitCompletion(uint8_t chipsMask); @@ -163,15 +166,31 @@ void ExternalMem_UnlockChips(uint8_t chipsMask) // Use a mask so we don't unlock chips we don't want to talk with uint32_t mask = ExternalMem_MaskForChips(chipsMask); - // First part of unlock sequence: - // Write 0x55555555 to the address bus and 0xAA to the data bus - // (Some datasheets may only say 0x555 or 0x5555, but they ignore - // the upper bits, so writing the alternating pattern to all address lines - // should make it compatible with larger chips) - ExternalMem_WriteCycle(0x55555555UL, 0xAAAAAAAAUL & mask); + // The unlock sequence changes depending on the chip + if (curChipType == ChipType8BitData_4MBitSize) + { + // First part of unlock sequence: + // Write 0x55555555 to the address bus and 0xAA to the data bus + // (Some datasheets may only say 0x555 or 0x5555, but they ignore + // the upper bits, so writing the alternating pattern to all address lines + // should make it compatible with larger chips) + ExternalMem_WriteCycle(0x55555555UL, 0xAAAAAAAAUL & mask); - // Second part of unlock sequence is the same thing, but reversed. - ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x55555555UL & mask); + // Second part of unlock sequence is the same thing, but reversed. + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x55555555UL & mask); + } + // The protocol is slightly different for 8/16-bit devices in 8-bit mode: + else if (curChipType == ChipType8Bit16BitData_16MBitSize) + { + // First part of unlock sequence: + // Write 0xAAAAAAAA to the address bus and 0xAA to the data bus + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0xAAAAAAAAUL & mask); + + // Second part of unlock sequence is the reversed pattern. + ExternalMem_WriteCycle(0x55555555UL, 0x55555555UL & mask); + } + // shouldn't ever be a value other than those two, so I'm not writing + // any extra code for that case. } void ExternalMem_IdentifyChips(struct ChipID *chips) @@ -180,7 +199,16 @@ void ExternalMem_IdentifyChips(struct ChipID *chips) ExternalMem_UnlockChips(ALL_CHIPS); // Write 0x90 to 0x55555555 for the identify command... - ExternalMem_WriteCycle(0x55555555UL, 0x90909090UL); + if (curChipType == ChipType8BitData_4MBitSize) + { + ExternalMem_WriteCycle(0x55555555UL, 0x90909090UL); + } + else if (curChipType == ChipType8Bit16BitData_16MBitSize) + { + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x90909090UL); + } + // shouldn't ever be a value other than those two, so I'm not writing + // any extra code for that case. // Now we can read the vendor and product ID uint32_t result = ExternalMem_ReadCycle(0); @@ -204,9 +232,23 @@ void ExternalMem_IdentifyChips(struct ChipID *chips) void ExternalMem_EraseChips(uint8_t chipsMask) { ExternalMem_UnlockChips(chipsMask); - ExternalMem_WriteCycle(0x55555555UL, 0x80808080UL); + if (curChipType == ChipType8BitData_4MBitSize) + { + ExternalMem_WriteCycle(0x55555555UL, 0x80808080UL); + } + else if (curChipType == ChipType8Bit16BitData_16MBitSize) + { + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x80808080UL); + } ExternalMem_UnlockChips(chipsMask); - ExternalMem_WriteCycle(0x55555555UL, 0x10101010UL); + if (curChipType == ChipType8BitData_4MBitSize) + { + ExternalMem_WriteCycle(0x55555555UL, 0x10101010UL); + } + else if (curChipType == ChipType8Bit16BitData_16MBitSize) + { + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0x10101010UL); + } ExternalMem_WaitCompletion(chipsMask); } @@ -282,7 +324,14 @@ void ExternalMem_WriteByteToChips(uint32_t address, uint32_t data, uint8_t chips uint32_t mask = ExternalMem_MaskForChips(chipsMask); ExternalMem_UnlockChips(chipsMask); - ExternalMem_WriteCycle(0x55555555UL, 0xA0A0A0A0UL & mask); + if (curChipType == ChipType8BitData_4MBitSize) + { + ExternalMem_WriteCycle(0x55555555UL, 0xA0A0A0A0UL & mask); + } + else if (curChipType == ChipType8Bit16BitData_16MBitSize) + { + ExternalMem_WriteCycle(0xAAAAAAAAUL, 0xA0A0A0A0UL & mask); + } ExternalMem_WriteCycle(address, data & mask); ExternalMem_WaitCompletion(chipsMask); } @@ -294,3 +343,8 @@ void ExternalMem_Write(uint32_t startAddress, uint32_t *buf, uint32_t len, uint8 ExternalMem_WriteByteToChips(startAddress++, *buf++, chipsMask); } } + +void ExternalMem_SetChipType(ChipType type) +{ + curChipType = type; +} diff --git a/external_mem.h b/external_mem.h index 50cd809..4eda3ac 100644 --- a/external_mem.h +++ b/external_mem.h @@ -45,6 +45,14 @@ struct ChipID #define IC4 (1 << 0) #define ALL_CHIPS (IC1 | IC2 | IC3 | IC4) +// Type of SIMM currently being addressed -- determines command protocol used +// to talk to the chips +typedef enum ChipType +{ + ChipType8BitData_4MBitSize, /* 512Kbit to 2Mbit flash, 8-bit */ + ChipType8Bit16BitData_16MBitSize /* 16Mbit flash, 8/16-bit in 8-bit mode */ +} ChipType; + // Initializes the (bit-banged) external memory interface void ExternalMem_Init(void); @@ -95,4 +103,7 @@ void ExternalMem_WriteByteToChips(uint32_t address, uint32_t data, uint8_t chips // 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); +// Tells which flash command protocol to use +void ExternalMem_SetChipType(ChipType type); + #endif /* EXTERNAL_MEM_H_ */ diff --git a/programmer_protocol.h b/programmer_protocol.h index 5b532b9..f357101 100644 --- a/programmer_protocol.h +++ b/programmer_protocol.h @@ -41,7 +41,9 @@ typedef enum ProgrammerCommand GetBootloaderState, EnterBootloader, EnterProgrammer, - BootloaderEraseAndWriteProgram + BootloaderEraseAndWriteProgram, + SetSIMMTypePLCC32_2MB, + SetSIMMTypeLarger } ProgrammerCommand; // After a command is sent, the programmer will always respond with diff --git a/usb_serial/usb_serial.c b/usb_serial/usb_serial.c index bd3a27f..53bbb90 100644 --- a/usb_serial/usb_serial.c +++ b/usb_serial/usb_serial.c @@ -208,6 +208,15 @@ void USBSerial_HandleWaitingForCommandByte(uint8_t byte) // Already in the programmer SendByte(CommandReplyOK); break; + // Set the SIMM type to the older, smaller chip size (2MB and below) + case SetSIMMTypePLCC32_2MB: + ExternalMem_SetChipType(ChipType8BitData_4MBitSize); + SendByte(CommandReplyOK); + break; + case SetSIMMTypeLarger: + ExternalMem_SetChipType(ChipType8Bit16BitData_16MBitSize); + SendByte(CommandReplyOK); + break; // We don't know what this command is, so reply that it was invalid. default: SendByte(CommandReplyInvalid);