diff options
author | David Crocker <dcrocker@eschertech.com> | 2020-12-04 16:53:23 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2020-12-04 16:53:23 +0300 |
commit | 5c342f14ab791a5cd1714324a15924d824cdb8eb (patch) | |
tree | a0b97292d173d86dd74cf4da30179a6c22ccee68 /src/Storage | |
parent | da2fb45945330a45d34a76d73ab78bd840f2d659 (diff) |
Tidied up FileStore, added CRC16 class
Diffstat (limited to 'src/Storage')
-rw-r--r-- | src/Storage/CRC16.cpp | 72 | ||||
-rw-r--r-- | src/Storage/CRC16.h | 37 | ||||
-rw-r--r-- | src/Storage/CRC32.cpp | 13 | ||||
-rw-r--r-- | src/Storage/CRC32.h | 10 | ||||
-rw-r--r-- | src/Storage/FileStore.cpp | 417 |
5 files changed, 315 insertions, 234 deletions
diff --git a/src/Storage/CRC16.cpp b/src/Storage/CRC16.cpp new file mode 100644 index 00000000..876064a0 --- /dev/null +++ b/src/Storage/CRC16.cpp @@ -0,0 +1,72 @@ +/* + * CRC16.cpp + * + * Created on: 4 Dec 2020 + * Author: David + */ + +#include "CRC16.h" + +static const uint16_t crc16_table[] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +CRC16::CRC16() noexcept +{ + Reset(); +} + +CRC16::~CRC16() +{ +} + +void CRC16::Update(char c) noexcept +{ + crc = (uint16_t)((crc >> 8) ^ crc16_table[(crc ^ c) & 0x00FF]); +} + +void CRC16::Update(const char *c, size_t len) noexcept +{ + //TODO speed this up, by unrolling the loop and/or using slicing-by-4 and/or using hardware CRC on the SAME5x + uint16_t locCrc = crc; + while (len != 0) + { + locCrc = (uint16_t)((locCrc >> 8) ^ crc16_table[(locCrc ^ *c++) & 0x00FF]); + --len; + } + crc = locCrc; +} + +// End diff --git a/src/Storage/CRC16.h b/src/Storage/CRC16.h new file mode 100644 index 00000000..b74a7b6b --- /dev/null +++ b/src/Storage/CRC16.h @@ -0,0 +1,37 @@ +/* + * CRC16.h + * + * Created on: 4 Dec 2020 + * Author: David + */ + +#ifndef SRC_STORAGE_CRC16_H_ +#define SRC_STORAGE_CRC16_H_ + +#include <RepRapFirmware.h> + +class CRC16 +{ +private: + uint16_t crc; + +public: + CRC16() noexcept; + ~CRC16(); + void Update(char c) noexcept; + void Update(const char *c, size_t len) noexcept; + void Reset(uint16_t initialValue = 0xFFFF) noexcept; + uint16_t Get() const noexcept; +}; + +inline uint16_t CRC16::Get() const noexcept +{ + return crc; +} + +inline void CRC16::Reset(uint16_t initialValue) noexcept +{ + crc = initialValue; +} + +#endif /* SRC_STORAGE_CRC16_H_ */ diff --git a/src/Storage/CRC32.cpp b/src/Storage/CRC32.cpp index a3760fff..c2f6f43b 100644 --- a/src/Storage/CRC32.cpp +++ b/src/Storage/CRC32.cpp @@ -166,6 +166,8 @@ CRC32::CRC32() noexcept Reset(); } +CRC32::~CRC32() { } + void CRC32::Update(char c) noexcept { crc = (CRC_32_TAB[(crc ^ c) & 0xFF] ^ (crc >> 8)); @@ -173,7 +175,7 @@ void CRC32::Update(char c) noexcept // A note on CRC algorithms on ARM: // Original algorithm (1 byte per loop iteration, 1K table): 7 instructions, 11 clocks (11 clocks/byte) -// Algorithm currently used on non-SAME70 processors (4 bytes per loop iteration, 1K table): 19 instructions, 26 clocks (6.5 clocks/byte) +// Algorithm currently used on non-SAME70/SAME5x processors (4 bytes per loop iteration, 1K table): 19 instructions, 26 clocks (6.5 clocks/byte) // Slicing-by-4 using 1 dword per loop iteration: 15 instructions, 18 clocks (4.5 clocks/byte) // Slicing-by-4 using 1 quadword per loop iteration: 28 instructions, 31 clocks (3.875 clocks/byte) void CRC32::Update(const char *s, size_t len) noexcept @@ -193,7 +195,7 @@ void CRC32::Update(const char *s, size_t len) noexcept const char * const endAligned = s + ((end - s) & ~7); while (s != endAligned) { - // Slicing-by-4 algorithm, 2 quadwords at a time + // Slicing-by-4 algorithm, 2 dwords at a time const uint32_t data0 = *reinterpret_cast<const uint32_t*>(s) ^ locCrc; locCrc = CRC_32_TAB[(data0 >> 24) & 0xFF] ^ CRC_32_TAB1[(data0 >> 16) & 0xFF] ^ CRC_32_TAB2[(data0 >> 8) & 0xFF] ^ CRC_32_TAB3[data0 & 0xFF]; const uint32_t data1 = *reinterpret_cast<const uint32_t*>(s + 4) ^ locCrc; @@ -213,7 +215,7 @@ void CRC32::Update(const char *s, size_t len) noexcept } #endif - // Process up to 7 (SAME70) or 3 (others) bytes at the end + // Process up to 7 (SAME70/SAME5x) or 3 (others) bytes at the end while (s != end) { locCrc = (CRC_32_TAB[(locCrc ^ *s++) & 0xFF] ^ (locCrc >> 8)); @@ -222,7 +224,4 @@ void CRC32::Update(const char *s, size_t len) noexcept crc = locCrc; } -void CRC32::Reset() noexcept -{ - crc = 0xffffffff; -} +// End diff --git a/src/Storage/CRC32.h b/src/Storage/CRC32.h index 1c5fed8c..892f9c5a 100644 --- a/src/Storage/CRC32.h +++ b/src/Storage/CRC32.h @@ -10,9 +10,10 @@ private: public: CRC32() noexcept; + ~CRC32(); void Update(char c) noexcept; - void Update(const char *c, size_t len) noexcept; - void Reset() noexcept; + void Update(const char *s, size_t len) noexcept; + void Reset(uint32_t initialValue = 0xFFFFFFFF) noexcept; uint32_t Get() const noexcept; }; @@ -21,4 +22,9 @@ inline uint32_t CRC32::Get() const noexcept return ~crc; } +inline void CRC32::Reset(uint32_t initialValue) noexcept +{ + crc = initialValue; +} + #endif diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp index 11bfa09e..516065cf 100644 --- a/src/Storage/FileStore.cpp +++ b/src/Storage/FileStore.cpp @@ -14,9 +14,11 @@ # include "Libraries/Fatfs/diskio.h" # include "Movement/StepTimer.h" #endif + #if HAS_LINUX_INTERFACE # include "Linux/LinuxInterface.h" #endif + FileStore::FileStore() noexcept : #if HAS_MASS_STORAGE @@ -48,48 +50,36 @@ void FileStore::Init() noexcept #endif } -#if HAS_MASS_STORAGE - -// Invalidate the file if it uses the specified FATFS object -bool FileStore::Invalidate(const FATFS *fs, bool doClose) noexcept +// Open a local file (for example on an SD card). +// This is protected - only Platform can access it. +bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) noexcept { - if (file.obj.fs == fs) +#if HAS_LINUX_INTERFACE + if (reprap.UsingLinuxInterface()) { - if (doClose) + if (mode != OpenMode::read) { - (void)ForceClose(); + REPORT_INTERNAL_ERROR; + return false; } - else + //TODO allocating dynamic memory here isn't nice because of possible memory fragmentation. Try to avoid it in future. + absoluteFilename = new char[strlen(filePath)+1]; + strcpy(absoluteFilename, filePath); + char dummyBuf[1]; + uint32_t dummyLen = 0; + if (!reprap.GetLinuxInterface().GetFileChunk(absoluteFilename, 0, dummyBuf, dummyLen, length)) { - file.obj.fs = nullptr; - if (writeBuffer != nullptr) - { - MassStorage::ReleaseWriteBuffer(writeBuffer); - writeBuffer = nullptr; - } + delete absoluteFilename; + absoluteFilename = nullptr; + return false; } - usageMode = FileUseMode::invalidated; + usageMode = FileUseMode::readOnly; + offset = 0; return true; } - return false; -} - -// Return true if the file is open on the specified file system -bool FileStore::IsOpenOn(const FATFS *fs) const noexcept -{ - return openCount != 0 && file.obj.fs == fs; -} -#endif - -// Open a local file (for example on an SD card). -// This is protected - only Platform can access it. -bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) noexcept -{ -#if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) #endif +#if HAS_MASS_STORAGE { -# if HAS_MASS_STORAGE const bool writing = (mode == OpenMode::write || mode == OpenMode::writeWithCrc || mode == OpenMode::append); writeBuffer = nullptr; @@ -147,157 +137,80 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) # endif reprap.VolumesUpdated(); return true; + } # else - return false; + return false; # endif - } +} + +// This may be called from an ISR, in which case we need to defer the close +bool FileStore::Close() noexcept +{ #if HAS_LINUX_INTERFACE - else + if (reprap.UsingLinuxInterface()) { - if (mode != OpenMode::read) - { - reprap.GetPlatform().Message(WarningMessage, "When using LinuxInterface files can only be opened for read access.\n"); - return false; - } - absoluteFilename = new char[strlen(filePath)+1]; - strcpy(absoluteFilename, filePath); - char dummyBuf[1]; - uint32_t dummyLen = 0; - if (!reprap.GetLinuxInterface().GetFileChunk(absoluteFilename, 0, dummyBuf, dummyLen, length)) - { - delete absoluteFilename; - absoluteFilename = nullptr; - return false; - } - usageMode = FileUseMode::readOnly; offset = 0; + length = 0; + delete absoluteFilename; + absoluteFilename = nullptr; + usageMode = FileUseMode::free; return true; } #endif -} - #if HAS_MASS_STORAGE -void FileStore::Duplicate() noexcept -{ switch (usageMode) { case FileUseMode::free: - REPORT_INTERNAL_ERROR; - break; + if (!inInterrupt()) + { + REPORT_INTERNAL_ERROR; + } + return false; case FileUseMode::readOnly: case FileUseMode::readWrite: { const irqflags_t flags = cpu_irq_save(); - ++openCount; - cpu_irq_restore(flags); + if (openCount > 1) + { + --openCount; + cpu_irq_restore(flags); + return true; + } + else if (inInterrupt()) + { + closeRequested = true; + cpu_irq_restore(flags); + return true; + } + else + { + cpu_irq_restore(flags); + return ForceClose(); + } } - break; case FileUseMode::invalidated: default: - break; - } -} -#endif - -// This may be called from an ISR, in which case we need to defer the close -bool FileStore::Close() noexcept -{ -#if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -#endif - { -#if HAS_MASS_STORAGE - switch (usageMode) { - case FileUseMode::free: - if (!inInterrupt()) + const irqflags_t flags = cpu_irq_save(); + if (openCount > 1) { - REPORT_INTERNAL_ERROR; + --openCount; } - return false; - - case FileUseMode::readOnly: - case FileUseMode::readWrite: - { - const irqflags_t flags = cpu_irq_save(); - if (openCount > 1) - { - --openCount; - cpu_irq_restore(flags); - return true; - } - else if (inInterrupt()) - { - closeRequested = true; - cpu_irq_restore(flags); - return true; - } - else - { - cpu_irq_restore(flags); - return ForceClose(); - } - } - - case FileUseMode::invalidated: - default: + else { - const irqflags_t flags = cpu_irq_save(); - if (openCount > 1) - { - --openCount; - } - else - { - usageMode = FileUseMode::free; - } - cpu_irq_restore(flags); -#endif - return true; -#if HAS_MASS_STORAGE + usageMode = FileUseMode::free; } + cpu_irq_restore(flags); + return true; } -#endif - } -#if HAS_LINUX_INTERFACE - else - { - offset = 0; - length = 0; - delete absoluteFilename; - absoluteFilename = nullptr; - usageMode = FileUseMode::free; - return true; } +#else + return true; #endif } -#if HAS_MASS_STORAGE -bool FileStore::ForceClose() noexcept -{ - bool ok = true; - if (usageMode == FileUseMode::readWrite) - { - ok = Flush(); - } - - if (writeBuffer != nullptr) - { - MassStorage::ReleaseWriteBuffer(writeBuffer); - writeBuffer = nullptr; - } - - const FRESULT fr = f_close(&file); - usageMode = FileUseMode::free; - closeRequested = false; - openCount = 0; - reprap.VolumesUpdated(); - return ok && fr == FR_OK; -} -#endif - bool FileStore::Seek(FilePosition pos) noexcept { switch (usageMode) @@ -309,17 +222,7 @@ bool FileStore::Seek(FilePosition pos) noexcept case FileUseMode::readOnly: case FileUseMode::readWrite: #if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -#endif - { -#if HAS_MASS_STORAGE - return f_lseek(&file, pos) == FR_OK; -#else - return false; -#endif - } -#if HAS_LINUX_INTERFACE - else + if (reprap.UsingLinuxInterface()) { const bool validTarget = offset < length; if (validTarget) @@ -329,6 +232,11 @@ bool FileStore::Seek(FilePosition pos) noexcept return validTarget; } #endif +#if HAS_MASS_STORAGE + return f_lseek(&file, pos) == FR_OK; +#else + return false; +#endif case FileUseMode::invalidated: default: @@ -339,36 +247,17 @@ bool FileStore::Seek(FilePosition pos) noexcept FilePosition FileStore::Position() const noexcept { #if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -#endif - { - return -#if HAS_MASS_STORAGE - (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.fptr : -#endif - 0; - } -#if HAS_LINUX_INTERFACE - else + if (reprap.UsingLinuxInterface()) { return offset; } #endif -} - #if HAS_MASS_STORAGE -uint32_t FileStore::ClusterSize() const noexcept -{ - return (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.obj.fs->csize * 512u : 1; // we divide by the cluster size so return 1 not 0 if there is an error -} + return (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.fptr : 0; +#else + return 0; #endif - -#if 0 // not currently used -bool FileStore::GoToEnd() -{ - return Seek(Length()); } -#endif FilePosition FileStore::Length() const noexcept { @@ -380,27 +269,22 @@ FilePosition FileStore::Length() const noexcept case FileUseMode::readOnly: #if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -#endif - { -#if HAS_MASS_STORAGE - return f_size(&file); -#else - return 0; -#endif - } -#if HAS_LINUX_INTERFACE - else + if (reprap.UsingLinuxInterface()) { return length; } #endif +#if HAS_MASS_STORAGE + return f_size(&file); +#else + return 0; +#endif case FileUseMode::readWrite: #if HAS_MASS_STORAGE return (writeBuffer != nullptr) ? f_size(&file) + writeBuffer->BytesStored() : f_size(&file); #else - return 0; + return 0; #endif case FileUseMode::invalidated: @@ -426,37 +310,33 @@ int FileStore::Read(char* extBuf, size_t nBytes) noexcept case FileUseMode::readOnly: case FileUseMode::readWrite: - { #if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -#endif + if (reprap.UsingLinuxInterface()) + { + uint32_t read = nBytes; + const bool success = reprap.GetLinuxInterface().GetFileChunk(absoluteFilename, offset, extBuf, read, length); + if (!success) { -#if HAS_MASS_STORAGE - UINT bytes_read; - FRESULT readStatus = f_read(&file, extBuf, nBytes, &bytes_read); - if (readStatus != FR_OK) - { - reprap.GetPlatform().MessageF(ErrorMessage, "Cannot read file, error code %d\n", (int)readStatus); + return -1; + } + offset += read; + return (int)read; + } #endif - return -1; #if HAS_MASS_STORAGE - } - return (int)bytes_read; -#endif - } -#if HAS_LINUX_INTERFACE - else + { + UINT bytes_read; + FRESULT readStatus = f_read(&file, extBuf, nBytes, &bytes_read); + if (readStatus != FR_OK) { - uint32_t read = nBytes; - const bool success = reprap.GetLinuxInterface().GetFileChunk(absoluteFilename, offset, extBuf, read, length); - if (!success) { - return -1; - } - offset += read; - return (int)read; + reprap.GetPlatform().MessageF(ErrorMessage, "Cannot read file, error code %d\n", (int)readStatus); + return -1; } -#endif + return (int)bytes_read; } +#else + return -1; +#endif case FileUseMode::invalidated: default: @@ -499,7 +379,83 @@ int FileStore::ReadLine(char* buf, size_t nBytes) noexcept return i; } -#if HAS_MASS_STORAGE +#if HAS_MASS_STORAGE // the remaining functions are only supported on local storage + +// Invalidate the file if it uses the specified FATFS object +bool FileStore::Invalidate(const FATFS *fs, bool doClose) noexcept +{ + if (file.obj.fs == fs) + { + if (doClose) + { + (void)ForceClose(); + } + else + { + file.obj.fs = nullptr; + if (writeBuffer != nullptr) + { + MassStorage::ReleaseWriteBuffer(writeBuffer); + writeBuffer = nullptr; + } + } + usageMode = FileUseMode::invalidated; + return true; + } + return false; +} + +// Return true if the file is open on the specified file system +bool FileStore::IsOpenOn(const FATFS *fs) const noexcept +{ + return openCount != 0 && file.obj.fs == fs; +} + +void FileStore::Duplicate() noexcept +{ + switch (usageMode) + { + case FileUseMode::free: + REPORT_INTERNAL_ERROR; + break; + + case FileUseMode::readOnly: + case FileUseMode::readWrite: + { + const irqflags_t flags = cpu_irq_save(); + ++openCount; + cpu_irq_restore(flags); + } + break; + + case FileUseMode::invalidated: + default: + break; + } +} + +bool FileStore::ForceClose() noexcept +{ + bool ok = true; + if (usageMode == FileUseMode::readWrite) + { + ok = Flush(); + } + + if (writeBuffer != nullptr) + { + MassStorage::ReleaseWriteBuffer(writeBuffer); + writeBuffer = nullptr; + } + + const FRESULT fr = f_close(&file); + usageMode = FileUseMode::free; + closeRequested = false; + openCount = 0; + reprap.VolumesUpdated(); + return ok && fr == FR_OK; +} + FRESULT FileStore::Store(const char *s, size_t len, size_t *bytesWritten) noexcept { if (calcCrc) @@ -638,9 +594,20 @@ bool FileStore::IsSameFile(const FIL& otherFile) const noexcept { return file.obj.fs == otherFile.obj.fs && file.dir_sect == otherFile.dir_sect && file.dir_ptr == otherFile.dir_ptr; } -#endif -#if 0 // not currently used +uint32_t FileStore::ClusterSize() const noexcept +{ + return (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.obj.fs->csize * 512u : 1; // we divide by the cluster size so return 1 not 0 if there is an error +} + +#endif // HAS_MASS_STORAGE + +#if 0 // these are not currently used + +bool FileStore::GoToEnd() +{ + return Seek(Length()); +} // Provide a cluster map for fast seeking. Needs _USE_FASTSEEK defined as 1 in conf_fatfs to make any difference. // The first element of the table must be set to the total number of 32-bit entries in the table before calling this. |