Merge pull request #7471 from thinkyhead/bf1_cleanups_aug9
Miscellaneous style tweaks
This commit is contained in:
commit
6172f150c2
@ -681,16 +681,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#define WRITE_FAN_N(n, v) WRITE_FAN##n(v)
|
#define WRITE_FAN_N(n, v) WRITE_FAN##n(v)
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Heater & Fan Pausing
|
|
||||||
*/
|
|
||||||
#if FAN_COUNT == 0
|
|
||||||
#undef PROBING_FANS_OFF
|
|
||||||
#endif
|
|
||||||
#define QUIET_PROBING (HAS_BED_PROBE && (ENABLED(PROBING_HEATERS_OFF) || ENABLED(PROBING_FANS_OFF) || DELAY_BEFORE_PROBING > 0))
|
|
||||||
#define HEATER_IDLE_HANDLER (ENABLED(ADVANCED_PAUSE_FEATURE) || ENABLED(PROBING_HEATERS_OFF))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Servos and probes
|
* Servos and probes
|
||||||
*/
|
*/
|
||||||
@ -702,7 +692,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PROBE_PIN_CONFIGURED (HAS_Z_MIN_PROBE_PIN || (HAS_Z_MIN && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)))
|
#define PROBE_PIN_CONFIGURED (HAS_Z_MIN_PROBE_PIN || (HAS_Z_MIN && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)))
|
||||||
|
|
||||||
#define HAS_BED_PROBE (PROBE_SELECTED && PROBE_PIN_CONFIGURED && DISABLED(PROBE_MANUALLY))
|
#define HAS_BED_PROBE (PROBE_SELECTED && PROBE_PIN_CONFIGURED && DISABLED(PROBE_MANUALLY))
|
||||||
|
|
||||||
#if ENABLED(Z_PROBE_ALLEN_KEY)
|
#if ENABLED(Z_PROBE_ALLEN_KEY)
|
||||||
@ -743,6 +732,15 @@
|
|||||||
#define Z_PROBE_OFFSET_FROM_EXTRUDER 0
|
#define Z_PROBE_OFFSET_FROM_EXTRUDER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Heater & Fan Pausing
|
||||||
|
*/
|
||||||
|
#if FAN_COUNT == 0
|
||||||
|
#undef PROBING_FANS_OFF
|
||||||
|
#endif
|
||||||
|
#define QUIET_PROBING (HAS_BED_PROBE && (ENABLED(PROBING_HEATERS_OFF) || ENABLED(PROBING_FANS_OFF) || DELAY_BEFORE_PROBING > 0))
|
||||||
|
#define HEATER_IDLE_HANDLER (ENABLED(ADVANCED_PAUSE_FEATURE) || ENABLED(PROBING_HEATERS_OFF))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delta radius/rod trimmers/angle trimmers
|
* Delta radius/rod trimmers/angle trimmers
|
||||||
*/
|
*/
|
||||||
|
@ -2359,10 +2359,11 @@ static void clean_up_after_endstop_or_probe_move() {
|
|||||||
|
|
||||||
const float nx = lx - (X_PROBE_OFFSET_FROM_EXTRUDER), ny = ly - (Y_PROBE_OFFSET_FROM_EXTRUDER);
|
const float nx = lx - (X_PROBE_OFFSET_FROM_EXTRUDER), ny = ly - (Y_PROBE_OFFSET_FROM_EXTRUDER);
|
||||||
|
|
||||||
if (printable) {
|
if (printable
|
||||||
if (!position_is_reachable_by_probe_xy(lx, ly)) return NAN;
|
? !position_is_reachable_xy(nx, ny)
|
||||||
}
|
: !position_is_reachable_by_probe_xy(lx, ly)
|
||||||
else if (!position_is_reachable_xy(nx, ny)) return NAN;
|
) return NAN;
|
||||||
|
|
||||||
|
|
||||||
const float old_feedrate_mm_s = feedrate_mm_s;
|
const float old_feedrate_mm_s = feedrate_mm_s;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** SPI receive a byte */
|
/** SPI receive a byte */
|
||||||
static uint8_t spiRec() {
|
static uint8_t spiRec() {
|
||||||
SPDR = 0XFF;
|
SPDR = 0xFF;
|
||||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||||
return SPDR;
|
return SPDR;
|
||||||
}
|
}
|
||||||
@ -64,11 +64,11 @@
|
|||||||
static inline __attribute__((always_inline))
|
static inline __attribute__((always_inline))
|
||||||
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||||
if (nbyte-- == 0) return;
|
if (nbyte-- == 0) return;
|
||||||
SPDR = 0XFF;
|
SPDR = 0xFF;
|
||||||
for (uint16_t i = 0; i < nbyte; i++) {
|
for (uint16_t i = 0; i < nbyte; i++) {
|
||||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||||
buf[i] = SPDR;
|
buf[i] = SPDR;
|
||||||
SPDR = 0XFF;
|
SPDR = 0xFF;
|
||||||
}
|
}
|
||||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||||
buf[nbyte] = SPDR;
|
buf[nbyte] = SPDR;
|
||||||
@ -103,7 +103,7 @@
|
|||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
// no interrupts during byte receive - about 8 us
|
// no interrupts during byte receive - about 8 us
|
||||||
cli();
|
cli();
|
||||||
// output pin high - like sending 0XFF
|
// output pin high - like sending 0xFF
|
||||||
WRITE(SPI_MOSI_PIN, HIGH);
|
WRITE(SPI_MOSI_PIN, HIGH);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
@ -137,7 +137,7 @@
|
|||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
WRITE(SPI_SCK_PIN, LOW);
|
WRITE(SPI_SCK_PIN, LOW);
|
||||||
|
|
||||||
WRITE(SPI_MOSI_PIN, data & 0X80);
|
WRITE(SPI_MOSI_PIN, data & 0x80);
|
||||||
|
|
||||||
data <<= 1;
|
data <<= 1;
|
||||||
|
|
||||||
@ -177,16 +177,16 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
|
|||||||
for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
|
for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
|
||||||
|
|
||||||
// send CRC
|
// send CRC
|
||||||
uint8_t crc = 0XFF;
|
uint8_t crc = 0xFF;
|
||||||
if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
|
if (cmd == CMD0) crc = 0x95; // correct crc for CMD0 with arg 0
|
||||||
if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
|
if (cmd == CMD8) crc = 0x87; // correct crc for CMD8 with arg 0x1AA
|
||||||
spiSend(crc);
|
spiSend(crc);
|
||||||
|
|
||||||
// skip stuff byte for stop read
|
// skip stuff byte for stop read
|
||||||
if (cmd == CMD12) spiRec();
|
if (cmd == CMD12) spiRec();
|
||||||
|
|
||||||
// wait for response
|
// wait for response
|
||||||
for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) { /* Intentionally left empty */ }
|
for (uint8_t i = 0; ((status_ = spiRec()) & 0x80) && i != 0xFF; i++) { /* Intentionally left empty */ }
|
||||||
return status_;
|
return status_;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -244,7 +244,7 @@ void Sd2Card::chipSelectLow() {
|
|||||||
*/
|
*/
|
||||||
bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||||
csd_t csd;
|
csd_t csd;
|
||||||
if (!readCSD(&csd)) goto fail;
|
if (!readCSD(&csd)) goto FAIL;
|
||||||
// check for single block erase
|
// check for single block erase
|
||||||
if (!csd.v1.erase_blk_en) {
|
if (!csd.v1.erase_blk_en) {
|
||||||
// erase size mask
|
// erase size mask
|
||||||
@ -252,7 +252,7 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
|||||||
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
|
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
|
||||||
// error card can't erase specified area
|
// error card can't erase specified area
|
||||||
error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
|
error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type_ != SD_CARD_TYPE_SDHC) {
|
if (type_ != SD_CARD_TYPE_SDHC) {
|
||||||
@ -263,15 +263,15 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
|||||||
|| cardCommand(CMD33, lastBlock)
|
|| cardCommand(CMD33, lastBlock)
|
||||||
|| cardCommand(CMD38, 0)) {
|
|| cardCommand(CMD38, 0)) {
|
||||||
error(SD_CARD_ERROR_ERASE);
|
error(SD_CARD_ERROR_ERASE);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -329,13 +329,13 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||||||
#endif // SOFTWARE_SPI
|
#endif // SOFTWARE_SPI
|
||||||
|
|
||||||
// must supply min of 74 clock cycles with CS high.
|
// must supply min of 74 clock cycles with CS high.
|
||||||
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
|
for (uint8_t i = 0; i < 10; i++) spiSend(0xFF);
|
||||||
|
|
||||||
// command to go idle in SPI mode
|
// command to go idle in SPI mode
|
||||||
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
|
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
|
||||||
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
|
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
|
||||||
error(SD_CARD_ERROR_CMD0);
|
error(SD_CARD_ERROR_CMD0);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check SD version
|
// check SD version
|
||||||
@ -345,29 +345,29 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||||||
else {
|
else {
|
||||||
// only need last byte of r7 response
|
// only need last byte of r7 response
|
||||||
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
|
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
|
||||||
if (status_ != 0XAA) {
|
if (status_ != 0xAA) {
|
||||||
error(SD_CARD_ERROR_CMD8);
|
error(SD_CARD_ERROR_CMD8);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
type(SD_CARD_TYPE_SD2);
|
type(SD_CARD_TYPE_SD2);
|
||||||
}
|
}
|
||||||
// initialize card and send host supports SDHC if SD2
|
// initialize card and send host supports SDHC if SD2
|
||||||
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
arg = type() == SD_CARD_TYPE_SD2 ? 0x40000000 : 0;
|
||||||
|
|
||||||
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
|
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
|
||||||
// check for timeout
|
// check for timeout
|
||||||
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
|
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
|
||||||
error(SD_CARD_ERROR_ACMD41);
|
error(SD_CARD_ERROR_ACMD41);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if SD2 read OCR register to check for SDHC card
|
// if SD2 read OCR register to check for SDHC card
|
||||||
if (type() == SD_CARD_TYPE_SD2) {
|
if (type() == SD_CARD_TYPE_SD2) {
|
||||||
if (cardCommand(CMD58, 0)) {
|
if (cardCommand(CMD58, 0)) {
|
||||||
error(SD_CARD_ERROR_CMD58);
|
error(SD_CARD_ERROR_CMD58);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
|
if ((spiRec() & 0xC0) == 0xC0) type(SD_CARD_TYPE_SDHC);
|
||||||
// discard rest of ocr - contains allowed voltage range
|
// discard rest of ocr - contains allowed voltage range
|
||||||
for (uint8_t i = 0; i < 3; i++) spiRec();
|
for (uint8_t i = 0; i < 3; i++) spiRec();
|
||||||
}
|
}
|
||||||
@ -380,7 +380,7 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||||||
return true;
|
return true;
|
||||||
#endif // SOFTWARE_SPI
|
#endif // SOFTWARE_SPI
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -473,7 +473,7 @@ static const uint16_t crctab[] PROGMEM = {
|
|||||||
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||||
uint16_t crc = 0;
|
uint16_t crc = 0;
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8);
|
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
@ -486,12 +486,12 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
|||||||
while ((status_ = spiRec()) == 0XFF) {
|
while ((status_ = spiRec()) == 0XFF) {
|
||||||
if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
|
if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
|
||||||
error(SD_CARD_ERROR_READ_TIMEOUT);
|
error(SD_CARD_ERROR_READ_TIMEOUT);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status_ != DATA_START_BLOCK) {
|
if (status_ != DATA_START_BLOCK) {
|
||||||
error(SD_CARD_ERROR_READ);
|
error(SD_CARD_ERROR_READ);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// transfer data
|
// transfer data
|
||||||
spiRead(dst, count);
|
spiRead(dst, count);
|
||||||
@ -503,7 +503,7 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
|||||||
recvCrc |= spiRec();
|
recvCrc |= spiRec();
|
||||||
if (calcCrc != recvCrc) {
|
if (calcCrc != recvCrc) {
|
||||||
error(SD_CARD_ERROR_CRC);
|
error(SD_CARD_ERROR_CRC);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -515,7 +515,7 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
|||||||
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
|
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
|
||||||
spiSend(0XFF);
|
spiSend(0XFF);
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
|
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
|
||||||
spiSend(0XFF);
|
spiSend(0XFF);
|
||||||
@ -527,10 +527,10 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
|||||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
||||||
if (cardCommand(cmd, 0)) {
|
if (cardCommand(cmd, 0)) {
|
||||||
error(SD_CARD_ERROR_READ_REG);
|
error(SD_CARD_ERROR_READ_REG);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
return readData(dst, 16);
|
return readData(dst, 16);
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -549,11 +549,11 @@ bool Sd2Card::readStart(uint32_t blockNumber) {
|
|||||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||||
if (cardCommand(CMD18, blockNumber)) {
|
if (cardCommand(CMD18, blockNumber)) {
|
||||||
error(SD_CARD_ERROR_CMD18);
|
error(SD_CARD_ERROR_CMD18);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -567,11 +567,11 @@ bool Sd2Card::readStop() {
|
|||||||
chipSelectLow();
|
chipSelectLow();
|
||||||
if (cardCommand(CMD12, 0)) {
|
if (cardCommand(CMD12, 0)) {
|
||||||
error(SD_CARD_ERROR_CMD12);
|
error(SD_CARD_ERROR_CMD12);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -601,10 +601,10 @@ bool Sd2Card::setSckRate(uint8_t sckRateID) {
|
|||||||
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
|
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
|
||||||
uint16_t t0 = millis();
|
uint16_t t0 = millis();
|
||||||
while (spiRec() != 0XFF) {
|
while (spiRec() != 0XFF) {
|
||||||
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
|
if (((uint16_t)millis() - t0) >= timeoutMillis) goto FAIL;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -621,23 +621,23 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
|||||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||||
if (cardCommand(CMD24, blockNumber)) {
|
if (cardCommand(CMD24, blockNumber)) {
|
||||||
error(SD_CARD_ERROR_CMD24);
|
error(SD_CARD_ERROR_CMD24);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
if (!writeData(DATA_START_BLOCK, src)) goto fail;
|
if (!writeData(DATA_START_BLOCK, src)) goto FAIL;
|
||||||
|
|
||||||
// wait for flash programming to complete
|
// wait for flash programming to complete
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// response is r2 so get and check two bytes for nonzero
|
// response is r2 so get and check two bytes for nonzero
|
||||||
if (cardCommand(CMD13, 0) || spiRec()) {
|
if (cardCommand(CMD13, 0) || spiRec()) {
|
||||||
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
|
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -650,11 +650,11 @@ fail:
|
|||||||
bool Sd2Card::writeData(const uint8_t* src) {
|
bool Sd2Card::writeData(const uint8_t* src) {
|
||||||
chipSelectLow();
|
chipSelectLow();
|
||||||
// wait for previous write to finish
|
// wait for previous write to finish
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
|
||||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
|
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto FAIL;
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
error(SD_CARD_ERROR_WRITE_MULTIPLE);
|
error(SD_CARD_ERROR_WRITE_MULTIPLE);
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
@ -670,10 +670,10 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
|||||||
status_ = spiRec();
|
status_ = spiRec();
|
||||||
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
||||||
error(SD_CARD_ERROR_WRITE);
|
error(SD_CARD_ERROR_WRITE);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -693,17 +693,17 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
|
|||||||
// send pre-erase count
|
// send pre-erase count
|
||||||
if (cardAcmd(ACMD23, eraseCount)) {
|
if (cardAcmd(ACMD23, eraseCount)) {
|
||||||
error(SD_CARD_ERROR_ACMD23);
|
error(SD_CARD_ERROR_ACMD23);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// use address if not SDHC card
|
// use address if not SDHC card
|
||||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||||
if (cardCommand(CMD25, blockNumber)) {
|
if (cardCommand(CMD25, blockNumber)) {
|
||||||
error(SD_CARD_ERROR_CMD25);
|
error(SD_CARD_ERROR_CMD25);
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -715,12 +715,12 @@ fail:
|
|||||||
*/
|
*/
|
||||||
bool Sd2Card::writeStop() {
|
bool Sd2Card::writeStop() {
|
||||||
chipSelectLow();
|
chipSelectLow();
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
|
||||||
spiSend(STOP_TRAN_TOKEN);
|
spiSend(STOP_TRAN_TOKEN);
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
error(SD_CARD_ERROR_STOP_TRAN);
|
error(SD_CARD_ERROR_STOP_TRAN);
|
||||||
chipSelectHigh();
|
chipSelectHigh();
|
||||||
return false;
|
return false;
|
||||||
|
@ -92,27 +92,27 @@ uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE;
|
|||||||
/** card returned an error token instead of read data */
|
/** card returned an error token instead of read data */
|
||||||
uint8_t const SD_CARD_ERROR_READ = 0XF;
|
uint8_t const SD_CARD_ERROR_READ = 0XF;
|
||||||
/** read CID or CSD failed */
|
/** read CID or CSD failed */
|
||||||
uint8_t const SD_CARD_ERROR_READ_REG = 0X10;
|
uint8_t const SD_CARD_ERROR_READ_REG = 0x10;
|
||||||
/** timeout while waiting for start of read data */
|
/** timeout while waiting for start of read data */
|
||||||
uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X11;
|
uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0x11;
|
||||||
/** card did not accept STOP_TRAN_TOKEN */
|
/** card did not accept STOP_TRAN_TOKEN */
|
||||||
uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X12;
|
uint8_t const SD_CARD_ERROR_STOP_TRAN = 0x12;
|
||||||
/** card returned an error token as a response to a write operation */
|
/** card returned an error token as a response to a write operation */
|
||||||
uint8_t const SD_CARD_ERROR_WRITE = 0X13;
|
uint8_t const SD_CARD_ERROR_WRITE = 0x13;
|
||||||
/** attempt to write protected block zero */
|
/** attempt to write protected block zero */
|
||||||
uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14; // REMOVE - not used
|
uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14; // REMOVE - not used
|
||||||
/** card did not go ready for a multiple block write */
|
/** card did not go ready for a multiple block write */
|
||||||
uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15;
|
uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0x15;
|
||||||
/** card returned an error to a CMD13 status check after a write */
|
/** card returned an error to a CMD13 status check after a write */
|
||||||
uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
|
uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16;
|
||||||
/** timeout occurred during write programming */
|
/** timeout occurred during write programming */
|
||||||
uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X17;
|
uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0x17;
|
||||||
/** incorrect rate selected */
|
/** incorrect rate selected */
|
||||||
uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18;
|
uint8_t const SD_CARD_ERROR_SCK_RATE = 0x18;
|
||||||
/** init() not called */
|
/** init() not called */
|
||||||
uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19;
|
uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0x19;
|
||||||
/** crc check error */
|
/** crc check error */
|
||||||
uint8_t const SD_CARD_ERROR_CRC = 0X20;
|
uint8_t const SD_CARD_ERROR_CRC = 0x20;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// card types
|
// card types
|
||||||
/** Standard capacity V1 SD card */
|
/** Standard capacity V1 SD card */
|
||||||
|
@ -39,7 +39,7 @@ void (*SdBaseFile::dateTime_)(uint16_t* date, uint16_t* time) = 0;
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// add a cluster to a file
|
// add a cluster to a file
|
||||||
bool SdBaseFile::addCluster() {
|
bool SdBaseFile::addCluster() {
|
||||||
if (!vol_->allocContiguous(1, &curCluster_)) goto fail;
|
if (!vol_->allocContiguous(1, &curCluster_)) goto FAIL;
|
||||||
|
|
||||||
// if first cluster of file link to directory entry
|
// if first cluster of file link to directory entry
|
||||||
if (firstCluster_ == 0) {
|
if (firstCluster_ == 0) {
|
||||||
@ -48,7 +48,7 @@ bool SdBaseFile::addCluster() {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -57,10 +57,10 @@ bool SdBaseFile::addCluster() {
|
|||||||
bool SdBaseFile::addDirCluster() {
|
bool SdBaseFile::addDirCluster() {
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
// max folder size
|
// max folder size
|
||||||
if (fileSize_ / sizeof(dir_t) >= 0XFFFF) goto fail;
|
if (fileSize_ / sizeof(dir_t) >= 0xFFFF) goto FAIL;
|
||||||
|
|
||||||
if (!addCluster()) goto fail;
|
if (!addCluster()) goto FAIL;
|
||||||
if (!vol_->cacheFlush()) goto fail;
|
if (!vol_->cacheFlush()) goto FAIL;
|
||||||
|
|
||||||
block = vol_->clusterStartBlock(curCluster_);
|
block = vol_->clusterStartBlock(curCluster_);
|
||||||
|
|
||||||
@ -72,21 +72,21 @@ bool SdBaseFile::addDirCluster() {
|
|||||||
|
|
||||||
// zero rest of cluster
|
// zero rest of cluster
|
||||||
for (uint8_t i = 1; i < vol_->blocksPerCluster_; i++) {
|
for (uint8_t i = 1; i < vol_->blocksPerCluster_; i++) {
|
||||||
if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) goto fail;
|
if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) goto FAIL;
|
||||||
}
|
}
|
||||||
// Increase directory file size by cluster size
|
// Increase directory file size by cluster size
|
||||||
fileSize_ += 512UL << vol_->clusterSizeShift_;
|
fileSize_ += 512UL << vol_->clusterSizeShift_;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// cache a file's directory entry
|
// cache a file's directory entry
|
||||||
// return pointer to cached entry or null for failure
|
// return pointer to cached entry or null for failure
|
||||||
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
|
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
|
||||||
if (!vol_->cacheRawBlock(dirBlock_, action)) goto fail;
|
if (!vol_->cacheRawBlock(dirBlock_, action)) goto FAIL;
|
||||||
return vol_->cache()->dir + dirIndex_;
|
return vol_->cache()->dir + dirIndex_;
|
||||||
fail:
|
FAIL:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -115,16 +115,16 @@ bool SdBaseFile::close() {
|
|||||||
*/
|
*/
|
||||||
bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
|
bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
|
||||||
// error if no blocks
|
// error if no blocks
|
||||||
if (firstCluster_ == 0) goto fail;
|
if (firstCluster_ == 0) goto FAIL;
|
||||||
|
|
||||||
for (uint32_t c = firstCluster_; ; c++) {
|
for (uint32_t c = firstCluster_; ; c++) {
|
||||||
uint32_t next;
|
uint32_t next;
|
||||||
if (!vol_->fatGet(c, &next)) goto fail;
|
if (!vol_->fatGet(c, &next)) goto FAIL;
|
||||||
|
|
||||||
// check for contiguous
|
// check for contiguous
|
||||||
if (next != (c + 1)) {
|
if (next != (c + 1)) {
|
||||||
// error if not end of chain
|
// error if not end of chain
|
||||||
if (!vol_->isEOC(next)) goto fail;
|
if (!vol_->isEOC(next)) goto FAIL;
|
||||||
*bgnBlock = vol_->clusterStartBlock(firstCluster_);
|
*bgnBlock = vol_->clusterStartBlock(firstCluster_);
|
||||||
*endBlock = vol_->clusterStartBlock(c)
|
*endBlock = vol_->clusterStartBlock(c)
|
||||||
+ vol_->blocksPerCluster_ - 1;
|
+ vol_->blocksPerCluster_ - 1;
|
||||||
@ -132,7 +132,7 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -157,8 +157,8 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
|
|||||||
const char* path, uint32_t size) {
|
const char* path, uint32_t size) {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
// don't allow zero length file
|
// don't allow zero length file
|
||||||
if (size == 0) goto fail;
|
if (size == 0) goto FAIL;
|
||||||
if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) goto fail;
|
if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) goto FAIL;
|
||||||
|
|
||||||
// calculate number of clusters needed
|
// calculate number of clusters needed
|
||||||
count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
|
count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
|
||||||
@ -166,7 +166,7 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
|
|||||||
// allocate clusters
|
// allocate clusters
|
||||||
if (!vol_->allocContiguous(count, &firstCluster_)) {
|
if (!vol_->allocContiguous(count, &firstCluster_)) {
|
||||||
remove();
|
remove();
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
fileSize_ = size;
|
fileSize_ = size;
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
|
|||||||
flags_ |= F_FILE_DIR_DIRTY;
|
flags_ |= F_FILE_DIR_DIRTY;
|
||||||
|
|
||||||
return sync();
|
return sync();
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -188,16 +188,16 @@ fail:
|
|||||||
bool SdBaseFile::dirEntry(dir_t* dir) {
|
bool SdBaseFile::dirEntry(dir_t* dir) {
|
||||||
dir_t* p;
|
dir_t* p;
|
||||||
// make sure fields on SD are correct
|
// make sure fields on SD are correct
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
|
|
||||||
// read entry
|
// read entry
|
||||||
p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
|
p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
// copy to caller's struct
|
// copy to caller's struct
|
||||||
memcpy(dir, p, sizeof(dir_t));
|
memcpy(dir, p, sizeof(dir_t));
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -395,7 +395,7 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
|
|||||||
while (*str != '\0' && *str != '/') {
|
while (*str != '\0' && *str != '/') {
|
||||||
c = *str++;
|
c = *str++;
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
if (n == 10) goto fail; // only one dot allowed
|
if (n == 10) goto FAIL; // only one dot allowed
|
||||||
n = 10; // max index for full 8.3 name
|
n = 10; // max index for full 8.3 name
|
||||||
i = 8; // place for extension
|
i = 8; // place for extension
|
||||||
}
|
}
|
||||||
@ -403,9 +403,9 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
|
|||||||
// illegal FAT characters
|
// illegal FAT characters
|
||||||
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
|
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
while ((b = pgm_read_byte(p++))) if (b == c) goto fail;
|
while ((b = pgm_read_byte(p++))) if (b == c) goto FAIL;
|
||||||
// check size and only allow ASCII printable characters
|
// check size and only allow ASCII printable characters
|
||||||
if (i > n || c < 0x21 || c == 0x7F) goto fail;
|
if (i > n || c < 0x21 || c == 0x7F) goto FAIL;
|
||||||
// only upper case allowed in 8.3 names - convert lower to upper
|
// only upper case allowed in 8.3 names - convert lower to upper
|
||||||
name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
|
name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
|
|||||||
*ptr = str;
|
*ptr = str;
|
||||||
// must have a file name, extension is optional
|
// must have a file name, extension is optional
|
||||||
return name[0] != ' ';
|
return name[0] != ' ';
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -437,22 +437,22 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
|
|||||||
SdBaseFile* sub = &dir1;
|
SdBaseFile* sub = &dir1;
|
||||||
SdBaseFile* start = parent;
|
SdBaseFile* start = parent;
|
||||||
|
|
||||||
if (!parent || isOpen()) goto fail;
|
if (!parent || isOpen()) goto FAIL;
|
||||||
|
|
||||||
if (*path == '/') {
|
if (*path == '/') {
|
||||||
while (*path == '/') path++;
|
while (*path == '/') path++;
|
||||||
if (!parent->isRoot()) {
|
if (!parent->isRoot()) {
|
||||||
if (!dir2.openRoot(parent->vol_)) goto fail;
|
if (!dir2.openRoot(parent->vol_)) goto FAIL;
|
||||||
parent = &dir2;
|
parent = &dir2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!make83Name(path, dname, &path)) goto fail;
|
if (!make83Name(path, dname, &path)) goto FAIL;
|
||||||
while (*path == '/') path++;
|
while (*path == '/') path++;
|
||||||
if (!*path) break;
|
if (!*path) break;
|
||||||
if (!sub->open(parent, dname, O_READ)) {
|
if (!sub->open(parent, dname, O_READ)) {
|
||||||
if (!pFlag || !sub->mkdir(parent, dname)) {
|
if (!pFlag || !sub->mkdir(parent, dname)) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parent != start) parent->close();
|
if (parent != start) parent->close();
|
||||||
@ -460,7 +460,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
|
|||||||
sub = parent != &dir1 ? &dir1 : &dir2;
|
sub = parent != &dir1 ? &dir1 : &dir2;
|
||||||
}
|
}
|
||||||
return mkdir(parent, dname);
|
return mkdir(parent, dname);
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -469,24 +469,24 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|||||||
dir_t d;
|
dir_t d;
|
||||||
dir_t* p;
|
dir_t* p;
|
||||||
|
|
||||||
if (!parent->isDir()) goto fail;
|
if (!parent->isDir()) goto FAIL;
|
||||||
|
|
||||||
// create a normal file
|
// create a normal file
|
||||||
if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) goto fail;
|
if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) goto FAIL;
|
||||||
|
|
||||||
// convert file to directory
|
// convert file to directory
|
||||||
flags_ = O_READ;
|
flags_ = O_READ;
|
||||||
type_ = FAT_FILE_TYPE_SUBDIR;
|
type_ = FAT_FILE_TYPE_SUBDIR;
|
||||||
|
|
||||||
// allocate and zero first cluster
|
// allocate and zero first cluster
|
||||||
if (!addDirCluster())goto fail;
|
if (!addDirCluster())goto FAIL;
|
||||||
|
|
||||||
// force entry to SD
|
// force entry to SD
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
|
|
||||||
// cache entry - should already be in cache due to sync() call
|
// cache entry - should already be in cache due to sync() call
|
||||||
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
// change directory entry attribute
|
// change directory entry attribute
|
||||||
p->attributes = DIR_ATT_DIRECTORY;
|
p->attributes = DIR_ATT_DIRECTORY;
|
||||||
@ -498,7 +498,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|||||||
|
|
||||||
// cache block for '.' and '..'
|
// cache block for '.' and '..'
|
||||||
block = vol_->clusterStartBlock(firstCluster_);
|
block = vol_->clusterStartBlock(firstCluster_);
|
||||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail;
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
|
||||||
|
|
||||||
// copy '.' to block
|
// copy '.' to block
|
||||||
memcpy(&vol_->cache()->dir[0], &d, sizeof(d));
|
memcpy(&vol_->cache()->dir[0], &d, sizeof(d));
|
||||||
@ -510,7 +510,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|||||||
d.firstClusterHigh = 0;
|
d.firstClusterHigh = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
d.firstClusterLow = parent->firstCluster_ & 0XFFFF;
|
d.firstClusterLow = parent->firstCluster_ & 0xFFFF;
|
||||||
d.firstClusterHigh = parent->firstCluster_ >> 16;
|
d.firstClusterHigh = parent->firstCluster_ >> 16;
|
||||||
}
|
}
|
||||||
// copy '..' to block
|
// copy '..' to block
|
||||||
@ -518,7 +518,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|||||||
|
|
||||||
// write first block
|
// write first block
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -592,29 +592,29 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
|
|||||||
SdBaseFile* parent = dirFile;
|
SdBaseFile* parent = dirFile;
|
||||||
SdBaseFile* sub = &dir1;
|
SdBaseFile* sub = &dir1;
|
||||||
|
|
||||||
if (!dirFile) goto fail;
|
if (!dirFile) goto FAIL;
|
||||||
|
|
||||||
// error if already open
|
// error if already open
|
||||||
if (isOpen()) goto fail;
|
if (isOpen()) goto FAIL;
|
||||||
|
|
||||||
if (*path == '/') {
|
if (*path == '/') {
|
||||||
while (*path == '/') path++;
|
while (*path == '/') path++;
|
||||||
if (!dirFile->isRoot()) {
|
if (!dirFile->isRoot()) {
|
||||||
if (!dir2.openRoot(dirFile->vol_)) goto fail;
|
if (!dir2.openRoot(dirFile->vol_)) goto FAIL;
|
||||||
parent = &dir2;
|
parent = &dir2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!make83Name(path, dname, &path)) goto fail;
|
if (!make83Name(path, dname, &path)) goto FAIL;
|
||||||
while (*path == '/') path++;
|
while (*path == '/') path++;
|
||||||
if (!*path) break;
|
if (!*path) break;
|
||||||
if (!sub->open(parent, dname, O_READ)) goto fail;
|
if (!sub->open(parent, dname, O_READ)) goto FAIL;
|
||||||
if (parent != dirFile) parent->close();
|
if (parent != dirFile) parent->close();
|
||||||
parent = sub;
|
parent = sub;
|
||||||
sub = parent != &dir1 ? &dir1 : &dir2;
|
sub = parent != &dir1 ? &dir1 : &dir2;
|
||||||
}
|
}
|
||||||
return open(parent, dname, oflag);
|
return open(parent, dname, oflag);
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -634,7 +634,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
|||||||
while (dirFile->curPosition_ < dirFile->fileSize_) {
|
while (dirFile->curPosition_ < dirFile->fileSize_) {
|
||||||
index = 0XF & (dirFile->curPosition_ >> 5);
|
index = 0XF & (dirFile->curPosition_ >> 5);
|
||||||
p = dirFile->readDirCache();
|
p = dirFile->readDirCache();
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
|
if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
|
||||||
// remember first empty slot
|
// remember first empty slot
|
||||||
@ -653,21 +653,21 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
|||||||
}
|
}
|
||||||
if (fileFound) {
|
if (fileFound) {
|
||||||
// don't open existing file if O_EXCL
|
// don't open existing file if O_EXCL
|
||||||
if (oflag & O_EXCL) goto fail;
|
if (oflag & O_EXCL) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// don't create unless O_CREAT and O_WRITE
|
// don't create unless O_CREAT and O_WRITE
|
||||||
if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) goto fail;
|
if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) goto FAIL;
|
||||||
if (emptyFound) {
|
if (emptyFound) {
|
||||||
index = dirIndex_;
|
index = dirIndex_;
|
||||||
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto fail;
|
if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto FAIL;
|
||||||
|
|
||||||
// add and zero cluster for dirFile - first cluster is in cache for write
|
// add and zero cluster for dirFile - first cluster is in cache for write
|
||||||
if (!dirFile->addDirCluster()) goto fail;
|
if (!dirFile->addDirCluster()) goto FAIL;
|
||||||
|
|
||||||
// use first entry in cluster
|
// use first entry in cluster
|
||||||
p = dirFile->vol_->cache()->dir;
|
p = dirFile->vol_->cache()->dir;
|
||||||
@ -692,11 +692,11 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
|||||||
p->lastWriteTime = p->creationTime;
|
p->lastWriteTime = p->creationTime;
|
||||||
|
|
||||||
// write entry to SD
|
// write entry to SD
|
||||||
if (!dirFile->vol_->cacheFlush()) goto fail;
|
if (!dirFile->vol_->cacheFlush()) goto FAIL;
|
||||||
}
|
}
|
||||||
// open entry in cache
|
// open entry in cache
|
||||||
return openCachedEntry(index, oflag);
|
return openCachedEntry(index, oflag);
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -719,26 +719,26 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
|
|||||||
vol_ = dirFile->vol_;
|
vol_ = dirFile->vol_;
|
||||||
|
|
||||||
// error if already open
|
// error if already open
|
||||||
if (isOpen() || !dirFile) goto fail;
|
if (isOpen() || !dirFile) goto FAIL;
|
||||||
|
|
||||||
// don't open existing file if O_EXCL - user call error
|
// don't open existing file if O_EXCL - user call error
|
||||||
if (oflag & O_EXCL) goto fail;
|
if (oflag & O_EXCL) goto FAIL;
|
||||||
|
|
||||||
// seek to location of entry
|
// seek to location of entry
|
||||||
if (!dirFile->seekSet(32 * index)) goto fail;
|
if (!dirFile->seekSet(32 * index)) goto FAIL;
|
||||||
|
|
||||||
// read entry into cache
|
// read entry into cache
|
||||||
p = dirFile->readDirCache();
|
p = dirFile->readDirCache();
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
// error if empty slot or '.' or '..'
|
// error if empty slot or '.' or '..'
|
||||||
if (p->name[0] == DIR_NAME_FREE ||
|
if (p->name[0] == DIR_NAME_FREE ||
|
||||||
p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
|
p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// open cached entry
|
// open cached entry
|
||||||
return openCachedEntry(index & 0XF, oflag);
|
return openCachedEntry(index & 0XF, oflag);
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -749,7 +749,7 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
|||||||
|
|
||||||
// write or truncate is an error for a directory or read-only file
|
// write or truncate is an error for a directory or read-only file
|
||||||
if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
|
if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
|
||||||
if (oflag & (O_WRITE | O_TRUNC)) goto fail;
|
if (oflag & (O_WRITE | O_TRUNC)) goto FAIL;
|
||||||
}
|
}
|
||||||
// remember location of directory entry on SD
|
// remember location of directory entry on SD
|
||||||
dirBlock_ = vol_->cacheBlockNumber();
|
dirBlock_ = vol_->cacheBlockNumber();
|
||||||
@ -765,11 +765,11 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
|||||||
type_ = FAT_FILE_TYPE_NORMAL;
|
type_ = FAT_FILE_TYPE_NORMAL;
|
||||||
}
|
}
|
||||||
else if (DIR_IS_SUBDIR(p)) {
|
else if (DIR_IS_SUBDIR(p)) {
|
||||||
if (!vol_->chainSize(firstCluster_, &fileSize_)) goto fail;
|
if (!vol_->chainSize(firstCluster_, &fileSize_)) goto FAIL;
|
||||||
type_ = FAT_FILE_TYPE_SUBDIR;
|
type_ = FAT_FILE_TYPE_SUBDIR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// save open flags for read/write
|
// save open flags for read/write
|
||||||
flags_ = oflag & F_OFLAG;
|
flags_ = oflag & F_OFLAG;
|
||||||
@ -779,7 +779,7 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
|||||||
curPosition_ = 0;
|
curPosition_ = 0;
|
||||||
if ((oflag & O_TRUNC) && !truncate(0)) return false;
|
if ((oflag & O_TRUNC) && !truncate(0)) return false;
|
||||||
return oflag & O_AT_END ? seekEnd(0) : true;
|
return oflag & O_AT_END ? seekEnd(0) : true;
|
||||||
fail:
|
FAIL:
|
||||||
type_ = FAT_FILE_TYPE_CLOSED;
|
type_ = FAT_FILE_TYPE_CLOSED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -799,10 +799,10 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
|||||||
dir_t* p;
|
dir_t* p;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
|
|
||||||
if (!dirFile) goto fail;
|
if (!dirFile) goto FAIL;
|
||||||
|
|
||||||
// error if already open
|
// error if already open
|
||||||
if (isOpen()) goto fail;
|
if (isOpen()) goto FAIL;
|
||||||
|
|
||||||
vol_ = dirFile->vol_;
|
vol_ = dirFile->vol_;
|
||||||
|
|
||||||
@ -811,10 +811,10 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
|||||||
|
|
||||||
// read entry into cache
|
// read entry into cache
|
||||||
p = dirFile->readDirCache();
|
p = dirFile->readDirCache();
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
// done if last entry
|
// done if last entry
|
||||||
if (p->name[0] == DIR_NAME_FREE) goto fail;
|
if (p->name[0] == DIR_NAME_FREE) goto FAIL;
|
||||||
|
|
||||||
// skip empty slot or '.' or '..'
|
// skip empty slot or '.' or '..'
|
||||||
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
|
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
|
||||||
@ -825,7 +825,7 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
|||||||
return openCachedEntry(index, oflag);
|
return openCachedEntry(index, oflag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -844,14 +844,14 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
|||||||
uint32_t cluster;
|
uint32_t cluster;
|
||||||
uint32_t lbn;
|
uint32_t lbn;
|
||||||
// error if already open or dir is root or dir is not a directory
|
// error if already open or dir is root or dir is not a directory
|
||||||
if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) goto fail;
|
if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) goto FAIL;
|
||||||
vol_ = dir->vol_;
|
vol_ = dir->vol_;
|
||||||
// position to '..'
|
// position to '..'
|
||||||
if (!dir->seekSet(32)) goto fail;
|
if (!dir->seekSet(32)) goto FAIL;
|
||||||
// read '..' entry
|
// read '..' entry
|
||||||
if (dir->read(&entry, sizeof(entry)) != 32) goto fail;
|
if (dir->read(&entry, sizeof(entry)) != 32) goto FAIL;
|
||||||
// verify it is '..'
|
// verify it is '..'
|
||||||
if (entry.name[0] != '.' || entry.name[1] != '.') goto fail;
|
if (entry.name[0] != '.' || entry.name[1] != '.') goto FAIL;
|
||||||
// start cluster for '..'
|
// start cluster for '..'
|
||||||
cluster = entry.firstClusterLow;
|
cluster = entry.firstClusterLow;
|
||||||
cluster |= (uint32_t)entry.firstClusterHigh << 16;
|
cluster |= (uint32_t)entry.firstClusterHigh << 16;
|
||||||
@ -860,27 +860,27 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
|||||||
lbn = vol_->clusterStartBlock(cluster);
|
lbn = vol_->clusterStartBlock(cluster);
|
||||||
// first block of parent dir
|
// first block of parent dir
|
||||||
if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) {
|
if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
p = &vol_->cacheBuffer_.dir[1];
|
p = &vol_->cacheBuffer_.dir[1];
|
||||||
// verify name for '../..'
|
// verify name for '../..'
|
||||||
if (p->name[0] != '.' || p->name[1] != '.') goto fail;
|
if (p->name[0] != '.' || p->name[1] != '.') goto FAIL;
|
||||||
// '..' is pointer to first cluster of parent. open '../..' to find parent
|
// '..' is pointer to first cluster of parent. open '../..' to find parent
|
||||||
if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) {
|
if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) {
|
||||||
if (!file.openRoot(dir->volume())) goto fail;
|
if (!file.openRoot(dir->volume())) goto FAIL;
|
||||||
}
|
}
|
||||||
else if (!file.openCachedEntry(1, O_READ)) {
|
else if (!file.openCachedEntry(1, O_READ)) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// search for parent in '../..'
|
// search for parent in '../..'
|
||||||
do {
|
do {
|
||||||
if (file.readDir(&entry, NULL) != 32) goto fail;
|
if (file.readDir(&entry, NULL) != 32) goto FAIL;
|
||||||
c = entry.firstClusterLow;
|
c = entry.firstClusterLow;
|
||||||
c |= (uint32_t)entry.firstClusterHigh << 16;
|
c |= (uint32_t)entry.firstClusterHigh << 16;
|
||||||
} while (c != cluster);
|
} while (c != cluster);
|
||||||
// open parent
|
// open parent
|
||||||
return open(&file, file.curPosition() / 32 - 1, O_READ);
|
return open(&file, file.curPosition() / 32 - 1, O_READ);
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -895,7 +895,7 @@ fail:
|
|||||||
*/
|
*/
|
||||||
bool SdBaseFile::openRoot(SdVolume* vol) {
|
bool SdBaseFile::openRoot(SdVolume* vol) {
|
||||||
// error if file is already open
|
// error if file is already open
|
||||||
if (isOpen()) goto fail;
|
if (isOpen()) goto FAIL;
|
||||||
|
|
||||||
if (vol->fatType() == 16 || (FAT12_SUPPORT && vol->fatType() == 12)) {
|
if (vol->fatType() == 16 || (FAT12_SUPPORT && vol->fatType() == 12)) {
|
||||||
type_ = FAT_FILE_TYPE_ROOT_FIXED;
|
type_ = FAT_FILE_TYPE_ROOT_FIXED;
|
||||||
@ -905,7 +905,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
|
|||||||
else if (vol->fatType() == 32) {
|
else if (vol->fatType() == 32) {
|
||||||
type_ = FAT_FILE_TYPE_ROOT32;
|
type_ = FAT_FILE_TYPE_ROOT32;
|
||||||
firstCluster_ = vol->rootDirStart();
|
firstCluster_ = vol->rootDirStart();
|
||||||
if (!vol->chainSize(firstCluster_, &fileSize_)) goto fail;
|
if (!vol->chainSize(firstCluster_, &fileSize_)) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// volume is not initialized, invalid, or FAT12 without support
|
// volume is not initialized, invalid, or FAT12 without support
|
||||||
@ -923,7 +923,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
|
|||||||
dirBlock_ = 0;
|
dirBlock_ = 0;
|
||||||
dirIndex_ = 0;
|
dirIndex_ = 0;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1055,7 +1055,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|||||||
uint32_t block; // raw device block number
|
uint32_t block; // raw device block number
|
||||||
|
|
||||||
// error if not open or write only
|
// error if not open or write only
|
||||||
if (!isOpen() || !(flags_ & O_READ)) goto fail;
|
if (!isOpen() || !(flags_ & O_READ)) goto FAIL;
|
||||||
|
|
||||||
// max bytes left in file
|
// max bytes left in file
|
||||||
NOMORE(nbyte, fileSize_ - curPosition_);
|
NOMORE(nbyte, fileSize_ - curPosition_);
|
||||||
@ -1063,7 +1063,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|||||||
// amount left to read
|
// amount left to read
|
||||||
toRead = nbyte;
|
toRead = nbyte;
|
||||||
while (toRead > 0) {
|
while (toRead > 0) {
|
||||||
offset = curPosition_ & 0X1FF; // offset in block
|
offset = curPosition_ & 0x1FF; // offset in block
|
||||||
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
||||||
block = vol_->rootDirStart() + (curPosition_ >> 9);
|
block = vol_->rootDirStart() + (curPosition_ >> 9);
|
||||||
}
|
}
|
||||||
@ -1077,7 +1077,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// get next cluster from FAT
|
// get next cluster from FAT
|
||||||
if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail;
|
if (!vol_->fatGet(curCluster_, &curCluster_)) goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
|
block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
|
||||||
@ -1089,11 +1089,11 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|||||||
|
|
||||||
// no buffering needed if n == 512
|
// no buffering needed if n == 512
|
||||||
if (n == 512 && block != vol_->cacheBlockNumber()) {
|
if (n == 512 && block != vol_->cacheBlockNumber()) {
|
||||||
if (!vol_->readBlock(block, dst)) goto fail;
|
if (!vol_->readBlock(block, dst)) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// read block to cache and copy data to caller
|
// read block to cache and copy data to caller
|
||||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto fail;
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto FAIL;
|
||||||
uint8_t* src = vol_->cache()->data + offset;
|
uint8_t* src = vol_->cache()->data + offset;
|
||||||
memcpy(dst, src, n);
|
memcpy(dst, src, n);
|
||||||
}
|
}
|
||||||
@ -1102,7 +1102,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|||||||
toRead -= n;
|
toRead -= n;
|
||||||
}
|
}
|
||||||
return nbyte;
|
return nbyte;
|
||||||
fail:
|
FAIL:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1120,7 +1120,7 @@ fail:
|
|||||||
int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
|
int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
|
||||||
int16_t n;
|
int16_t n;
|
||||||
// if not a directory file or miss-positioned return an error
|
// if not a directory file or miss-positioned return an error
|
||||||
if (!isDir() || (0X1F & curPosition_)) return -1;
|
if (!isDir() || (0x1F & curPosition_)) return -1;
|
||||||
|
|
||||||
//If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
|
//If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
|
||||||
if (longFilename != NULL) longFilename[0] = '\0';
|
if (longFilename != NULL) longFilename[0] = '\0';
|
||||||
@ -1161,20 +1161,20 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
|
|||||||
dir_t* SdBaseFile::readDirCache() {
|
dir_t* SdBaseFile::readDirCache() {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
// error if not directory
|
// error if not directory
|
||||||
if (!isDir()) goto fail;
|
if (!isDir()) goto FAIL;
|
||||||
|
|
||||||
// index of entry in cache
|
// index of entry in cache
|
||||||
i = (curPosition_ >> 5) & 0XF;
|
i = (curPosition_ >> 5) & 0XF;
|
||||||
|
|
||||||
// use read to locate and cache block
|
// use read to locate and cache block
|
||||||
if (read() < 0) goto fail;
|
if (read() < 0) goto FAIL;
|
||||||
|
|
||||||
// advance to next entry
|
// advance to next entry
|
||||||
curPosition_ += 31;
|
curPosition_ += 31;
|
||||||
|
|
||||||
// return pointer to entry
|
// return pointer to entry
|
||||||
return vol_->cache()->dir + i;
|
return vol_->cache()->dir + i;
|
||||||
fail:
|
FAIL:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1194,11 +1194,11 @@ fail:
|
|||||||
bool SdBaseFile::remove() {
|
bool SdBaseFile::remove() {
|
||||||
dir_t* d;
|
dir_t* d;
|
||||||
// free any clusters - will fail if read-only or directory
|
// free any clusters - will fail if read-only or directory
|
||||||
if (!truncate(0)) goto fail;
|
if (!truncate(0)) goto FAIL;
|
||||||
|
|
||||||
// cache directory entry
|
// cache directory entry
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
|
|
||||||
// mark entry deleted
|
// mark entry deleted
|
||||||
d->name[0] = DIR_NAME_DELETED;
|
d->name[0] = DIR_NAME_DELETED;
|
||||||
@ -1209,7 +1209,7 @@ bool SdBaseFile::remove() {
|
|||||||
// write entry to SD
|
// write entry to SD
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1232,9 +1232,9 @@ fail:
|
|||||||
*/
|
*/
|
||||||
bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
|
bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
|
||||||
SdBaseFile file;
|
SdBaseFile file;
|
||||||
if (!file.open(dirFile, path, O_WRITE)) goto fail;
|
if (!file.open(dirFile, path, O_WRITE)) goto FAIL;
|
||||||
return file.remove();
|
return file.remove();
|
||||||
fail:
|
FAIL:
|
||||||
// can't set iostate - static function
|
// can't set iostate - static function
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1256,15 +1256,15 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
|
|||||||
dir_t* d;
|
dir_t* d;
|
||||||
|
|
||||||
// must be an open file or subdirectory
|
// must be an open file or subdirectory
|
||||||
if (!(isFile() || isSubDir())) goto fail;
|
if (!(isFile() || isSubDir())) goto FAIL;
|
||||||
|
|
||||||
// can't move file
|
// can't move file
|
||||||
if (vol_ != dirFile->vol_) goto fail;
|
if (vol_ != dirFile->vol_) goto FAIL;
|
||||||
|
|
||||||
// sync() and cache directory entry
|
// sync() and cache directory entry
|
||||||
sync();
|
sync();
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
|
|
||||||
// save directory entry
|
// save directory entry
|
||||||
memcpy(&entry, d, sizeof(entry));
|
memcpy(&entry, d, sizeof(entry));
|
||||||
@ -1295,7 +1295,7 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
|
|||||||
|
|
||||||
// cache new directory entry
|
// cache new directory entry
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
|
|
||||||
// copy all but name field to new directory entry
|
// copy all but name field to new directory entry
|
||||||
memcpy(&d->attributes, &entry.attributes, sizeof(entry) - sizeof(d->name));
|
memcpy(&d->attributes, &entry.attributes, sizeof(entry) - sizeof(d->name));
|
||||||
@ -1304,27 +1304,27 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
|
|||||||
if (dirCluster) {
|
if (dirCluster) {
|
||||||
// get new dot dot
|
// get new dot dot
|
||||||
uint32_t block = vol_->clusterStartBlock(dirCluster);
|
uint32_t block = vol_->clusterStartBlock(dirCluster);
|
||||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto fail;
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto FAIL;
|
||||||
memcpy(&entry, &vol_->cache()->dir[1], sizeof(entry));
|
memcpy(&entry, &vol_->cache()->dir[1], sizeof(entry));
|
||||||
|
|
||||||
// free unused cluster
|
// free unused cluster
|
||||||
if (!vol_->freeChain(dirCluster)) goto fail;
|
if (!vol_->freeChain(dirCluster)) goto FAIL;
|
||||||
|
|
||||||
// store new dot dot
|
// store new dot dot
|
||||||
block = vol_->clusterStartBlock(firstCluster_);
|
block = vol_->clusterStartBlock(firstCluster_);
|
||||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail;
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
|
||||||
memcpy(&vol_->cache()->dir[1], &entry, sizeof(entry));
|
memcpy(&vol_->cache()->dir[1], &entry, sizeof(entry));
|
||||||
}
|
}
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
|
|
||||||
restore:
|
restore:
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
// restore entry
|
// restore entry
|
||||||
d->name[0] = entry.name[0];
|
d->name[0] = entry.name[0];
|
||||||
vol_->cacheFlush();
|
vol_->cacheFlush();
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1345,26 +1345,26 @@ fail:
|
|||||||
*/
|
*/
|
||||||
bool SdBaseFile::rmdir() {
|
bool SdBaseFile::rmdir() {
|
||||||
// must be open subdirectory
|
// must be open subdirectory
|
||||||
if (!isSubDir()) goto fail;
|
if (!isSubDir()) goto FAIL;
|
||||||
|
|
||||||
rewind();
|
rewind();
|
||||||
|
|
||||||
// make sure directory is empty
|
// make sure directory is empty
|
||||||
while (curPosition_ < fileSize_) {
|
while (curPosition_ < fileSize_) {
|
||||||
dir_t* p = readDirCache();
|
dir_t* p = readDirCache();
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
// done if past last used entry
|
// done if past last used entry
|
||||||
if (p->name[0] == DIR_NAME_FREE) break;
|
if (p->name[0] == DIR_NAME_FREE) break;
|
||||||
// skip empty slot, '.' or '..'
|
// skip empty slot, '.' or '..'
|
||||||
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
|
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
|
||||||
// error not empty
|
// error not empty
|
||||||
if (DIR_IS_FILE_OR_SUBDIR(p)) goto fail;
|
if (DIR_IS_FILE_OR_SUBDIR(p)) goto FAIL;
|
||||||
}
|
}
|
||||||
// convert empty directory to normal file for remove
|
// convert empty directory to normal file for remove
|
||||||
type_ = FAT_FILE_TYPE_NORMAL;
|
type_ = FAT_FILE_TYPE_NORMAL;
|
||||||
flags_ |= O_WRITE;
|
flags_ |= O_WRITE;
|
||||||
return remove();
|
return remove();
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1392,7 +1392,7 @@ bool SdBaseFile::rmRfStar() {
|
|||||||
index = curPosition_ / 32;
|
index = curPosition_ / 32;
|
||||||
|
|
||||||
dir_t* p = readDirCache();
|
dir_t* p = readDirCache();
|
||||||
if (!p) goto fail;
|
if (!p) goto FAIL;
|
||||||
|
|
||||||
// done if past last entry
|
// done if past last entry
|
||||||
if (p->name[0] == DIR_NAME_FREE) break;
|
if (p->name[0] == DIR_NAME_FREE) break;
|
||||||
@ -1403,27 +1403,27 @@ bool SdBaseFile::rmRfStar() {
|
|||||||
// skip if part of long file name or volume label in root
|
// skip if part of long file name or volume label in root
|
||||||
if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
|
if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
|
||||||
|
|
||||||
if (!f.open(this, index, O_READ)) goto fail;
|
if (!f.open(this, index, O_READ)) goto FAIL;
|
||||||
if (f.isSubDir()) {
|
if (f.isSubDir()) {
|
||||||
// recursively delete
|
// recursively delete
|
||||||
if (!f.rmRfStar()) goto fail;
|
if (!f.rmRfStar()) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ignore read-only
|
// ignore read-only
|
||||||
f.flags_ |= O_WRITE;
|
f.flags_ |= O_WRITE;
|
||||||
if (!f.remove()) goto fail;
|
if (!f.remove()) goto FAIL;
|
||||||
}
|
}
|
||||||
// position to next entry if required
|
// position to next entry if required
|
||||||
if (curPosition_ != (32 * (index + 1))) {
|
if (curPosition_ != (32 * (index + 1))) {
|
||||||
if (!seekSet(32 * (index + 1))) goto fail;
|
if (!seekSet(32 * (index + 1))) goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// don't try to delete root
|
// don't try to delete root
|
||||||
if (!isRoot()) {
|
if (!isRoot()) {
|
||||||
if (!rmdir()) goto fail;
|
if (!rmdir()) goto FAIL;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1451,7 +1451,7 @@ bool SdBaseFile::seekSet(uint32_t pos) {
|
|||||||
uint32_t nCur;
|
uint32_t nCur;
|
||||||
uint32_t nNew;
|
uint32_t nNew;
|
||||||
// error if file not open or seek past end of file
|
// error if file not open or seek past end of file
|
||||||
if (!isOpen() || pos > fileSize_) goto fail;
|
if (!isOpen() || pos > fileSize_) goto FAIL;
|
||||||
|
|
||||||
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
||||||
curPosition_ = pos;
|
curPosition_ = pos;
|
||||||
@ -1476,14 +1476,14 @@ bool SdBaseFile::seekSet(uint32_t pos) {
|
|||||||
nNew -= nCur;
|
nNew -= nCur;
|
||||||
}
|
}
|
||||||
while (nNew--) {
|
while (nNew--) {
|
||||||
if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail;
|
if (!vol_->fatGet(curCluster_, &curCluster_)) goto FAIL;
|
||||||
}
|
}
|
||||||
curPosition_ = pos;
|
curPosition_ = pos;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1502,18 +1502,18 @@ void SdBaseFile::setpos(filepos_t* pos) {
|
|||||||
*/
|
*/
|
||||||
bool SdBaseFile::sync() {
|
bool SdBaseFile::sync() {
|
||||||
// only allow open files and directories
|
// only allow open files and directories
|
||||||
if (!isOpen()) goto fail;
|
if (!isOpen()) goto FAIL;
|
||||||
|
|
||||||
if (flags_ & F_FILE_DIR_DIRTY) {
|
if (flags_ & F_FILE_DIR_DIRTY) {
|
||||||
dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
// check for deleted by another open file object
|
// check for deleted by another open file object
|
||||||
if (!d || d->name[0] == DIR_NAME_DELETED) goto fail;
|
if (!d || d->name[0] == DIR_NAME_DELETED) goto FAIL;
|
||||||
|
|
||||||
// do not set filesize for dir files
|
// do not set filesize for dir files
|
||||||
if (!isDir()) d->fileSize = fileSize_;
|
if (!isDir()) d->fileSize = fileSize_;
|
||||||
|
|
||||||
// update first cluster fields
|
// update first cluster fields
|
||||||
d->firstClusterLow = firstCluster_ & 0XFFFF;
|
d->firstClusterLow = firstCluster_ & 0xFFFF;
|
||||||
d->firstClusterHigh = firstCluster_ >> 16;
|
d->firstClusterHigh = firstCluster_ >> 16;
|
||||||
|
|
||||||
// set modify time if user supplied a callback date/time function
|
// set modify time if user supplied a callback date/time function
|
||||||
@ -1526,7 +1526,7 @@ bool SdBaseFile::sync() {
|
|||||||
}
|
}
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
writeError = true;
|
writeError = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1547,13 +1547,13 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
|
|||||||
dir_t dir;
|
dir_t dir;
|
||||||
|
|
||||||
// get timestamps
|
// get timestamps
|
||||||
if (!file->dirEntry(&dir)) goto fail;
|
if (!file->dirEntry(&dir)) goto FAIL;
|
||||||
|
|
||||||
// update directory fields
|
// update directory fields
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
|
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
|
|
||||||
// copy timestamps
|
// copy timestamps
|
||||||
d->lastAccessDate = dir.lastAccessDate;
|
d->lastAccessDate = dir.lastAccessDate;
|
||||||
@ -1566,7 +1566,7 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
|
|||||||
// write back entry
|
// write back entry
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1619,13 +1619,13 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
|||||||
|| hour > 23
|
|| hour > 23
|
||||||
|| minute > 59
|
|| minute > 59
|
||||||
|| second > 59) {
|
|| second > 59) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// update directory entry
|
// update directory entry
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
|
|
||||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||||
if (!d) goto fail;
|
if (!d) goto FAIL;
|
||||||
|
|
||||||
dirDate = FAT_DATE(year, month, day);
|
dirDate = FAT_DATE(year, month, day);
|
||||||
dirTime = FAT_TIME(hour, minute, second);
|
dirTime = FAT_TIME(hour, minute, second);
|
||||||
@ -1643,7 +1643,7 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
|||||||
d->lastWriteTime = dirTime;
|
d->lastWriteTime = dirTime;
|
||||||
}
|
}
|
||||||
return vol_->cacheFlush();
|
return vol_->cacheFlush();
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1661,10 +1661,10 @@ fail:
|
|||||||
bool SdBaseFile::truncate(uint32_t length) {
|
bool SdBaseFile::truncate(uint32_t length) {
|
||||||
uint32_t newPos;
|
uint32_t newPos;
|
||||||
// error if not a normal file or read-only
|
// error if not a normal file or read-only
|
||||||
if (!isFile() || !(flags_ & O_WRITE)) goto fail;
|
if (!isFile() || !(flags_ & O_WRITE)) goto FAIL;
|
||||||
|
|
||||||
// error if length is greater than current size
|
// error if length is greater than current size
|
||||||
if (length > fileSize_) goto fail;
|
if (length > fileSize_) goto FAIL;
|
||||||
|
|
||||||
// fileSize and length are zero - nothing to do
|
// fileSize and length are zero - nothing to do
|
||||||
if (fileSize_ == 0) return true;
|
if (fileSize_ == 0) return true;
|
||||||
@ -1673,23 +1673,23 @@ bool SdBaseFile::truncate(uint32_t length) {
|
|||||||
newPos = curPosition_ > length ? length : curPosition_;
|
newPos = curPosition_ > length ? length : curPosition_;
|
||||||
|
|
||||||
// position to last cluster in truncated file
|
// position to last cluster in truncated file
|
||||||
if (!seekSet(length)) goto fail;
|
if (!seekSet(length)) goto FAIL;
|
||||||
|
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
// free all clusters
|
// free all clusters
|
||||||
if (!vol_->freeChain(firstCluster_)) goto fail;
|
if (!vol_->freeChain(firstCluster_)) goto FAIL;
|
||||||
firstCluster_ = 0;
|
firstCluster_ = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t toFree;
|
uint32_t toFree;
|
||||||
if (!vol_->fatGet(curCluster_, &toFree)) goto fail;
|
if (!vol_->fatGet(curCluster_, &toFree)) goto FAIL;
|
||||||
|
|
||||||
if (!vol_->isEOC(toFree)) {
|
if (!vol_->isEOC(toFree)) {
|
||||||
// free extra clusters
|
// free extra clusters
|
||||||
if (!vol_->freeChain(toFree)) goto fail;
|
if (!vol_->freeChain(toFree)) goto FAIL;
|
||||||
|
|
||||||
// current cluster is end of chain
|
// current cluster is end of chain
|
||||||
if (!vol_->fatPutEOC(curCluster_)) goto fail;
|
if (!vol_->fatPutEOC(curCluster_)) goto FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileSize_ = length;
|
fileSize_ = length;
|
||||||
@ -1697,12 +1697,12 @@ bool SdBaseFile::truncate(uint32_t length) {
|
|||||||
// need to update directory entry
|
// need to update directory entry
|
||||||
flags_ |= F_FILE_DIR_DIRTY;
|
flags_ |= F_FILE_DIR_DIRTY;
|
||||||
|
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
|
|
||||||
// set file to correct position
|
// set file to correct position
|
||||||
return seekSet(newPos);
|
return seekSet(newPos);
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1729,22 +1729,22 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
|||||||
uint16_t nToWrite = nbyte;
|
uint16_t nToWrite = nbyte;
|
||||||
|
|
||||||
// error if not a normal file or is read-only
|
// error if not a normal file or is read-only
|
||||||
if (!isFile() || !(flags_ & O_WRITE)) goto fail;
|
if (!isFile() || !(flags_ & O_WRITE)) goto FAIL;
|
||||||
|
|
||||||
// seek to end of file if append flag
|
// seek to end of file if append flag
|
||||||
if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
|
if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
|
||||||
if (!seekEnd()) goto fail;
|
if (!seekEnd()) goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nToWrite > 0) {
|
while (nToWrite > 0) {
|
||||||
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
|
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
|
||||||
uint16_t blockOffset = curPosition_ & 0X1FF;
|
uint16_t blockOffset = curPosition_ & 0x1FF;
|
||||||
if (blockOfCluster == 0 && blockOffset == 0) {
|
if (blockOfCluster == 0 && blockOffset == 0) {
|
||||||
// start of new cluster
|
// start of new cluster
|
||||||
if (curCluster_ == 0) {
|
if (curCluster_ == 0) {
|
||||||
if (firstCluster_ == 0) {
|
if (firstCluster_ == 0) {
|
||||||
// allocate first cluster of file
|
// allocate first cluster of file
|
||||||
if (!addCluster()) goto fail;
|
if (!addCluster()) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
curCluster_ = firstCluster_;
|
curCluster_ = firstCluster_;
|
||||||
@ -1752,10 +1752,10 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t next;
|
uint32_t next;
|
||||||
if (!vol_->fatGet(curCluster_, &next)) goto fail;
|
if (!vol_->fatGet(curCluster_, &next)) goto FAIL;
|
||||||
if (vol_->isEOC(next)) {
|
if (vol_->isEOC(next)) {
|
||||||
// add cluster if at end of chain
|
// add cluster if at end of chain
|
||||||
if (!addCluster()) goto fail;
|
if (!addCluster()) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
curCluster_ = next;
|
curCluster_ = next;
|
||||||
@ -1774,20 +1774,20 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
|||||||
// full block - don't need to use cache
|
// full block - don't need to use cache
|
||||||
if (vol_->cacheBlockNumber() == block) {
|
if (vol_->cacheBlockNumber() == block) {
|
||||||
// invalidate cache if block is in cache
|
// invalidate cache if block is in cache
|
||||||
vol_->cacheSetBlockNumber(0XFFFFFFFF, false);
|
vol_->cacheSetBlockNumber(0xFFFFFFFF, false);
|
||||||
}
|
}
|
||||||
if (!vol_->writeBlock(block, src)) goto fail;
|
if (!vol_->writeBlock(block, src)) goto FAIL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (blockOffset == 0 && curPosition_ >= fileSize_) {
|
if (blockOffset == 0 && curPosition_ >= fileSize_) {
|
||||||
// start of new block don't need to read into cache
|
// start of new block don't need to read into cache
|
||||||
if (!vol_->cacheFlush()) goto fail;
|
if (!vol_->cacheFlush()) goto FAIL;
|
||||||
// set cache dirty and SD address of block
|
// set cache dirty and SD address of block
|
||||||
vol_->cacheSetBlockNumber(block, true);
|
vol_->cacheSetBlockNumber(block, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// rewrite part of block
|
// rewrite part of block
|
||||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail;
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
|
||||||
}
|
}
|
||||||
uint8_t* dst = vol_->cache()->data + blockOffset;
|
uint8_t* dst = vol_->cache()->data + blockOffset;
|
||||||
memcpy(dst, src, n);
|
memcpy(dst, src, n);
|
||||||
@ -1807,11 +1807,11 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags_ & O_SYNC) {
|
if (flags_ & O_SYNC) {
|
||||||
if (!sync()) goto fail;
|
if (!sync()) goto FAIL;
|
||||||
}
|
}
|
||||||
return nbyte;
|
return nbyte;
|
||||||
|
|
||||||
fail:
|
FAIL:
|
||||||
// return for write error
|
// return for write error
|
||||||
writeError = true;
|
writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -54,11 +54,11 @@ struct filepos_t {
|
|||||||
|
|
||||||
// use the gnu style oflag in open()
|
// use the gnu style oflag in open()
|
||||||
/** open() oflag for reading */
|
/** open() oflag for reading */
|
||||||
uint8_t const O_READ = 0X01;
|
uint8_t const O_READ = 0x01;
|
||||||
/** open() oflag - same as O_IN */
|
/** open() oflag - same as O_IN */
|
||||||
uint8_t const O_RDONLY = O_READ;
|
uint8_t const O_RDONLY = O_READ;
|
||||||
/** open() oflag for write */
|
/** open() oflag for write */
|
||||||
uint8_t const O_WRITE = 0X02;
|
uint8_t const O_WRITE = 0x02;
|
||||||
/** open() oflag - same as O_WRITE */
|
/** open() oflag - same as O_WRITE */
|
||||||
uint8_t const O_WRONLY = O_WRITE;
|
uint8_t const O_WRONLY = O_WRITE;
|
||||||
/** open() oflag for reading and writing */
|
/** open() oflag for reading and writing */
|
||||||
@ -66,17 +66,17 @@ uint8_t const O_RDWR = (O_READ | O_WRITE);
|
|||||||
/** open() oflag mask for access modes */
|
/** open() oflag mask for access modes */
|
||||||
uint8_t const O_ACCMODE = (O_READ | O_WRITE);
|
uint8_t const O_ACCMODE = (O_READ | O_WRITE);
|
||||||
/** The file offset shall be set to the end of the file prior to each write. */
|
/** The file offset shall be set to the end of the file prior to each write. */
|
||||||
uint8_t const O_APPEND = 0X04;
|
uint8_t const O_APPEND = 0x04;
|
||||||
/** synchronous writes - call sync() after each write */
|
/** synchronous writes - call sync() after each write */
|
||||||
uint8_t const O_SYNC = 0X08;
|
uint8_t const O_SYNC = 0x08;
|
||||||
/** truncate the file to zero length */
|
/** truncate the file to zero length */
|
||||||
uint8_t const O_TRUNC = 0X10;
|
uint8_t const O_TRUNC = 0x10;
|
||||||
/** set the initial position at the end of the file */
|
/** set the initial position at the end of the file */
|
||||||
uint8_t const O_AT_END = 0X20;
|
uint8_t const O_AT_END = 0x20;
|
||||||
/** create the file if nonexistent */
|
/** create the file if nonexistent */
|
||||||
uint8_t const O_CREAT = 0X40;
|
uint8_t const O_CREAT = 0x40;
|
||||||
/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
|
/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
|
||||||
uint8_t const O_EXCL = 0X80;
|
uint8_t const O_EXCL = 0x80;
|
||||||
|
|
||||||
// SdBaseFile class static and const definitions
|
// SdBaseFile class static and const definitions
|
||||||
// flags for ls()
|
// flags for ls()
|
||||||
@ -141,7 +141,7 @@ static inline uint8_t FAT_MONTH(uint16_t fatDate) {
|
|||||||
* \return Extracted day [1,31]
|
* \return Extracted day [1,31]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
||||||
return fatDate & 0X1F;
|
return fatDate & 0x1F;
|
||||||
}
|
}
|
||||||
/** time field for FAT directory entry
|
/** time field for FAT directory entry
|
||||||
* \param[in] hour [0,23]
|
* \param[in] hour [0,23]
|
||||||
@ -167,7 +167,7 @@ static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
|||||||
* \return Extracted minute [0,59]
|
* \return Extracted minute [0,59]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||||
return (fatTime >> 5) & 0X3F;
|
return (fatTime >> 5) & 0x3F;
|
||||||
}
|
}
|
||||||
/** second part of FAT directory time field
|
/** second part of FAT directory time field
|
||||||
* Note second/2 is stored in packed time.
|
* Note second/2 is stored in packed time.
|
||||||
@ -177,7 +177,7 @@ static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
|||||||
* \return Extracted second [0,58]
|
* \return Extracted second [0,58]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
||||||
return 2 * (fatTime & 0X1F);
|
return 2 * (fatTime & 0x1F);
|
||||||
}
|
}
|
||||||
/** Default date for file timestamps is 1 Jan 2000 */
|
/** Default date for file timestamps is 1 Jan 2000 */
|
||||||
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
||||||
@ -338,10 +338,10 @@ class SdBaseFile {
|
|||||||
// data time callback function
|
// data time callback function
|
||||||
static void (*dateTime_)(uint16_t* date, uint16_t* time);
|
static void (*dateTime_)(uint16_t* date, uint16_t* time);
|
||||||
// bits defined in flags_
|
// bits defined in flags_
|
||||||
// should be 0X0F
|
// should be 0x0F
|
||||||
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
|
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
|
||||||
// sync of directory entry required
|
// sync of directory entry required
|
||||||
static uint8_t const F_FILE_DIR_DIRTY = 0X80;
|
static uint8_t const F_FILE_DIR_DIRTY = 0x80;
|
||||||
|
|
||||||
// private data
|
// private data
|
||||||
uint8_t flags_; // See above for definition of flags_ bits
|
uint8_t flags_; // See above for definition of flags_ bits
|
||||||
|
@ -43,11 +43,11 @@
|
|||||||
*/
|
*/
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Value for byte 510 of boot block or MBR */
|
/** Value for byte 510 of boot block or MBR */
|
||||||
uint8_t const BOOTSIG0 = 0X55;
|
uint8_t const BOOTSIG0 = 0x55;
|
||||||
/** Value for byte 511 of boot block or MBR */
|
/** Value for byte 511 of boot block or MBR */
|
||||||
uint8_t const BOOTSIG1 = 0XAA;
|
uint8_t const BOOTSIG1 = 0xAA;
|
||||||
/** Value for bootSignature field int FAT/FAT32 boot sector */
|
/** Value for bootSignature field int FAT/FAT32 boot sector */
|
||||||
uint8_t const EXTENDED_BOOT_SIG = 0X29;
|
uint8_t const EXTENDED_BOOT_SIG = 0x29;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* \struct partitionTable
|
* \struct partitionTable
|
||||||
@ -59,8 +59,8 @@ uint8_t const EXTENDED_BOOT_SIG = 0X29;
|
|||||||
struct partitionTable {
|
struct partitionTable {
|
||||||
/**
|
/**
|
||||||
* Boot Indicator . Indicates whether the volume is the active
|
* Boot Indicator . Indicates whether the volume is the active
|
||||||
* partition. Legal values include: 0X00. Do not use for booting.
|
* partition. Legal values include: 0x00. Do not use for booting.
|
||||||
* 0X80 Active partition.
|
* 0x80 Active partition.
|
||||||
*/
|
*/
|
||||||
uint8_t boot;
|
uint8_t boot;
|
||||||
/**
|
/**
|
||||||
@ -126,9 +126,9 @@ struct masterBootRecord {
|
|||||||
uint16_t usuallyZero;
|
uint16_t usuallyZero;
|
||||||
/** Partition tables. */
|
/** Partition tables. */
|
||||||
part_t part[4];
|
part_t part[4];
|
||||||
/** First MBR signature byte. Must be 0X55 */
|
/** First MBR signature byte. Must be 0x55 */
|
||||||
uint8_t mbrSig0;
|
uint8_t mbrSig0;
|
||||||
/** Second MBR signature byte. Must be 0XAA */
|
/** Second MBR signature byte. Must be 0xAA */
|
||||||
uint8_t mbrSig1;
|
uint8_t mbrSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for masterBootRecord */
|
/** Type name for masterBootRecord */
|
||||||
@ -234,7 +234,7 @@ struct fat_boot {
|
|||||||
uint8_t driveNumber;
|
uint8_t driveNumber;
|
||||||
/** used by Windows NT - should be zero for FAT */
|
/** used by Windows NT - should be zero for FAT */
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
/** 0X29 if next three fields are valid */
|
/** 0x29 if next three fields are valid */
|
||||||
uint8_t bootSignature;
|
uint8_t bootSignature;
|
||||||
/**
|
/**
|
||||||
* A random serial number created when formatting a disk,
|
* A random serial number created when formatting a disk,
|
||||||
@ -254,9 +254,9 @@ struct fat_boot {
|
|||||||
char fileSystemType[8];
|
char fileSystemType[8];
|
||||||
/** X86 boot code */
|
/** X86 boot code */
|
||||||
uint8_t bootCode[448];
|
uint8_t bootCode[448];
|
||||||
/** must be 0X55 */
|
/** must be 0x55 */
|
||||||
uint8_t bootSectorSig0;
|
uint8_t bootSectorSig0;
|
||||||
/** must be 0XAA */
|
/** must be 0xAA */
|
||||||
uint8_t bootSectorSig1;
|
uint8_t bootSectorSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT Boot Sector */
|
/** Type name for FAT Boot Sector */
|
||||||
@ -389,7 +389,7 @@ struct fat32_boot {
|
|||||||
uint8_t driveNumber;
|
uint8_t driveNumber;
|
||||||
/** used by Windows NT - should be zero for FAT */
|
/** used by Windows NT - should be zero for FAT */
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
/** 0X29 if next three fields are valid */
|
/** 0x29 if next three fields are valid */
|
||||||
uint8_t bootSignature;
|
uint8_t bootSignature;
|
||||||
/**
|
/**
|
||||||
* A random serial number created when formatting a disk,
|
* A random serial number created when formatting a disk,
|
||||||
@ -408,9 +408,9 @@ struct fat32_boot {
|
|||||||
char fileSystemType[8];
|
char fileSystemType[8];
|
||||||
/** X86 boot code */
|
/** X86 boot code */
|
||||||
uint8_t bootCode[420];
|
uint8_t bootCode[420];
|
||||||
/** must be 0X55 */
|
/** must be 0x55 */
|
||||||
uint8_t bootSectorSig0;
|
uint8_t bootSectorSig0;
|
||||||
/** must be 0XAA */
|
/** must be 0xAA */
|
||||||
uint8_t bootSectorSig1;
|
uint8_t bootSectorSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT32 Boot Sector */
|
/** Type name for FAT32 Boot Sector */
|
||||||
@ -427,11 +427,11 @@ uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct fat32_fsinfo {
|
struct fat32_fsinfo {
|
||||||
/** must be 0X52, 0X52, 0X61, 0X41 */
|
/** must be 0x52, 0x52, 0x61, 0x41 */
|
||||||
uint32_t leadSignature;
|
uint32_t leadSignature;
|
||||||
/** must be zero */
|
/** must be zero */
|
||||||
uint8_t reserved1[480];
|
uint8_t reserved1[480];
|
||||||
/** must be 0X72, 0X72, 0X41, 0X61 */
|
/** must be 0x72, 0x72, 0x41, 0x61 */
|
||||||
uint32_t structSignature;
|
uint32_t structSignature;
|
||||||
/**
|
/**
|
||||||
* Contains the last known free cluster count on the volume.
|
* Contains the last known free cluster count on the volume.
|
||||||
@ -450,7 +450,7 @@ struct fat32_fsinfo {
|
|||||||
uint32_t nextFree;
|
uint32_t nextFree;
|
||||||
/** must be zero */
|
/** must be zero */
|
||||||
uint8_t reserved2[12];
|
uint8_t reserved2[12];
|
||||||
/** must be 0X00, 0X00, 0X55, 0XAA */
|
/** must be 0x00, 0x00, 0x55, 0xAA */
|
||||||
uint8_t tailSignature[4];
|
uint8_t tailSignature[4];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT32 FSINFO Sector */
|
/** Type name for FAT32 FSINFO Sector */
|
||||||
@ -458,19 +458,19 @@ typedef struct fat32_fsinfo fat32_fsinfo_t;
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// End Of Chain values for FAT entries
|
// End Of Chain values for FAT entries
|
||||||
/** FAT12 end of chain value used by Microsoft. */
|
/** FAT12 end of chain value used by Microsoft. */
|
||||||
uint16_t const FAT12EOC = 0XFFF;
|
uint16_t const FAT12EOC = 0xFFF;
|
||||||
/** Minimum value for FAT12 EOC. Use to test for EOC. */
|
/** Minimum value for FAT12 EOC. Use to test for EOC. */
|
||||||
uint16_t const FAT12EOC_MIN = 0XFF8;
|
uint16_t const FAT12EOC_MIN = 0xFF8;
|
||||||
/** FAT16 end of chain value used by Microsoft. */
|
/** FAT16 end of chain value used by Microsoft. */
|
||||||
uint16_t const FAT16EOC = 0XFFFF;
|
uint16_t const FAT16EOC = 0xFFFF;
|
||||||
/** Minimum value for FAT16 EOC. Use to test for EOC. */
|
/** Minimum value for FAT16 EOC. Use to test for EOC. */
|
||||||
uint16_t const FAT16EOC_MIN = 0XFFF8;
|
uint16_t const FAT16EOC_MIN = 0xFFF8;
|
||||||
/** FAT32 end of chain value used by Microsoft. */
|
/** FAT32 end of chain value used by Microsoft. */
|
||||||
uint32_t const FAT32EOC = 0X0FFFFFFF;
|
uint32_t const FAT32EOC = 0x0FFFFFFF;
|
||||||
/** Minimum value for FAT32 EOC. Use to test for EOC. */
|
/** Minimum value for FAT32 EOC. Use to test for EOC. */
|
||||||
uint32_t const FAT32EOC_MIN = 0X0FFFFFF8;
|
uint32_t const FAT32EOC_MIN = 0x0FFFFFF8;
|
||||||
/** Mask a for FAT32 entry. Entries are 28 bits. */
|
/** Mask a for FAT32 entry. Entries are 28 bits. */
|
||||||
uint32_t const FAT32MASK = 0X0FFFFFFF;
|
uint32_t const FAT32MASK = 0x0FFFFFFF;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* \struct directoryEntry
|
* \struct directoryEntry
|
||||||
@ -590,31 +590,31 @@ struct directoryVFATEntry {
|
|||||||
typedef struct directoryEntry dir_t;
|
typedef struct directoryEntry dir_t;
|
||||||
/** Type name for directoryVFATEntry */
|
/** Type name for directoryVFATEntry */
|
||||||
typedef struct directoryVFATEntry vfat_t;
|
typedef struct directoryVFATEntry vfat_t;
|
||||||
/** escape for name[0] = 0XE5 */
|
/** escape for name[0] = 0xE5 */
|
||||||
uint8_t const DIR_NAME_0XE5 = 0X05;
|
uint8_t const DIR_NAME_0xE5 = 0x05;
|
||||||
/** name[0] value for entry that is free after being "deleted" */
|
/** name[0] value for entry that is free after being "deleted" */
|
||||||
uint8_t const DIR_NAME_DELETED = 0XE5;
|
uint8_t const DIR_NAME_DELETED = 0xE5;
|
||||||
/** name[0] value for entry that is free and no allocated entries follow */
|
/** name[0] value for entry that is free and no allocated entries follow */
|
||||||
uint8_t const DIR_NAME_FREE = 0X00;
|
uint8_t const DIR_NAME_FREE = 0x00;
|
||||||
/** file is read-only */
|
/** file is read-only */
|
||||||
uint8_t const DIR_ATT_READ_ONLY = 0X01;
|
uint8_t const DIR_ATT_READ_ONLY = 0x01;
|
||||||
/** File should hidden in directory listings */
|
/** File should hidden in directory listings */
|
||||||
uint8_t const DIR_ATT_HIDDEN = 0X02;
|
uint8_t const DIR_ATT_HIDDEN = 0x02;
|
||||||
/** Entry is for a system file */
|
/** Entry is for a system file */
|
||||||
uint8_t const DIR_ATT_SYSTEM = 0X04;
|
uint8_t const DIR_ATT_SYSTEM = 0x04;
|
||||||
/** Directory entry contains the volume label */
|
/** Directory entry contains the volume label */
|
||||||
uint8_t const DIR_ATT_VOLUME_ID = 0X08;
|
uint8_t const DIR_ATT_VOLUME_ID = 0x08;
|
||||||
/** Entry is for a directory */
|
/** Entry is for a directory */
|
||||||
uint8_t const DIR_ATT_DIRECTORY = 0X10;
|
uint8_t const DIR_ATT_DIRECTORY = 0x10;
|
||||||
/** Old DOS archive bit for backup support */
|
/** Old DOS archive bit for backup support */
|
||||||
uint8_t const DIR_ATT_ARCHIVE = 0X20;
|
uint8_t const DIR_ATT_ARCHIVE = 0x20;
|
||||||
/** Test value for long name entry. Test is
|
/** Test value for long name entry. Test is
|
||||||
(d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
|
(d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
|
||||||
uint8_t const DIR_ATT_LONG_NAME = 0X0F;
|
uint8_t const DIR_ATT_LONG_NAME = 0x0F;
|
||||||
/** Test mask for long name entry */
|
/** Test mask for long name entry */
|
||||||
uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
|
uint8_t const DIR_ATT_LONG_NAME_MASK = 0x3F;
|
||||||
/** defined attribute bits */
|
/** defined attribute bits */
|
||||||
uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
|
uint8_t const DIR_ATT_DEFINED_BITS = 0x3F;
|
||||||
/** Directory entry is part of a long name
|
/** Directory entry is part of a long name
|
||||||
* \param[in] dir Pointer to a directory entry.
|
* \param[in] dir Pointer to a directory entry.
|
||||||
*
|
*
|
||||||
|
@ -45,59 +45,59 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// SD card commands
|
// SD card commands
|
||||||
/** GO_IDLE_STATE - init card in spi mode if CS low */
|
/** GO_IDLE_STATE - init card in spi mode if CS low */
|
||||||
uint8_t const CMD0 = 0X00;
|
uint8_t const CMD0 = 0x00;
|
||||||
/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
|
/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
|
||||||
uint8_t const CMD8 = 0X08;
|
uint8_t const CMD8 = 0x08;
|
||||||
/** SEND_CSD - read the Card Specific Data (CSD register) */
|
/** SEND_CSD - read the Card Specific Data (CSD register) */
|
||||||
uint8_t const CMD9 = 0X09;
|
uint8_t const CMD9 = 0x09;
|
||||||
/** SEND_CID - read the card identification information (CID register) */
|
/** SEND_CID - read the card identification information (CID register) */
|
||||||
uint8_t const CMD10 = 0X0A;
|
uint8_t const CMD10 = 0x0A;
|
||||||
/** STOP_TRANSMISSION - end multiple block read sequence */
|
/** STOP_TRANSMISSION - end multiple block read sequence */
|
||||||
uint8_t const CMD12 = 0X0C;
|
uint8_t const CMD12 = 0x0C;
|
||||||
/** SEND_STATUS - read the card status register */
|
/** SEND_STATUS - read the card status register */
|
||||||
uint8_t const CMD13 = 0X0D;
|
uint8_t const CMD13 = 0x0D;
|
||||||
/** READ_SINGLE_BLOCK - read a single data block from the card */
|
/** READ_SINGLE_BLOCK - read a single data block from the card */
|
||||||
uint8_t const CMD17 = 0X11;
|
uint8_t const CMD17 = 0x11;
|
||||||
/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
|
/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
|
||||||
uint8_t const CMD18 = 0X12;
|
uint8_t const CMD18 = 0x12;
|
||||||
/** WRITE_BLOCK - write a single data block to the card */
|
/** WRITE_BLOCK - write a single data block to the card */
|
||||||
uint8_t const CMD24 = 0X18;
|
uint8_t const CMD24 = 0x18;
|
||||||
/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
|
/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
|
||||||
uint8_t const CMD25 = 0X19;
|
uint8_t const CMD25 = 0x19;
|
||||||
/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
|
/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
|
||||||
uint8_t const CMD32 = 0X20;
|
uint8_t const CMD32 = 0x20;
|
||||||
/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
|
/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
|
||||||
range to be erased*/
|
range to be erased*/
|
||||||
uint8_t const CMD33 = 0X21;
|
uint8_t const CMD33 = 0x21;
|
||||||
/** ERASE - erase all previously selected blocks */
|
/** ERASE - erase all previously selected blocks */
|
||||||
uint8_t const CMD38 = 0X26;
|
uint8_t const CMD38 = 0x26;
|
||||||
/** APP_CMD - escape for application specific command */
|
/** APP_CMD - escape for application specific command */
|
||||||
uint8_t const CMD55 = 0X37;
|
uint8_t const CMD55 = 0x37;
|
||||||
/** READ_OCR - read the OCR register of a card */
|
/** READ_OCR - read the OCR register of a card */
|
||||||
uint8_t const CMD58 = 0X3A;
|
uint8_t const CMD58 = 0x3A;
|
||||||
/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
|
/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
|
||||||
pre-erased before writing */
|
pre-erased before writing */
|
||||||
uint8_t const ACMD23 = 0X17;
|
uint8_t const ACMD23 = 0x17;
|
||||||
/** SD_SEND_OP_COMD - Sends host capacity support information and
|
/** SD_SEND_OP_COMD - Sends host capacity support information and
|
||||||
activates the card's initialization process */
|
activates the card's initialization process */
|
||||||
uint8_t const ACMD41 = 0X29;
|
uint8_t const ACMD41 = 0x29;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** status for card in the ready state */
|
/** status for card in the ready state */
|
||||||
uint8_t const R1_READY_STATE = 0X00;
|
uint8_t const R1_READY_STATE = 0x00;
|
||||||
/** status for card in the idle state */
|
/** status for card in the idle state */
|
||||||
uint8_t const R1_IDLE_STATE = 0X01;
|
uint8_t const R1_IDLE_STATE = 0x01;
|
||||||
/** status bit for illegal command */
|
/** status bit for illegal command */
|
||||||
uint8_t const R1_ILLEGAL_COMMAND = 0X04;
|
uint8_t const R1_ILLEGAL_COMMAND = 0x04;
|
||||||
/** start data token for read or write single block*/
|
/** start data token for read or write single block*/
|
||||||
uint8_t const DATA_START_BLOCK = 0XFE;
|
uint8_t const DATA_START_BLOCK = 0xFE;
|
||||||
/** stop token for write multiple blocks*/
|
/** stop token for write multiple blocks*/
|
||||||
uint8_t const STOP_TRAN_TOKEN = 0XFD;
|
uint8_t const STOP_TRAN_TOKEN = 0xFD;
|
||||||
/** start data token for write multiple blocks*/
|
/** start data token for write multiple blocks*/
|
||||||
uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC;
|
uint8_t const WRITE_MULTIPLE_TOKEN = 0xFC;
|
||||||
/** mask for data response tokens after a write block operation */
|
/** mask for data response tokens after a write block operation */
|
||||||
uint8_t const DATA_RES_MASK = 0X1F;
|
uint8_t const DATA_RES_MASK = 0x1F;
|
||||||
/** write data accepted token */
|
/** write data accepted token */
|
||||||
uint8_t const DATA_RES_ACCEPTED = 0X05;
|
uint8_t const DATA_RES_ACCEPTED = 0x05;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Card IDentification (CID) register */
|
/** Card IDentification (CID) register */
|
||||||
typedef struct CID {
|
typedef struct CID {
|
||||||
@ -203,7 +203,7 @@ typedef struct CSDV2 {
|
|||||||
unsigned char reserved1 : 6;
|
unsigned char reserved1 : 6;
|
||||||
unsigned char csd_ver : 2;
|
unsigned char csd_ver : 2;
|
||||||
// byte 1
|
// byte 1
|
||||||
/** fixed to 0X0E */
|
/** fixed to 0x0E */
|
||||||
unsigned char taac;
|
unsigned char taac;
|
||||||
// byte 2
|
// byte 2
|
||||||
/** fixed to 0 */
|
/** fixed to 0 */
|
||||||
|
@ -73,14 +73,14 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
|||||||
// search the FAT for free clusters
|
// search the FAT for free clusters
|
||||||
for (uint32_t n = 0;; n++, endCluster++) {
|
for (uint32_t n = 0;; n++, endCluster++) {
|
||||||
// can't find space checked all clusters
|
// can't find space checked all clusters
|
||||||
if (n >= clusterCount_) goto fail;
|
if (n >= clusterCount_) goto FAIL;
|
||||||
|
|
||||||
// past end - start from beginning of FAT
|
// past end - start from beginning of FAT
|
||||||
if (endCluster > fatEnd) {
|
if (endCluster > fatEnd) {
|
||||||
bgnCluster = endCluster = 2;
|
bgnCluster = endCluster = 2;
|
||||||
}
|
}
|
||||||
uint32_t f;
|
uint32_t f;
|
||||||
if (!fatGet(endCluster, &f)) goto fail;
|
if (!fatGet(endCluster, &f)) goto FAIL;
|
||||||
|
|
||||||
if (f != 0) {
|
if (f != 0) {
|
||||||
// cluster in use try next cluster as bgnCluster
|
// cluster in use try next cluster as bgnCluster
|
||||||
@ -92,16 +92,16 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// mark end of chain
|
// mark end of chain
|
||||||
if (!fatPutEOC(endCluster)) goto fail;
|
if (!fatPutEOC(endCluster)) goto FAIL;
|
||||||
|
|
||||||
// link clusters
|
// link clusters
|
||||||
while (endCluster > bgnCluster) {
|
while (endCluster > bgnCluster) {
|
||||||
if (!fatPut(endCluster - 1, endCluster)) goto fail;
|
if (!fatPut(endCluster - 1, endCluster)) goto FAIL;
|
||||||
endCluster--;
|
endCluster--;
|
||||||
}
|
}
|
||||||
if (*curCluster != 0) {
|
if (*curCluster != 0) {
|
||||||
// connect chains
|
// connect chains
|
||||||
if (!fatPut(*curCluster, bgnCluster)) goto fail;
|
if (!fatPut(*curCluster, bgnCluster)) goto FAIL;
|
||||||
}
|
}
|
||||||
// return first cluster number to caller
|
// return first cluster number to caller
|
||||||
*curCluster = bgnCluster;
|
*curCluster = bgnCluster;
|
||||||
@ -110,38 +110,38 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
|||||||
if (setStart) allocSearchStart_ = bgnCluster + 1;
|
if (setStart) allocSearchStart_ = bgnCluster + 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool SdVolume::cacheFlush() {
|
bool SdVolume::cacheFlush() {
|
||||||
if (cacheDirty_) {
|
if (cacheDirty_) {
|
||||||
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
|
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
// mirror FAT tables
|
// mirror FAT tables
|
||||||
if (cacheMirrorBlock_) {
|
if (cacheMirrorBlock_) {
|
||||||
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
|
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
cacheMirrorBlock_ = 0;
|
cacheMirrorBlock_ = 0;
|
||||||
}
|
}
|
||||||
cacheDirty_ = 0;
|
cacheDirty_ = 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
|
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
|
||||||
if (cacheBlockNumber_ != blockNumber) {
|
if (cacheBlockNumber_ != blockNumber) {
|
||||||
if (!cacheFlush()) goto fail;
|
if (!cacheFlush()) goto FAIL;
|
||||||
if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail;
|
if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto FAIL;
|
||||||
cacheBlockNumber_ = blockNumber;
|
cacheBlockNumber_ = blockNumber;
|
||||||
}
|
}
|
||||||
if (dirty) cacheDirty_ = true;
|
if (dirty) cacheDirty_ = true;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -149,33 +149,33 @@ fail:
|
|||||||
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
|
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
|
||||||
uint32_t s = 0;
|
uint32_t s = 0;
|
||||||
do {
|
do {
|
||||||
if (!fatGet(cluster, &cluster)) goto fail;
|
if (!fatGet(cluster, &cluster)) goto FAIL;
|
||||||
s += 512UL << clusterSizeShift_;
|
s += 512UL << clusterSizeShift_;
|
||||||
} while (!isEOC(cluster));
|
} while (!isEOC(cluster));
|
||||||
*size = s;
|
*size = s;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Fetch a FAT entry
|
// Fetch a FAT entry
|
||||||
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
||||||
uint32_t lba;
|
uint32_t lba;
|
||||||
if (cluster > (clusterCount_ + 1)) goto fail;
|
if (cluster > (clusterCount_ + 1)) goto FAIL;
|
||||||
if (FAT12_SUPPORT && fatType_ == 12) {
|
if (FAT12_SUPPORT && fatType_ == 12) {
|
||||||
uint16_t index = cluster;
|
uint16_t index = cluster;
|
||||||
index += index >> 1;
|
index += index >> 1;
|
||||||
lba = fatStartBlock_ + (index >> 9);
|
lba = fatStartBlock_ + (index >> 9);
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto FAIL;
|
||||||
index &= 0X1FF;
|
index &= 0x1FF;
|
||||||
uint16_t tmp = cacheBuffer_.data[index];
|
uint16_t tmp = cacheBuffer_.data[index];
|
||||||
index++;
|
index++;
|
||||||
if (index == 512) {
|
if (index == 512) {
|
||||||
if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto FAIL;
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
tmp |= cacheBuffer_.data[index] << 8;
|
tmp |= cacheBuffer_.data[index] << 8;
|
||||||
*value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
|
*value = cluster & 1 ? tmp >> 4 : tmp & 0xFFF;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (fatType_ == 16) {
|
if (fatType_ == 16) {
|
||||||
@ -185,19 +185,19 @@ bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
|||||||
lba = fatStartBlock_ + (cluster >> 7);
|
lba = fatStartBlock_ + (cluster >> 7);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
if (lba != cacheBlockNumber_) {
|
if (lba != cacheBlockNumber_) {
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto FAIL;
|
||||||
}
|
}
|
||||||
if (fatType_ == 16) {
|
if (fatType_ == 16) {
|
||||||
*value = cacheBuffer_.fat16[cluster & 0XFF];
|
*value = cacheBuffer_.fat16[cluster & 0xFF];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
|
*value = cacheBuffer_.fat32[cluster & 0x7F] & FAT32MASK;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -205,19 +205,19 @@ fail:
|
|||||||
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
||||||
uint32_t lba;
|
uint32_t lba;
|
||||||
// error if reserved cluster
|
// error if reserved cluster
|
||||||
if (cluster < 2) goto fail;
|
if (cluster < 2) goto FAIL;
|
||||||
|
|
||||||
// error if not in FAT
|
// error if not in FAT
|
||||||
if (cluster > (clusterCount_ + 1)) goto fail;
|
if (cluster > (clusterCount_ + 1)) goto FAIL;
|
||||||
|
|
||||||
if (FAT12_SUPPORT && fatType_ == 12) {
|
if (FAT12_SUPPORT && fatType_ == 12) {
|
||||||
uint16_t index = cluster;
|
uint16_t index = cluster;
|
||||||
index += index >> 1;
|
index += index >> 1;
|
||||||
lba = fatStartBlock_ + (index >> 9);
|
lba = fatStartBlock_ + (index >> 9);
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
|
||||||
// mirror second FAT
|
// mirror second FAT
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
index &= 0X1FF;
|
index &= 0x1FF;
|
||||||
uint8_t tmp = value;
|
uint8_t tmp = value;
|
||||||
if (cluster & 1) {
|
if (cluster & 1) {
|
||||||
tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
|
tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
|
||||||
@ -227,13 +227,13 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
|||||||
if (index == 512) {
|
if (index == 512) {
|
||||||
lba++;
|
lba++;
|
||||||
index = 0;
|
index = 0;
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
|
||||||
// mirror second FAT
|
// mirror second FAT
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
}
|
}
|
||||||
tmp = value >> 4;
|
tmp = value >> 4;
|
||||||
if (!(cluster & 1)) {
|
if (!(cluster & 1)) {
|
||||||
tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4;
|
tmp = ((cacheBuffer_.data[index] & 0xF0)) | tmp >> 4;
|
||||||
}
|
}
|
||||||
cacheBuffer_.data[index] = tmp;
|
cacheBuffer_.data[index] = tmp;
|
||||||
return true;
|
return true;
|
||||||
@ -245,20 +245,20 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
|||||||
lba = fatStartBlock_ + (cluster >> 7);
|
lba = fatStartBlock_ + (cluster >> 7);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
|
||||||
// store entry
|
// store entry
|
||||||
if (fatType_ == 16) {
|
if (fatType_ == 16) {
|
||||||
cacheBuffer_.fat16[cluster & 0XFF] = value;
|
cacheBuffer_.fat16[cluster & 0xFF] = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cacheBuffer_.fat32[cluster & 0X7F] = value;
|
cacheBuffer_.fat32[cluster & 0x7F] = value;
|
||||||
}
|
}
|
||||||
// mirror second FAT
|
// mirror second FAT
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -270,16 +270,16 @@ bool SdVolume::freeChain(uint32_t cluster) {
|
|||||||
allocSearchStart_ = 2;
|
allocSearchStart_ = 2;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!fatGet(cluster, &next)) goto fail;
|
if (!fatGet(cluster, &next)) goto FAIL;
|
||||||
|
|
||||||
// free cluster
|
// free cluster
|
||||||
if (!fatPut(cluster, 0)) goto fail;
|
if (!fatPut(cluster, 0)) goto FAIL;
|
||||||
|
|
||||||
cluster = next;
|
cluster = next;
|
||||||
} while (!isEOC(cluster));
|
} while (!isEOC(cluster));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -344,30 +344,30 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
|||||||
allocSearchStart_ = 2;
|
allocSearchStart_ = 2;
|
||||||
cacheDirty_ = 0; // cacheFlush() will write block if true
|
cacheDirty_ = 0; // cacheFlush() will write block if true
|
||||||
cacheMirrorBlock_ = 0;
|
cacheMirrorBlock_ = 0;
|
||||||
cacheBlockNumber_ = 0XFFFFFFFF;
|
cacheBlockNumber_ = 0xFFFFFFFF;
|
||||||
|
|
||||||
// if part == 0 assume super floppy with FAT boot sector in block zero
|
// if part == 0 assume super floppy with FAT boot sector in block zero
|
||||||
// if part > 0 assume mbr volume with partition table
|
// if part > 0 assume mbr volume with partition table
|
||||||
if (part) {
|
if (part) {
|
||||||
if (part > 4)goto fail;
|
if (part > 4)goto FAIL;
|
||||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto FAIL;
|
||||||
part_t* p = &cacheBuffer_.mbr.part[part - 1];
|
part_t* p = &cacheBuffer_.mbr.part[part - 1];
|
||||||
if ((p->boot & 0X7F) != 0 ||
|
if ((p->boot & 0x7F) != 0 ||
|
||||||
p->totalSectors < 100 ||
|
p->totalSectors < 100 ||
|
||||||
p->firstSector == 0) {
|
p->firstSector == 0) {
|
||||||
// not a valid partition
|
// not a valid partition
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
volumeStartBlock = p->firstSector;
|
volumeStartBlock = p->firstSector;
|
||||||
}
|
}
|
||||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto FAIL;
|
||||||
fbs = &cacheBuffer_.fbs32;
|
fbs = &cacheBuffer_.fbs32;
|
||||||
if (fbs->bytesPerSector != 512 ||
|
if (fbs->bytesPerSector != 512 ||
|
||||||
fbs->fatCount == 0 ||
|
fbs->fatCount == 0 ||
|
||||||
fbs->reservedSectorCount == 0 ||
|
fbs->reservedSectorCount == 0 ||
|
||||||
fbs->sectorsPerCluster == 0) {
|
fbs->sectorsPerCluster == 0) {
|
||||||
// not valid FAT volume
|
// not valid FAT volume
|
||||||
goto fail;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
fatCount_ = fbs->fatCount;
|
fatCount_ = fbs->fatCount;
|
||||||
blocksPerCluster_ = fbs->sectorsPerCluster;
|
blocksPerCluster_ = fbs->sectorsPerCluster;
|
||||||
@ -375,7 +375,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
|||||||
clusterSizeShift_ = 0;
|
clusterSizeShift_ = 0;
|
||||||
while (blocksPerCluster_ != _BV(clusterSizeShift_)) {
|
while (blocksPerCluster_ != _BV(clusterSizeShift_)) {
|
||||||
// error if not power of 2
|
// error if not power of 2
|
||||||
if (clusterSizeShift_++ > 7) goto fail;
|
if (clusterSizeShift_++ > 7) goto FAIL;
|
||||||
}
|
}
|
||||||
blocksPerFat_ = fbs->sectorsPerFat16 ?
|
blocksPerFat_ = fbs->sectorsPerFat16 ?
|
||||||
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
||||||
@ -404,7 +404,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
|||||||
// FAT type is determined by cluster count
|
// FAT type is determined by cluster count
|
||||||
if (clusterCount_ < 4085) {
|
if (clusterCount_ < 4085) {
|
||||||
fatType_ = 12;
|
fatType_ = 12;
|
||||||
if (!FAT12_SUPPORT) goto fail;
|
if (!FAT12_SUPPORT) goto FAIL;
|
||||||
}
|
}
|
||||||
else if (clusterCount_ < 65525) {
|
else if (clusterCount_ < 65525) {
|
||||||
fatType_ = 16;
|
fatType_ = 16;
|
||||||
@ -414,7 +414,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
|||||||
fatType_ = 32;
|
fatType_ = 32;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
fail:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,7 +76,7 @@ class SdVolume {
|
|||||||
*/
|
*/
|
||||||
cache_t* cacheClear() {
|
cache_t* cacheClear() {
|
||||||
if (!cacheFlush()) return 0;
|
if (!cacheFlush()) return 0;
|
||||||
cacheBlockNumber_ = 0XFFFFFFFF;
|
cacheBlockNumber_ = 0xFFFFFFFF;
|
||||||
return &cacheBuffer_;
|
return &cacheBuffer_;
|
||||||
}
|
}
|
||||||
/** Initialize a FAT volume. Try partition one first then try super
|
/** Initialize a FAT volume. Try partition one first then try super
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
// User-specified version info of this build to display in [Pronterface, etc] terminal window during
|
// User-specified version info of this build to display in [Pronterface, etc] terminal window during
|
||||||
// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
|
// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
|
||||||
// build by the user have been successfully uploaded into firmware.
|
// build by the user have been successfully uploaded into firmware.
|
||||||
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
|
#define STRING_CONFIG_H_AUTHOR "(Creality CR-10)" // Who made the changes.
|
||||||
#define SHOW_BOOTSCREEN
|
#define SHOW_BOOTSCREEN
|
||||||
#define STRING_SPLASH_LINE1 SHORT_BUILD_VERSION // will be shown during bootup in line 1
|
#define STRING_SPLASH_LINE1 SHORT_BUILD_VERSION // will be shown during bootup in line 1
|
||||||
//#define STRING_SPLASH_LINE2 WEBSITE_URL // will be shown during bootup in line 2
|
//#define STRING_SPLASH_LINE2 WEBSITE_URL // will be shown during bootup in line 2
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#define PCA9632_PWM3 0x05
|
#define PCA9632_PWM3 0x05
|
||||||
#define PCA9632_GRPPWM 0x06
|
#define PCA9632_GRPPWM 0x06
|
||||||
#define PCA9632_GRPFREQ 0x07
|
#define PCA9632_GRPFREQ 0x07
|
||||||
#define PCA9632_LEDOUT 0X08
|
#define PCA9632_LEDOUT 0x08
|
||||||
#define PCA9632_SUBADR1 0x09
|
#define PCA9632_SUBADR1 0x09
|
||||||
#define PCA9632_SUBADR2 0x0A
|
#define PCA9632_SUBADR2 0x0A
|
||||||
#define PCA9632_SUBADR3 0x0B
|
#define PCA9632_SUBADR3 0x0B
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* Melzi (Creality) pin assignments
|
* Melzi (Creality) pin assignments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BOARD_NAME "Melzi Creality"
|
#define BOARD_NAME "Melzi (Creality)"
|
||||||
|
|
||||||
#ifdef __AVR_ATmega1284P__
|
#ifdef __AVR_ATmega1284P__
|
||||||
#define LARGE_FLASH true
|
#define LARGE_FLASH true
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* Melzi with ATmega1284 (MaKr3d version) pin assignments
|
* Melzi with ATmega1284 (MaKr3d version) pin assignments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BOARD_NAME "Melzi ATmega1284"
|
#define BOARD_NAME "Melzi (ATmega1284)"
|
||||||
|
|
||||||
#ifdef __AVR_ATmega1284P__
|
#ifdef __AVR_ATmega1284P__
|
||||||
#define LARGE_FLASH true
|
#define LARGE_FLASH true
|
||||||
|
@ -455,7 +455,7 @@ void badPinCheck(uint8_t pin) {
|
|||||||
static inline __attribute__((always_inline))
|
static inline __attribute__((always_inline))
|
||||||
void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
|
void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
|
||||||
uint8_t oldSREG;
|
uint8_t oldSREG;
|
||||||
if (address > (uint8_t*)0X5F) {
|
if (address > (uint8_t*)0x5F) {
|
||||||
oldSREG = SREG;
|
oldSREG = SREG;
|
||||||
cli();
|
cli();
|
||||||
}
|
}
|
||||||
@ -464,7 +464,7 @@ void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
|
|||||||
} else {
|
} else {
|
||||||
*address &= ~(1 << bit);
|
*address &= ~(1 << bit);
|
||||||
}
|
}
|
||||||
if (address > (uint8_t*)0X5F) {
|
if (address > (uint8_t*)0x5F) {
|
||||||
SREG = oldSREG;
|
SREG = oldSREG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,7 +488,7 @@ bool fastDigitalRead(uint8_t pin) {
|
|||||||
static inline __attribute__((always_inline))
|
static inline __attribute__((always_inline))
|
||||||
void fastDigitalToggle(uint8_t pin) {
|
void fastDigitalToggle(uint8_t pin) {
|
||||||
badPinCheck(pin);
|
badPinCheck(pin);
|
||||||
if (pinMap[pin].pin > (uint8_t*)0X5F) {
|
if (pinMap[pin].pin > (uint8_t*)0x5F) {
|
||||||
// must write bit to high address port
|
// must write bit to high address port
|
||||||
*pinMap[pin].pin = 1 << pinMap[pin].bit;
|
*pinMap[pin].pin = 1 << pinMap[pin].bit;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2720,11 +2720,16 @@ void kill_screen(const char* lcd_msg) {
|
|||||||
|
|
||||||
screenFunc_t _manual_move_func_ptr;
|
screenFunc_t _manual_move_func_ptr;
|
||||||
|
|
||||||
void lcd_move_menu_10mm() { move_menu_scale = 10.0; lcd_goto_screen(_manual_move_func_ptr); }
|
void _goto_manual_move(const float scale) {
|
||||||
void lcd_move_menu_1mm() { move_menu_scale = 1.0; lcd_goto_screen(_manual_move_func_ptr); }
|
defer_return_to_status = true;
|
||||||
void lcd_move_menu_01mm() { move_menu_scale = 0.1; lcd_goto_screen(_manual_move_func_ptr); }
|
move_menu_scale = scale;
|
||||||
|
lcd_goto_screen(_manual_move_func_ptr);
|
||||||
|
}
|
||||||
|
void lcd_move_menu_10mm() { _goto_manual_move(10.0); }
|
||||||
|
void lcd_move_menu_1mm() { _goto_manual_move( 1.0); }
|
||||||
|
void lcd_move_menu_01mm() { _goto_manual_move( 0.1); }
|
||||||
|
|
||||||
void _lcd_move_distance_menu(AxisEnum axis, screenFunc_t func) {
|
void _lcd_move_distance_menu(const AxisEnum axis, const screenFunc_t func) {
|
||||||
_manual_move_func_ptr = func;
|
_manual_move_func_ptr = func;
|
||||||
START_MENU();
|
START_MENU();
|
||||||
if (LCD_HEIGHT >= 4) {
|
if (LCD_HEIGHT >= 4) {
|
||||||
|
Loading…
Reference in New Issue
Block a user