diff --git a/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.cpp b/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.cpp new file mode 100644 index 0000000..8b6ae7d --- /dev/null +++ b/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.cpp @@ -0,0 +1,114 @@ +// ============================================================================= +// +// Copyright (c) 2013-2016 Christopher Baker +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// ============================================================================= + + +#include "CRC32.h" + +#if defined(PROGMEM) + #define FLASH_PROGMEM PROGMEM + #define FLASH_READ_DWORD(x) (pgm_read_dword_near(x)) +#else + #define FLASH_PROGMEM + #define FLASH_READ_DWORD(x) (*(uint32_t*)(x)) +#endif + +static const uint32_t crc32_table[] FLASH_PROGMEM = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c +}; + +uint32_t CRC32::calculate(const void* data, size_t size) +{ + CRC32 crc; + crc.update(data, size); + return crc.finalize(); +} + +void CRC32::reset() +{ + state = ~0L; +} + +void CRC32::update(uint8_t data) +{ + // via http://forum.arduino.cc/index.php?topic=91179.0 + uint8_t tbl_idx; + + tbl_idx = state ^ (data >> (0 * 4)); + state = FLASH_READ_DWORD(crc32_table + (tbl_idx & 0x0f)) ^ (state >> 4); + tbl_idx = state ^ (data >> (1 * 4)); + state = FLASH_READ_DWORD(crc32_table + (tbl_idx & 0x0f)) ^ (state >> 4); +} + +void CRC32::update(const void* data, size_t size) +{ + const uint8_t* d = (const uint8_t*)data; + while (size--) { + update(*d++); + } +} + +uint32_t CRC32::finalize(const void* data, size_t size) +{ + update(data, size); + return finalize(); +} + +uint32_t CRC32::finalize() const +{ + return ~state; +} + +// Deprecated API + +uint32_t CRC32::checksum(const uint8_t* data, size_t size) +{ + CRC32 crc; + crc.update(data, size); + return crc.finalize(); +} + + +uint32_t CRC32::update(uint32_t checksum, uint8_t data) +{ + // via http://forum.arduino.cc/index.php?topic=91179.0 + uint8_t tbl_idx; + + tbl_idx = checksum ^ (data >> (0 * 4)); + checksum = pgm_read_dword_near(crc32_table + (tbl_idx & 0x0f)) ^ (checksum >> 4); + tbl_idx = checksum ^ (data >> (1 * 4)); + checksum = pgm_read_dword_near(crc32_table + (tbl_idx & 0x0f)) ^ (checksum >> 4); + + return checksum; +} + + +uint32_t CRC32::update(uint32_t checksum, const uint8_t* data, size_t size) +{ + while(size--) checksum = update(checksum, *data++); + + return checksum; +} diff --git a/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.h b/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.h new file mode 100644 index 0000000..47ae2ee --- /dev/null +++ b/STM32/libraries/SDIO/examples/copytest/CRC32/CRC32.h @@ -0,0 +1,66 @@ +// ============================================================================= +// +// Copyright (c) 2013-2016 Christopher Baker +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// ============================================================================= + +#ifndef CRC32_H +#define CRC32_H + +#if defined(SPARK) || defined(PARTICLE) + #include "application.h" +#elif defined(ARDUINO) + #if ARDUINO >= 100 + #include "Arduino.h" + #else + #include "WProgram.h" + #endif +#endif + +class CRC32 +{ +public: + static uint32_t calculate(const void* data, size_t size); + +public: + CRC32() { reset(); } + + void reset(); + void update(uint8_t data); + void update(const void* data, size_t size); + uint32_t finalize(const void* data, size_t size); + uint32_t finalize() const; + + // Deprecated API + __attribute__ ((deprecated)) + static uint32_t checksum(const uint8_t* data, size_t size); + + __attribute__ ((deprecated)) + static uint32_t update(uint32_t checksum, uint8_t data); + + __attribute__ ((deprecated)) + static uint32_t update(uint32_t checksum, const uint8_t* data, size_t size); + +private: + uint32_t state; +}; + +#endif diff --git a/STM32/libraries/SDIO/examples/copytest/copytest.ino b/STM32/libraries/SDIO/examples/copytest/copytest.ino index d55cb2c..2fe6d15 100644 --- a/STM32/libraries/SDIO/examples/copytest/copytest.ino +++ b/STM32/libraries/SDIO/examples/copytest/copytest.ino @@ -1,17 +1,19 @@ /* - SDcard SDIO example - Copy Test - copy binaries + SDcard SDIO example - Copy Test - copy binaries Buffer of BUFSIZE bytes is used for writing. You have to place a binary called "test_in.bin" on the SDcard and run the sketch. You will get the "test_out.bin" after the copy finishes. Pito 5/2016, no warranties of any kind - Pito 5/2017, no warranties of any kind + Pito 5/2017, no warranties of any kind */ #include "SDIO.h" #include "STM32SdFatSdio.h" +#include "CRC32/CRC32.h" STM32SdFatSdio sd; SdFile myFileIn; SdFile myFileOut; +CRC32 crc; #define BUFSIZE 32*1024 @@ -19,55 +21,109 @@ SdFile myFileOut; ArduinoOutStream cout(Serial); void setup() { - Serial.begin(115200); - delay(1000); - cout << F("\nUse a freshly formatted SD for best performance.\n"); - // Discard any input. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); - - Serial.println("Type any character to start\n"); - while (!Serial.available()) { - SysCall::yield(); - } - - if (!sd.begin()) { - sd.initErrorHalt(); - } - Serial.println("*************************************************"); - Serial.println("Opening the read file.."); - // open the file for Read - if (!myFileIn.open("test_in.bin", O_RDONLY)) { - sd.errorHalt("opening test_in.bin for Read failed"); - } - - Serial.println("Opening the write file.."); - // open the file for Write - if (!myFileOut.open("test_out.bin", O_WRITE | O_CREAT)) { - sd.errorHalt("opening test_out.bin for Write failed"); - } - - // Read from myFileIn and write to myFileOut via a Buffer - Serial.println("Reading and Writing.."); - uint8_t buf[BUFSIZE]; - uint32_t nr; - uint32_t t = millis(); - while ((nr = myFileIn.read(buf, BUFSIZE)) > 0) { - if (nr < BUFSIZE){ - myFileOut.write(buf, nr); } - else { - myFileOut.write(buf, BUFSIZE); } - } - t = millis() - t; - // close the files - myFileIn.close(); - myFileOut.close(); - Serial.println("*************************************************"); - Serial.print("Done in "); - Serial.print(t); - Serial.print(" msecs"); + Serial.begin(115200); + delay(1000); + cout << F("\nUse a freshly formatted SD for best performance.\n"); + // Discard any input. + do { + delay(10); + } while (Serial.available() && Serial.read() >= 0); + + Serial.println("Type any character to start\n"); + while (!Serial.available()) { + SysCall::yield(); + } + + if (!sd.begin()) { + sd.initErrorHalt(); + } } void loop() { -} \ No newline at end of file + Serial.println("*************************************************"); + Serial.println("Opening the read file.."); + // open the file for Read + if (!myFileIn.open("test_in.bin", O_RDONLY)) { + sd.errorHalt("opening test_in.bin for Read failed"); + } + + Serial.println("Opening the write file.."); + // open the file for Write + if (!myFileOut.open("test_out.bin", O_WRITE | O_CREAT)) { + sd.errorHalt("opening test_out.bin for Write failed"); + } + + // Read from myFileIn and write to myFileOut via a Buffer + Serial.println("Reading and Writing.."); + uint8_t buf[BUFSIZE]; + uint32_t nr; + uint32_t t = millis(); + while ((nr = myFileIn.read(buf, BUFSIZE)) > 0) { + if (nr < BUFSIZE){ + myFileOut.write(buf, nr); } + else { + myFileOut.write(buf, BUFSIZE); } + } + t = millis() - t; + // close the files + myFileIn.close(); + myFileOut.close(); + Serial.println("*************************************************"); + Serial.print("Done in "); + Serial.print(t); + Serial.println(" msecs"); + + /* + * CRC Calculations + */ + Serial.println("*************************************************"); + Serial.println("Running CRC calculations..."); + t = millis(); + + if (!myFileIn.open("test_in.bin", O_RDONLY)) { + sd.errorHalt("opening test_in.bin for CRC calculation failed"); + } + crc.reset(); + while ((nr = myFileIn.read(buf, BUFSIZE)) > 0) { + crc.update(buf,nr); + } + uint32_t checksumIn = crc.finalize(); + myFileIn.close(); + + if (!myFileIn.open("test_out.bin", O_RDONLY)) { + sd.errorHalt("opening test_out.bin for CRC calculation failed"); + } + crc.reset(); + while ((nr = myFileIn.read(buf, BUFSIZE)) > 0) { + crc.update(buf,nr); + } + uint32_t checksumOut = crc.finalize(); + t = millis() - t; + + Serial.print("File in CRC: "); + Serial.println(checksumIn, HEX); + Serial.print("File out CRC: "); + Serial.println(checksumOut, HEX); + if (checksumIn != checksumOut) { + Serial.println("**CHECKSUM DID NOT MATCH!"); + } + Serial.println("*************************************************"); + Serial.print("Done in "); + Serial.print(t); + Serial.print(" msecs"); + + myFileIn.close(); + + + + Serial.println("Type any character to start\n"); + while (!Serial.available()) { + SysCall::yield(); + } + if (!myFileOut.open("test_out.bin", O_RDWR)) { + sd.errorHalt("opening test_out.bin for delete failed"); + } + if (!myFileOut.remove()) { + sd.errorHalt("removing test_out.bin failed"); + } +} diff --git a/STM32/libraries/SDIO/src/SDIO.cpp b/STM32/libraries/SDIO/src/SDIO.cpp index cc93b9e..37340c3 100644 --- a/STM32/libraries/SDIO/src/SDIO.cpp +++ b/STM32/libraries/SDIO/src/SDIO.cpp @@ -20,7 +20,9 @@ inline bool setSdErrorCode(uint8_t code, uint32_t line) { uint8_t SDIOClass::begin() { //GPIO_InitTypeDef GPIO_InitStruct; - + if (hsd.State == HAL_SD_STATE_READY){ + return true; + } __HAL_RCC_SDIO_CLK_ENABLE(); stm32AfSDIO4BitInit(SDIO, NULL, 0, NULL, 0, @@ -77,11 +79,14 @@ uint8_t SDIOClass::begin() { /* * Up to here */ - _useDMA = false; + _useDMA = true; m_errorCode = SD_CARD_ERROR_NONE; return true; } +uint8_t SDIOClass::end() { + return (HAL_SD_DeInit(&hsd) == HAL_OK); +} uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) { if (((uint32_t)dst & 0x3U) != 0){ @@ -94,7 +99,8 @@ uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) { return false; } - return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; +//common with dma, so it's down at the end + //return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; } else { hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; @@ -108,7 +114,7 @@ uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) { // We need to block here, until we implement a callback feature uint32_t tickstart = HAL_GetTick(); while (hsd.State == HAL_SD_STATE_BUSY){ - if((HAL_GetTick() - tickstart) >= sd_timeout) + if((HAL_GetTick() - tickstart) >= sdRdTimeout * nb) { /* Abort transfer and send return error */ HAL_SD_Abort(&hsd); @@ -118,9 +124,12 @@ uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) { if (hsd.State != HAL_SD_STATE_READY ) { return false; } - - return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; + if (__HAL_SD_GET_FLAG(&hsd,SDIO_FLAG_DCRCFAIL)) { + //return false; + while (1); //stay here + } } + return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; } uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) { @@ -133,7 +142,8 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) { if (state != HAL_OK) { return false; } - return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; +//common with dma, so it's down at the end + //return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; } else { hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; @@ -147,13 +157,13 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) { /* * We need to block here, until we implement a callback feature * TODO: better check if the card is still in programming mode. - * Also confirm the timeout to wait from the specs, currently sd_timeout=100 + * Also confirm the timeout to wait from the specs, currently sd_timeout * It may need to be multiplied by a factor depending on number of blocks. * Finally, perhaps rename sd_timeout to something else */ uint32_t tickstart = HAL_GetTick(); while (hsd.State == HAL_SD_STATE_BUSY){ - if((HAL_GetTick() - tickstart) >= sd_timeout) + if((HAL_GetTick() - tickstart) >= sdWrTimeout * nb+1) { /* Abort transfer and send return error */ HAL_SD_Abort(&hsd); @@ -163,9 +173,13 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) { if (hsd.State != HAL_SD_STATE_READY) { return false; } + } + if (__HAL_SD_GET_FLAG(&hsd,SDIO_FLAG_DCRCFAIL)) { + //return false; + while (1); //stay here + } while (HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_PROGRAMMING); return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER; - } } bool SDIOClass::erase(uint32_t firstBlock, uint32_t lastBlock) { diff --git a/STM32/libraries/SDIO/src/SDIO.h b/STM32/libraries/SDIO/src/SDIO.h index c25afb5..2115e51 100644 --- a/STM32/libraries/SDIO/src/SDIO.h +++ b/STM32/libraries/SDIO/src/SDIO.h @@ -7,7 +7,7 @@ #define sdRdTimeout 100 #define sdWrTimeout 500 #define sdErTimeout 250 -#define sd_timeout 2000 // timeout in ms in the new HAL API +#define sd_timeout 250 // timeout in ms in the new HAL API /* * Auxiliary macros to derive several names from the same values