mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-08-13 06:19:02 +08:00
Add [ESP715]FORMATSD to format SD card
Add SD format feature on SDFat for esp8266 and esp32
This commit is contained in:
parent
ba31b453e3
commit
3bae4748bf
@ -187,6 +187,9 @@ Get will give type and settings only, not the protected T1/T2
|
|||||||
* Format ESP Filesystem
|
* Format ESP Filesystem
|
||||||
[ESP710]FORMAT pwd=<admin password>
|
[ESP710]FORMAT pwd=<admin password>
|
||||||
|
|
||||||
|
* Format SD Filesystem
|
||||||
|
[ESP715]FORMATSD pwd=<admin password>
|
||||||
|
|
||||||
* List ESP Filesystem
|
* List ESP Filesystem
|
||||||
[ESP720]<Root> pwd=<admin password>
|
[ESP720]<Root> pwd=<admin password>
|
||||||
|
|
||||||
|
@ -513,9 +513,16 @@ bool Commands::execute_internal_command (int cmd, const char* cmd_params, level_
|
|||||||
response = ESP710(cmd_params, auth_type, output);
|
response = ESP710(cmd_params, auth_type, output);
|
||||||
break;
|
break;
|
||||||
#endif //FILESYSTEM_FEATURE
|
#endif //FILESYSTEM_FEATURE
|
||||||
|
#if defined(SD_DEVICE)
|
||||||
|
//Format ESP Filesystem
|
||||||
|
//[ESP715]FORMATSD pwd=<admin password>
|
||||||
|
case 715:
|
||||||
|
response = ESP715(cmd_params, auth_type, output);
|
||||||
|
break;
|
||||||
|
#endif //SD_DEVICE
|
||||||
#if defined(FILESYSTEM_FEATURE) && defined(ESP_GCODE_HOST_FEATURE)
|
#if defined(FILESYSTEM_FEATURE) && defined(ESP_GCODE_HOST_FEATURE)
|
||||||
//Open local file
|
//Open local file
|
||||||
//[ESP700]<filname>
|
//[ESP700]<filename>
|
||||||
case 700:
|
case 700:
|
||||||
response = ESP700(cmd_params, auth_type, output);
|
response = ESP700(cmd_params, auth_type, output);
|
||||||
break;
|
break;
|
||||||
|
@ -124,6 +124,7 @@ public:
|
|||||||
bool ESP730(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP730(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
#endif //FILESYSTEM_FEATURE
|
#endif //FILESYSTEM_FEATURE
|
||||||
#if defined (SD_DEVICE)
|
#if defined (SD_DEVICE)
|
||||||
|
bool ESP715(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
bool ESP750(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP750(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
bool ESP740(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP740(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
#endif //SD_DEVICE
|
#endif //SD_DEVICE
|
||||||
|
@ -187,7 +187,7 @@ size_t ESP3DOutput::printLN(const char * s)
|
|||||||
return println(s);
|
return println(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ESP3DOutput::printMSG(const char * s)
|
size_t ESP3DOutput::printMSG(const char * s, bool withNL)
|
||||||
{
|
{
|
||||||
if (!isOutput(_client)) {
|
if (!isOutput(_client)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -237,7 +237,11 @@ size_t ESP3DOutput::printMSG(const char * s)
|
|||||||
display = ";";
|
display = ";";
|
||||||
display += s;
|
display += s;
|
||||||
}
|
}
|
||||||
|
if(withNL) {
|
||||||
return printLN(display.c_str());
|
return printLN(display.c_str());
|
||||||
|
} else {
|
||||||
|
return print(display.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ESP3DOutput::printERROR(const char * s, int code_error)
|
size_t ESP3DOutput::printERROR(const char * s, int code_error)
|
||||||
|
@ -81,7 +81,7 @@ public:
|
|||||||
return _client;
|
return _client;
|
||||||
}
|
}
|
||||||
size_t dispatch (uint8_t * sbuf, size_t len);
|
size_t dispatch (uint8_t * sbuf, size_t len);
|
||||||
size_t printMSG(const char * s);
|
size_t printMSG(const char * s, bool withNL = true);
|
||||||
size_t printERROR(const char * s, int code_error = 200);
|
size_t printERROR(const char * s, int code_error = 200);
|
||||||
size_t printLN(const char * s);
|
size_t printLN(const char * s);
|
||||||
void flush();
|
void flush();
|
||||||
|
59
esp3d/src/core/espcmd/ESP715.cpp
Normal file
59
esp3d/src/core/espcmd/ESP715.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
ESP715.cpp - ESP3D command class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if defined (SD_DEVICE)
|
||||||
|
#include "../commands.h"
|
||||||
|
#include "../esp3doutput.h"
|
||||||
|
#include "../settings_esp3d.h"
|
||||||
|
#include "../../modules/authentication/authentication_service.h"
|
||||||
|
#include "../../modules/filesystem/esp_sd.h"
|
||||||
|
//Format SD Filesystem
|
||||||
|
//[ESP715]FORMAT pwd=<admin password>
|
||||||
|
bool Commands::ESP715(const char* cmd_params, level_authenticate_type auth_type, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
bool response = true;
|
||||||
|
String parameter;
|
||||||
|
parameter = get_param (cmd_params, "");
|
||||||
|
#ifdef AUTHENTICATION_FEATURE
|
||||||
|
if (auth_type != LEVEL_ADMIN) {
|
||||||
|
output->printERROR("Wrong authentication!", 401);
|
||||||
|
response = false;
|
||||||
|
} else
|
||||||
|
#else
|
||||||
|
(void)auth_type;
|
||||||
|
#endif //AUTHENTICATION_FEATURE
|
||||||
|
{
|
||||||
|
if (parameter == "FORMATSD") {
|
||||||
|
output->printMSG("Start Formating");
|
||||||
|
if (ESP_SD::format(output)) {
|
||||||
|
output->printMSG("Format Done");
|
||||||
|
} else {
|
||||||
|
output->printERROR ("Format failed!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output->printERROR ("Invalid parameter!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SD_DEVICE
|
@ -22,7 +22,7 @@
|
|||||||
#define _VERSION_ESP3D_H
|
#define _VERSION_ESP3D_H
|
||||||
|
|
||||||
//version and sources location
|
//version and sources location
|
||||||
#define FW_VERSION "3.0.0.a23"
|
#define FW_VERSION "3.0.0.a24"
|
||||||
#define REPOSITORY "https://github.com/luc-github/ESP3D"
|
#define REPOSITORY "https://github.com/luc-github/ESP3D"
|
||||||
|
|
||||||
#endif //_VERSION_ESP3D_H
|
#endif //_VERSION_ESP3D_H
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#ifndef _ESP_SD_H
|
#ifndef _ESP_SD_H
|
||||||
#define _ESP_SD_H
|
#define _ESP_SD_H
|
||||||
#include "../../include/esp3d_config.h"
|
#include "../../include/esp3d_config.h"
|
||||||
|
#include "../../core/esp3doutput.h"
|
||||||
#ifdef SD_TIMESTAMP_FEATURE
|
#ifdef SD_TIMESTAMP_FEATURE
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif //SD_TIMESTAMP_FEATURE
|
#endif //SD_TIMESTAMP_FEATURE
|
||||||
@ -85,7 +86,7 @@ public:
|
|||||||
static uint64_t usedBytes();
|
static uint64_t usedBytes();
|
||||||
static uint64_t freeBytes();
|
static uint64_t freeBytes();
|
||||||
static const char * FilesystemName();
|
static const char * FilesystemName();
|
||||||
static bool format();
|
static bool format(ESP3DOutput * output = nullptr);
|
||||||
static ESP_SDFile open(const char* path, uint8_t mode = ESP_SD_FILE_READ);
|
static ESP_SDFile open(const char* path, uint8_t mode = ESP_SD_FILE_READ);
|
||||||
static bool exists(const char* path);
|
static bool exists(const char* path);
|
||||||
static bool remove(const char *path);
|
static bool remove(const char *path);
|
||||||
|
@ -99,9 +99,12 @@ uint64_t ESP_SD::freeBytes()
|
|||||||
return (SD.totalBytes() - SD.usedBytes());
|
return (SD.totalBytes() - SD.usedBytes());
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ESP_SD::format()
|
bool ESP_SD::format(ESP3DOutput * output)
|
||||||
{
|
{
|
||||||
//not available yet
|
//not available yet
|
||||||
|
if (output) {
|
||||||
|
output->printERROR ("Not implemented!");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +147,441 @@ uint64_t ESP_SD::freeBytes()
|
|||||||
return volFree * blocks * 512;
|
return volFree * blocks * 512;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ESP_SD::format()
|
// strings needed in file system structures
|
||||||
|
#define noName "NO NAME "
|
||||||
|
#define fat16str "FAT16 "
|
||||||
|
#define fat32str "FAT32 "
|
||||||
|
// constants for file system structure
|
||||||
|
#define BU16 128
|
||||||
|
#define BU32 8192
|
||||||
|
#define ERASE_SIZE 262144L;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// write cached block to the card
|
||||||
|
uint8_t writeCache(uint32_t lbn, Sd2Card & card, cache_t & cache)
|
||||||
{
|
{
|
||||||
//not available yet
|
return card.writeBlock(lbn, cache.data);
|
||||||
//SDFat has a feature for this
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// initialize appropriate sizes for SD capacity
|
||||||
|
bool initSizes(uint32_t cardCapacityMB, uint8_t & sectorsPerCluster, uint8_t & numberOfHeads, uint8_t & sectorsPerTrack)
|
||||||
|
{
|
||||||
|
if (cardCapacityMB <= 6) {
|
||||||
|
return false;
|
||||||
|
} else if (cardCapacityMB <= 16) {
|
||||||
|
sectorsPerCluster = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
sectorsPerCluster = 4;
|
||||||
|
} else if (cardCapacityMB <= 64) {
|
||||||
|
sectorsPerCluster = 8;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
sectorsPerCluster = 16;
|
||||||
|
} else if (cardCapacityMB <= 1024) {
|
||||||
|
sectorsPerCluster = 32;
|
||||||
|
} else if (cardCapacityMB <= 32768) {
|
||||||
|
sectorsPerCluster = 64;
|
||||||
|
} else {
|
||||||
|
// SDXC cards
|
||||||
|
sectorsPerCluster = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set fake disk geometry
|
||||||
|
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
|
||||||
|
|
||||||
|
if (cardCapacityMB <= 16) {
|
||||||
|
numberOfHeads = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
numberOfHeads = 4;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
numberOfHeads = 8;
|
||||||
|
} else if (cardCapacityMB <= 504) {
|
||||||
|
numberOfHeads = 16;
|
||||||
|
} else if (cardCapacityMB <= 1008) {
|
||||||
|
numberOfHeads = 32;
|
||||||
|
} else if (cardCapacityMB <= 2016) {
|
||||||
|
numberOfHeads = 64;
|
||||||
|
} else if (cardCapacityMB <= 4032) {
|
||||||
|
numberOfHeads = 128;
|
||||||
|
} else {
|
||||||
|
numberOfHeads = 255;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// zero cache and optionally set the sector signature
|
||||||
|
void clearCache(uint8_t addSig, cache_t & cache)
|
||||||
|
{
|
||||||
|
memset(&cache, 0, sizeof(cache));
|
||||||
|
if (addSig) {
|
||||||
|
cache.mbr.mbrSig0 = BOOTSIG0;
|
||||||
|
cache.mbr.mbrSig1 = BOOTSIG1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// zero FAT and root dir area on SD
|
||||||
|
bool clearFatDir(uint32_t bgn, uint32_t count, Sd2Card & card, cache_t & cache, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
clearCache(false, cache);
|
||||||
|
if (!card.writeStart(bgn, count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if ((i & 0XFF) == 0) {
|
||||||
|
if (output) {
|
||||||
|
output->print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!card.writeData(cache.data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!card.writeStop()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return cylinder number for a logical block number
|
||||||
|
uint16_t lbnToCylinder(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return lbn / (numberOfHeads * sectorsPerTrack);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return head number for a logical block number
|
||||||
|
uint8_t lbnToHead(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return sector number for a logical block number
|
||||||
|
uint8_t lbnToSector(uint32_t lbn, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return (lbn % sectorsPerTrack) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// format and write the Master Boot Record
|
||||||
|
bool writeMbr(Sd2Card & card, cache_t & cache, uint8_t partType, uint32_t relSector, uint32_t partSize, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
clearCache(true, cache);
|
||||||
|
part_t* p = cache.mbr.part;
|
||||||
|
p->boot = 0;
|
||||||
|
uint16_t c = lbnToCylinder(relSector, numberOfHeads, sectorsPerTrack);
|
||||||
|
if (c > 1023) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p->beginCylinderHigh = c >> 8;
|
||||||
|
p->beginCylinderLow = c & 0XFF;
|
||||||
|
p->beginHead = lbnToHead(relSector, numberOfHeads, sectorsPerTrack);
|
||||||
|
p->beginSector = lbnToSector(relSector, sectorsPerTrack);
|
||||||
|
p->type = partType;
|
||||||
|
uint32_t endLbn = relSector + partSize - 1;
|
||||||
|
c = lbnToCylinder(endLbn,numberOfHeads, sectorsPerTrack);
|
||||||
|
if (c <= 1023) {
|
||||||
|
p->endCylinderHigh = c >> 8;
|
||||||
|
p->endCylinderLow = c & 0XFF;
|
||||||
|
p->endHead = lbnToHead(endLbn, numberOfHeads, sectorsPerTrack);
|
||||||
|
p->endSector = lbnToSector(endLbn, sectorsPerTrack);
|
||||||
|
} else {
|
||||||
|
// Too big flag, c = 1023, h = 254, s = 63
|
||||||
|
p->endCylinderHigh = 3;
|
||||||
|
p->endCylinderLow = 255;
|
||||||
|
p->endHead = 254;
|
||||||
|
p->endSector = 63;
|
||||||
|
}
|
||||||
|
p->firstSector = relSector;
|
||||||
|
p->totalSectors = partSize;
|
||||||
|
if (!writeCache(0, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// generate serial number from card size and micros since boot
|
||||||
|
uint32_t volSerialNumber(uint32_t cardSizeBlocks)
|
||||||
|
{
|
||||||
|
return (cardSizeBlocks << 8) + micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
// format the SD as FAT16
|
||||||
|
bool makeFat16(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t nc;
|
||||||
|
for (dataStart = 2 * BU16;; dataStart += BU16) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 255)/256;
|
||||||
|
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
|
||||||
|
if (dataStart < r) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
relSector = dataStart - r + BU16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// check valid cluster count for FAT16 volume
|
||||||
|
if (nc < 4085 || nc >= 65525) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reservedSectors = 1;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
|
||||||
|
if (partSize < 32680) {
|
||||||
|
partType = 0X01;
|
||||||
|
} else if (partSize < 65536) {
|
||||||
|
partType = 0X04;
|
||||||
|
} else {
|
||||||
|
partType = 0X06;
|
||||||
|
}
|
||||||
|
// write MBR
|
||||||
|
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
fat_boot_t* pb = &cache.fbs;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->rootDirEntryCount = 512;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerFat16 = fatSize;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
|
||||||
|
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||||
|
memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector
|
||||||
|
if (!writeCache(relSector, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// clear FAT and root directory
|
||||||
|
clearFatDir(fatStart, dataStart - fatStart, card, cache, output);
|
||||||
|
clearCache(false, cache);
|
||||||
|
cache.fat16[0] = 0XFFF8;
|
||||||
|
cache.fat16[1] = 0XFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart, card, cache)
|
||||||
|
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format the SD as FAT32
|
||||||
|
bool makeFat32(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t nc;
|
||||||
|
relSector = BU32;
|
||||||
|
for (dataStart = 2 * BU32;; dataStart += BU32) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 127)/128;
|
||||||
|
uint32_t r = relSector + 9 + 2 * fatSize;
|
||||||
|
if (dataStart >= r) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// error if too few clusters in FAT32 volume
|
||||||
|
if (nc < 65525) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reservedSectors = dataStart - relSector - 2 * fatSize;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + dataStart - relSector;
|
||||||
|
// type depends on address of end sector
|
||||||
|
// max CHS has lbn = 16450560 = 1024*255*63
|
||||||
|
if ((relSector + partSize) <= 16450560) {
|
||||||
|
// FAT32
|
||||||
|
partType = 0X0B;
|
||||||
|
} else {
|
||||||
|
// FAT32 with INT 13
|
||||||
|
partType = 0X0C;
|
||||||
|
}
|
||||||
|
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
|
||||||
|
fat32_boot_t* pb = &cache.fbs32;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->sectorsPerFat32 = fatSize;
|
||||||
|
pb->fat32RootCluster = 2;
|
||||||
|
pb->fat32FSInfo = 1;
|
||||||
|
pb->fat32BackBootBlock = 6;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
|
||||||
|
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||||
|
memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector and backup
|
||||||
|
if (!writeCache(relSector, card, cache)
|
||||||
|
|| !writeCache(relSector + 6, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
// write extra boot area and backup
|
||||||
|
if (!writeCache(relSector + 2, card, cache)
|
||||||
|
|| !writeCache(relSector + 8, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fat32_fsinfo_t* pf = &cache.fsinfo;
|
||||||
|
pf->leadSignature = FSINFO_LEAD_SIG;
|
||||||
|
pf->structSignature = FSINFO_STRUCT_SIG;
|
||||||
|
pf->freeCount = 0XFFFFFFFF;
|
||||||
|
pf->nextFree = 0XFFFFFFFF;
|
||||||
|
// write FSINFO sector and backup
|
||||||
|
if (!writeCache(relSector + 1, card, cache)
|
||||||
|
|| !writeCache(relSector + 7, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster, card, cache, output);
|
||||||
|
clearCache(false, cache);
|
||||||
|
cache.fat32[0] = 0x0FFFFFF8;
|
||||||
|
cache.fat32[1] = 0x0FFFFFFF;
|
||||||
|
cache.fat32[2] = 0x0FFFFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart, card, cache)
|
||||||
|
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eraseCard(Sd2Card & card, cache_t & cache, uint32_t cardSizeBlocks, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t firstBlock = 0;
|
||||||
|
uint32_t lastBlock;
|
||||||
|
uint16_t n = 0;
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Erasing ", false);
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
lastBlock = firstBlock + ERASE_SIZE - 1;
|
||||||
|
if (lastBlock >= cardSizeBlocks) {
|
||||||
|
lastBlock = cardSizeBlocks - 1;
|
||||||
|
}
|
||||||
|
if (!card.erase(firstBlock, lastBlock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->print(".");
|
||||||
|
}
|
||||||
|
firstBlock += ERASE_SIZE;
|
||||||
|
} while (firstBlock < cardSizeBlocks);
|
||||||
|
|
||||||
|
if (!card.readBlock(0, cache.data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->printLN("");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool formatCard(uint32_t & dataStart, Sd2Card & card,
|
||||||
|
cache_t & cache, uint8_t numberOfHeads,
|
||||||
|
uint8_t sectorsPerTrack, uint32_t cardSizeBlocks,
|
||||||
|
uint8_t sectorsPerCluster, uint32_t &relSector,
|
||||||
|
uint32_t partSize, uint8_t & partType,
|
||||||
|
uint32_t &fatSize, uint32_t &fatStart,
|
||||||
|
uint32_t cardCapacityMB, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
initSizes(cardCapacityMB, sectorsPerCluster, numberOfHeads, sectorsPerTrack);
|
||||||
|
if (card.type() != SD_CARD_TYPE_SDHC) {
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Formating FAT16 ");
|
||||||
|
}
|
||||||
|
if(!makeFat16(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Formating FAT32 ", false);
|
||||||
|
}
|
||||||
|
if(!makeFat32(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->printLN("");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_SD::format(ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
if (ESP_SD::getState(true) == ESP_SDCARD_IDLE) {
|
||||||
|
Sd2Card card;
|
||||||
|
uint32_t cardSizeBlocks;
|
||||||
|
uint32_t cardCapacityMB;
|
||||||
|
// cache for SD block
|
||||||
|
cache_t cache;
|
||||||
|
|
||||||
|
// MBR information
|
||||||
|
uint8_t partType;
|
||||||
|
uint32_t relSector;
|
||||||
|
uint32_t partSize;
|
||||||
|
|
||||||
|
// Fake disk geometry
|
||||||
|
uint8_t numberOfHeads;
|
||||||
|
uint8_t sectorsPerTrack;
|
||||||
|
|
||||||
|
// FAT parameters
|
||||||
|
uint16_t reservedSectors;
|
||||||
|
uint8_t sectorsPerCluster;
|
||||||
|
uint32_t fatStart;
|
||||||
|
uint32_t fatSize;
|
||||||
|
uint32_t dataStart;
|
||||||
|
if (!card.begin((ESP_SD_CS_PIN == -1)?SS:ESP_SD_CS_PIN, SD_SCK_HZ(F_CPU/_spi_speed_divider))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cardSizeBlocks = card.cardSize();
|
||||||
|
if (cardSizeBlocks == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
|
||||||
|
if (output) {
|
||||||
|
String s = "Capacity detected :" + String((1.048576*cardCapacityMB)/1024) + "GB";
|
||||||
|
output->printMSG(s.c_str());
|
||||||
|
}
|
||||||
|
if (!eraseCard(card, cache, cardSizeBlocks, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formatCard(dataStart, card, cache, numberOfHeads,
|
||||||
|
sectorsPerTrack, cardSizeBlocks,
|
||||||
|
sectorsPerCluster, relSector, partSize, partType,
|
||||||
|
fatSize, fatStart, cardCapacityMB, reservedSectors,output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,10 +146,441 @@ uint64_t ESP_SD::freeBytes()
|
|||||||
return volFree * blocks * 512;
|
return volFree * blocks * 512;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ESP_SD::format()
|
// strings needed in file system structures
|
||||||
|
#define noName "NO NAME "
|
||||||
|
#define fat16str "FAT16 "
|
||||||
|
#define fat32str "FAT32 "
|
||||||
|
// constants for file system structure
|
||||||
|
#define BU16 128
|
||||||
|
#define BU32 8192
|
||||||
|
#define ERASE_SIZE 262144L;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// write cached block to the card
|
||||||
|
uint8_t writeCache(uint32_t lbn, Sd2Card & card, cache_t & cache)
|
||||||
{
|
{
|
||||||
//not available yet
|
return card.writeBlock(lbn, cache.data);
|
||||||
//SDFat has a feature for this
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// initialize appropriate sizes for SD capacity
|
||||||
|
bool initSizes(uint32_t cardCapacityMB, uint8_t & sectorsPerCluster, uint8_t & numberOfHeads, uint8_t & sectorsPerTrack)
|
||||||
|
{
|
||||||
|
if (cardCapacityMB <= 6) {
|
||||||
|
return false;
|
||||||
|
} else if (cardCapacityMB <= 16) {
|
||||||
|
sectorsPerCluster = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
sectorsPerCluster = 4;
|
||||||
|
} else if (cardCapacityMB <= 64) {
|
||||||
|
sectorsPerCluster = 8;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
sectorsPerCluster = 16;
|
||||||
|
} else if (cardCapacityMB <= 1024) {
|
||||||
|
sectorsPerCluster = 32;
|
||||||
|
} else if (cardCapacityMB <= 32768) {
|
||||||
|
sectorsPerCluster = 64;
|
||||||
|
} else {
|
||||||
|
// SDXC cards
|
||||||
|
sectorsPerCluster = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set fake disk geometry
|
||||||
|
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
|
||||||
|
|
||||||
|
if (cardCapacityMB <= 16) {
|
||||||
|
numberOfHeads = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
numberOfHeads = 4;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
numberOfHeads = 8;
|
||||||
|
} else if (cardCapacityMB <= 504) {
|
||||||
|
numberOfHeads = 16;
|
||||||
|
} else if (cardCapacityMB <= 1008) {
|
||||||
|
numberOfHeads = 32;
|
||||||
|
} else if (cardCapacityMB <= 2016) {
|
||||||
|
numberOfHeads = 64;
|
||||||
|
} else if (cardCapacityMB <= 4032) {
|
||||||
|
numberOfHeads = 128;
|
||||||
|
} else {
|
||||||
|
numberOfHeads = 255;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// zero cache and optionally set the sector signature
|
||||||
|
void clearCache(uint8_t addSig, cache_t & cache)
|
||||||
|
{
|
||||||
|
memset(&cache, 0, sizeof(cache));
|
||||||
|
if (addSig) {
|
||||||
|
cache.mbr.mbrSig0 = BOOTSIG0;
|
||||||
|
cache.mbr.mbrSig1 = BOOTSIG1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// zero FAT and root dir area on SD
|
||||||
|
bool clearFatDir(uint32_t bgn, uint32_t count, Sd2Card & card, cache_t & cache, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
clearCache(false, cache);
|
||||||
|
if (!card.writeStart(bgn, count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if ((i & 0XFF) == 0) {
|
||||||
|
if (output) {
|
||||||
|
output->print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!card.writeData(cache.data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!card.writeStop()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return cylinder number for a logical block number
|
||||||
|
uint16_t lbnToCylinder(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return lbn / (numberOfHeads * sectorsPerTrack);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return head number for a logical block number
|
||||||
|
uint8_t lbnToHead(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// return sector number for a logical block number
|
||||||
|
uint8_t lbnToSector(uint32_t lbn, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
return (lbn % sectorsPerTrack) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// format and write the Master Boot Record
|
||||||
|
bool writeMbr(Sd2Card & card, cache_t & cache, uint8_t partType, uint32_t relSector, uint32_t partSize, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||||
|
{
|
||||||
|
clearCache(true, cache);
|
||||||
|
part_t* p = cache.mbr.part;
|
||||||
|
p->boot = 0;
|
||||||
|
uint16_t c = lbnToCylinder(relSector, numberOfHeads, sectorsPerTrack);
|
||||||
|
if (c > 1023) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p->beginCylinderHigh = c >> 8;
|
||||||
|
p->beginCylinderLow = c & 0XFF;
|
||||||
|
p->beginHead = lbnToHead(relSector, numberOfHeads, sectorsPerTrack);
|
||||||
|
p->beginSector = lbnToSector(relSector, sectorsPerTrack);
|
||||||
|
p->type = partType;
|
||||||
|
uint32_t endLbn = relSector + partSize - 1;
|
||||||
|
c = lbnToCylinder(endLbn,numberOfHeads, sectorsPerTrack);
|
||||||
|
if (c <= 1023) {
|
||||||
|
p->endCylinderHigh = c >> 8;
|
||||||
|
p->endCylinderLow = c & 0XFF;
|
||||||
|
p->endHead = lbnToHead(endLbn, numberOfHeads, sectorsPerTrack);
|
||||||
|
p->endSector = lbnToSector(endLbn, sectorsPerTrack);
|
||||||
|
} else {
|
||||||
|
// Too big flag, c = 1023, h = 254, s = 63
|
||||||
|
p->endCylinderHigh = 3;
|
||||||
|
p->endCylinderLow = 255;
|
||||||
|
p->endHead = 254;
|
||||||
|
p->endSector = 63;
|
||||||
|
}
|
||||||
|
p->firstSector = relSector;
|
||||||
|
p->totalSectors = partSize;
|
||||||
|
if (!writeCache(0, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// generate serial number from card size and micros since boot
|
||||||
|
uint32_t volSerialNumber(uint32_t cardSizeBlocks)
|
||||||
|
{
|
||||||
|
return (cardSizeBlocks << 8) + micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
// format the SD as FAT16
|
||||||
|
bool makeFat16(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t nc;
|
||||||
|
for (dataStart = 2 * BU16;; dataStart += BU16) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 255)/256;
|
||||||
|
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
|
||||||
|
if (dataStart < r) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
relSector = dataStart - r + BU16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// check valid cluster count for FAT16 volume
|
||||||
|
if (nc < 4085 || nc >= 65525) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reservedSectors = 1;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
|
||||||
|
if (partSize < 32680) {
|
||||||
|
partType = 0X01;
|
||||||
|
} else if (partSize < 65536) {
|
||||||
|
partType = 0X04;
|
||||||
|
} else {
|
||||||
|
partType = 0X06;
|
||||||
|
}
|
||||||
|
// write MBR
|
||||||
|
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
fat_boot_t* pb = &cache.fbs;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->rootDirEntryCount = 512;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerFat16 = fatSize;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
|
||||||
|
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||||
|
memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector
|
||||||
|
if (!writeCache(relSector, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// clear FAT and root directory
|
||||||
|
clearFatDir(fatStart, dataStart - fatStart, card, cache, output);
|
||||||
|
clearCache(false, cache);
|
||||||
|
cache.fat16[0] = 0XFFF8;
|
||||||
|
cache.fat16[1] = 0XFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart, card, cache)
|
||||||
|
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format the SD as FAT32
|
||||||
|
bool makeFat32(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t nc;
|
||||||
|
relSector = BU32;
|
||||||
|
for (dataStart = 2 * BU32;; dataStart += BU32) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 127)/128;
|
||||||
|
uint32_t r = relSector + 9 + 2 * fatSize;
|
||||||
|
if (dataStart >= r) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// error if too few clusters in FAT32 volume
|
||||||
|
if (nc < 65525) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reservedSectors = dataStart - relSector - 2 * fatSize;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + dataStart - relSector;
|
||||||
|
// type depends on address of end sector
|
||||||
|
// max CHS has lbn = 16450560 = 1024*255*63
|
||||||
|
if ((relSector + partSize) <= 16450560) {
|
||||||
|
// FAT32
|
||||||
|
partType = 0X0B;
|
||||||
|
} else {
|
||||||
|
// FAT32 with INT 13
|
||||||
|
partType = 0X0C;
|
||||||
|
}
|
||||||
|
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
|
||||||
|
fat32_boot_t* pb = &cache.fbs32;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->sectorsPerFat32 = fatSize;
|
||||||
|
pb->fat32RootCluster = 2;
|
||||||
|
pb->fat32FSInfo = 1;
|
||||||
|
pb->fat32BackBootBlock = 6;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
|
||||||
|
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||||
|
memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector and backup
|
||||||
|
if (!writeCache(relSector, card, cache)
|
||||||
|
|| !writeCache(relSector + 6, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true, cache);
|
||||||
|
// write extra boot area and backup
|
||||||
|
if (!writeCache(relSector + 2, card, cache)
|
||||||
|
|| !writeCache(relSector + 8, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fat32_fsinfo_t* pf = &cache.fsinfo;
|
||||||
|
pf->leadSignature = FSINFO_LEAD_SIG;
|
||||||
|
pf->structSignature = FSINFO_STRUCT_SIG;
|
||||||
|
pf->freeCount = 0XFFFFFFFF;
|
||||||
|
pf->nextFree = 0XFFFFFFFF;
|
||||||
|
// write FSINFO sector and backup
|
||||||
|
if (!writeCache(relSector + 1, card, cache)
|
||||||
|
|| !writeCache(relSector + 7, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster, card, cache, output);
|
||||||
|
clearCache(false, cache);
|
||||||
|
cache.fat32[0] = 0x0FFFFFF8;
|
||||||
|
cache.fat32[1] = 0x0FFFFFFF;
|
||||||
|
cache.fat32[2] = 0x0FFFFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart, card, cache)
|
||||||
|
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eraseCard(Sd2Card & card, cache_t & cache, uint32_t cardSizeBlocks, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
uint32_t firstBlock = 0;
|
||||||
|
uint32_t lastBlock;
|
||||||
|
uint16_t n = 0;
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Erasing ", false);
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
lastBlock = firstBlock + ERASE_SIZE - 1;
|
||||||
|
if (lastBlock >= cardSizeBlocks) {
|
||||||
|
lastBlock = cardSizeBlocks - 1;
|
||||||
|
}
|
||||||
|
if (!card.erase(firstBlock, lastBlock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->print(".");
|
||||||
|
}
|
||||||
|
firstBlock += ERASE_SIZE;
|
||||||
|
} while (firstBlock < cardSizeBlocks);
|
||||||
|
|
||||||
|
if (!card.readBlock(0, cache.data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->printLN("");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool formatCard(uint32_t & dataStart, Sd2Card & card,
|
||||||
|
cache_t & cache, uint8_t numberOfHeads,
|
||||||
|
uint8_t sectorsPerTrack, uint32_t cardSizeBlocks,
|
||||||
|
uint8_t sectorsPerCluster, uint32_t &relSector,
|
||||||
|
uint32_t partSize, uint8_t & partType,
|
||||||
|
uint32_t &fatSize, uint32_t &fatStart,
|
||||||
|
uint32_t cardCapacityMB, uint16_t reservedSectors, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
initSizes(cardCapacityMB, sectorsPerCluster, numberOfHeads, sectorsPerTrack);
|
||||||
|
if (card.type() != SD_CARD_TYPE_SDHC) {
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Formating FAT16 ");
|
||||||
|
}
|
||||||
|
if(!makeFat16(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (output) {
|
||||||
|
output->printMSG("Formating FAT32 ", false);
|
||||||
|
}
|
||||||
|
if(!makeFat32(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (output) {
|
||||||
|
output->printLN("");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_SD::format(ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
if (ESP_SD::getState(true) == ESP_SDCARD_IDLE) {
|
||||||
|
Sd2Card card;
|
||||||
|
uint32_t cardSizeBlocks;
|
||||||
|
uint32_t cardCapacityMB;
|
||||||
|
// cache for SD block
|
||||||
|
cache_t cache;
|
||||||
|
|
||||||
|
// MBR information
|
||||||
|
uint8_t partType;
|
||||||
|
uint32_t relSector;
|
||||||
|
uint32_t partSize;
|
||||||
|
|
||||||
|
// Fake disk geometry
|
||||||
|
uint8_t numberOfHeads;
|
||||||
|
uint8_t sectorsPerTrack;
|
||||||
|
|
||||||
|
// FAT parameters
|
||||||
|
uint16_t reservedSectors;
|
||||||
|
uint8_t sectorsPerCluster;
|
||||||
|
uint32_t fatStart;
|
||||||
|
uint32_t fatSize;
|
||||||
|
uint32_t dataStart;
|
||||||
|
if (!card.begin((ESP_SD_CS_PIN == -1)?SS:ESP_SD_CS_PIN, SD_SCK_MHZ(FREQMZ/_spi_speed_divider))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cardSizeBlocks = card.cardSize();
|
||||||
|
if (cardSizeBlocks == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
|
||||||
|
if (output) {
|
||||||
|
String s = "Capacity detected :" + String((1.048576*cardCapacityMB)/1024) + "GB";
|
||||||
|
output->printMSG(s.c_str());
|
||||||
|
}
|
||||||
|
if (!eraseCard(card, cache, cardSizeBlocks, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formatCard(dataStart, card, cache, numberOfHeads,
|
||||||
|
sectorsPerTrack, cardSizeBlocks,
|
||||||
|
sectorsPerCluster, relSector, partSize, partType,
|
||||||
|
fatSize, fatStart, cardCapacityMB, reservedSectors,output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +88,12 @@ uint64_t ESP_SD::freeBytes()
|
|||||||
return (SD_MMC.totalBytes() - SD_MMC.usedBytes());
|
return (SD_MMC.totalBytes() - SD_MMC.usedBytes());
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ESP_SD::format()
|
bool ESP_SD::format(ESP3DOutput * output)
|
||||||
{
|
{
|
||||||
//not available yet
|
//not available yet
|
||||||
|
if (output) {
|
||||||
|
output->printERROR ("Not implemented!");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user