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.
This commit is contained in:
Doug Brown 2020-11-25 16:30:57 -08:00 committed by Doug Brown
parent 3df4c40f38
commit 2943b80c42
3 changed files with 84 additions and 66 deletions

View File

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

View File

@ -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_ */

View File

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