From 2943b80c4260651c1cbe6566464f837e92191df7 Mon Sep 17 00:00:00 2001 From: Doug Brown Date: Wed, 25 Nov 2020 16:30:57 -0800 Subject: [PATCH] Optimize reading of 1024 byte chunks This was a suggestion from bigmessowires. Do a tight loop when reading a chunk of 1024 bytes. It's faster. --- hal/at90usb646/usbcdc_hw.h | 23 +++++-- hal/usbcdc.h | 1 + simm_programmer.c | 126 +++++++++++++++++++------------------ 3 files changed, 84 insertions(+), 66 deletions(-) diff --git a/hal/at90usb646/usbcdc_hw.h b/hal/at90usb646/usbcdc_hw.h index 2bbc921..fc81ec5 100644 --- a/hal/at90usb646/usbcdc_hw.h +++ b/hal/at90usb646/usbcdc_hw.h @@ -27,12 +27,13 @@ #include "LUFA/Drivers/USB/USB.h" #include "cdc_device_definition.h" +#include "../../util.h" /** Sends a byte over the USB CDC serial port * * @param byte The byte to send */ -static __attribute__((always_inline)) inline void USBCDC_SendByte(uint8_t byte) +static ALWAYS_INLINE void USBCDC_SendByte(uint8_t byte) { CDC_Device_SendByte(&VirtualSerial_CDC_Interface, byte); } @@ -43,7 +44,7 @@ static __attribute__((always_inline)) inline void USBCDC_SendByte(uint8_t byte) * @param len The number of bytes * @return True on success, false on failure */ -static __attribute__((always_inline)) inline bool USBCDC_SendData(uint8_t const *data, uint16_t len) +static ALWAYS_INLINE bool USBCDC_SendData(uint8_t const *data, uint16_t len) { return CDC_Device_SendData(&VirtualSerial_CDC_Interface, (char const *)data, len) == ENDPOINT_RWSTREAM_NoError; } @@ -52,15 +53,29 @@ static __attribute__((always_inline)) inline bool USBCDC_SendData(uint8_t const * * @return The byte read, or -1 if there are no bytes available */ -static __attribute__((always_inline)) inline int16_t USBCDC_ReadByte(void) +static ALWAYS_INLINE int16_t USBCDC_ReadByte(void) { return CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); } +/** Reads a byte from the USB CDC serial port. Blocks until one is available. + * + * @return The byte read + */ +static ALWAYS_INLINE uint8_t USBCDC_ReadByteBlocking(void) +{ + int16_t b; + do + { + b = USBCDC_ReadByte(); + } while (b < 0); + return (uint8_t)b; +} + /** Forces any transmitted data to be sent over USB immediately * */ -static __attribute__((always_inline)) inline void USBCDC_Flush(void) +static ALWAYS_INLINE inline void USBCDC_Flush(void) { CDC_Device_Flush(&VirtualSerial_CDC_Interface); } diff --git a/hal/usbcdc.h b/hal/usbcdc.h index 6a5176a..5af0e36 100644 --- a/hal/usbcdc.h +++ b/hal/usbcdc.h @@ -36,6 +36,7 @@ void USBCDC_Check(void); //void USBCDC_SendByte(uint8_t byte); //bool USBCDC_SendData(uint8_t const *data, uint16_t len); //int16_t USBCDC_ReadByte(void); +//uint8_t USBCDC_ReadByteBlocking(void); //void USBCDC_Flush(void) #endif /* HAL_USBCDC_H_ */ diff --git a/simm_programmer.c b/simm_programmer.c index 349e139..1738d78 100644 --- a/simm_programmer.c +++ b/simm_programmer.c @@ -422,82 +422,84 @@ static void SIMMProgrammer_HandleWritingChipsByte(uint8_t byte) } else // Interpret the incoming byte as data to write to the SIMM. { - // Save the byte, and check if we've filled up an entire chunk + // Save the byte. Then, block until we receive the rest of the data. writeChunks.bytes[writePosInChunk++] = byte; - if (writePosInChunk >= READ_WRITE_CHUNK_SIZE_BYTES) + while (writePosInChunk < READ_WRITE_CHUNK_SIZE_BYTES) { - // We filled up the chunk, write it out and confirm it, then wait - // for the next command from the computer! - if (chipsMask == ALL_CHIPS) - { - ParallelFlash_WriteAllChips(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), - writeChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS); - } - else - { - ParallelFlash_WriteSomeChips(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), - writeChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS, chipsMask); - } + writeChunks.bytes[writePosInChunk++] = USBCDC_ReadByteBlocking(); + } - // Verify if we were asked to. - uint8_t badVerifyChipsMask = 0; - if (verifyDuringWrite) - { - // Read back a chunk - ParallelFlash_Read(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), - readChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS); + // We filled up the chunk, write it out and confirm it, then wait + // for the next command from the computer! + if (chipsMask == ALL_CHIPS) + { + ParallelFlash_WriteAllChips(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), + writeChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS); + } + else + { + ParallelFlash_WriteSomeChips(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), + writeChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS, chipsMask); + } - // Compare the readback to what we attempted to flash. - // Look at each chip - for (uint8_t chip = 0; chip < PARALLEL_FLASH_NUM_CHIPS; chip++) + // Verify if we were asked to. + uint8_t badVerifyChipsMask = 0; + if (verifyDuringWrite) + { + // Read back a chunk + ParallelFlash_Read(curWriteIndex * (READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS), + readChunks.words, READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS); + + // Compare the readback to what we attempted to flash. + // Look at each chip + for (uint8_t chip = 0; chip < PARALLEL_FLASH_NUM_CHIPS; chip++) + { + uint16_t bytePos = chip; + uint8_t thisChipMask = 1 << chip; + // Loop over all bytes that are on this chip + for (uint16_t i = 0; i < READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS; i++) { - uint16_t bytePos = chip; - uint8_t thisChipMask = 1 << chip; - // Loop over all bytes that are on this chip - for (uint16_t i = 0; i < READ_WRITE_CHUNK_SIZE_BYTES/PARALLEL_FLASH_NUM_CHIPS; i++) + if (writeChunks.bytes[bytePos] != readChunks.bytes[bytePos]) { - if (writeChunks.bytes[bytePos] != readChunks.bytes[bytePos]) - { - badVerifyChipsMask |= thisChipMask; - } - bytePos += PARALLEL_FLASH_NUM_CHIPS; + badVerifyChipsMask |= thisChipMask; } + bytePos += PARALLEL_FLASH_NUM_CHIPS; } - - // Filter out chips we didn't care about - badVerifyChipsMask &= chipsMask; } - // Bail if verification failed - if (badVerifyChipsMask != 0) + // Filter out chips we didn't care about + badVerifyChipsMask &= chipsMask; + } + + // Bail if verification failed + if (badVerifyChipsMask != 0) + { + // Verification failed. The mask we calculated is actually + // backwards. We need to reverse it when we transmit the IC + // status back to the programmer software. This is kind of silly + // but it's too late to update the protocol. + uint8_t actualBadMask = 0; + for (uint8_t i = 0; i < PARALLEL_FLASH_NUM_CHIPS; i++) { - // Verification failed. The mask we calculated is actually - // backwards. We need to reverse it when we transmit the IC - // status back to the programmer software. This is kind of silly - // but it's too late to update the protocol. - uint8_t actualBadMask = 0; - for (uint8_t i = 0; i < PARALLEL_FLASH_NUM_CHIPS; i++) + if (badVerifyChipsMask & (1 << i)) { - if (badVerifyChipsMask & (1 << i)) - { - actualBadMask |= 0x80; - } - actualBadMask >>= 1; + actualBadMask |= 0x80; } + actualBadMask >>= 1; + } - // Uh oh -- verification failure. - LED_Off(); - // Send the fail bit along with a mask of failed chips. - USBCDC_SendByte(ProgrammerWriteVerificationError | badVerifyChipsMask); - curCommandState = WaitingForCommand; - } - else - { - USBCDC_SendByte(ProgrammerWriteOK); - curWriteIndex++; - writePosInChunk = -1; - LED_Toggle(); - } + // Uh oh -- verification failure. + LED_Off(); + // Send the fail bit along with a mask of failed chips. + USBCDC_SendByte(ProgrammerWriteVerificationError | badVerifyChipsMask); + curCommandState = WaitingForCommand; + } + else + { + USBCDC_SendByte(ProgrammerWriteOK); + curWriteIndex++; + writePosInChunk = -1; + LED_Toggle(); } } }