# SCHC_FTHR
## functions:
## Background Information:
### FATFS
FATFS(File Allocation Table File System)是一种文件系统,通常用于嵌入式系统和存储设备(如SD卡、USB闪存驱动器等)上。FATFS最早由Microsoft开发,用于DOS和Windows操作系统,因此它的名字中包含"FAT",代表文件分配表(File Allocation Table)。FATFS是一种简单的文件系统,易于实现和跨平台使用,因此在许多嵌入式系统中得到了广泛的应用。
FATFS的主要特点包括:
简单性: FATFS采用了一种相对简单的文件组织方式,文件和目录的信息存储在文件分配表(FAT)中,这使得它易于实现和维护。
兼容性: FATFS文件系统通常能够与不同操作系统和平台兼容,因为它是一种开放标准,并且已经得到了广泛的支持和实现。
适用于闪存设备: FATFS适用于闪存设备,这些设备通常需要一种轻量级的文件系统来管理存储。
可读性: FATFS文件系统通常易于人类阅读,这使得它在调试和维护方面具有优势。
尽管FATFS在许多嵌入式系统中得到广泛使用,但也有一些局限性,例如不支持文件权限和加密等高级功能。在某些应用场景中,可能需要更复杂的文件系统,如FAT32、exFAT或NTFS,以满足更高级的需求。但对于许多嵌入式系统来说,FATFS是一种简单而有效的选择。
### FIL
`FIL` 是 FatFs 文件系统库中定义的一个数据结构,用于表示打开的文件。`FIL` 结构用于跟踪文件的状态、位置、属性以及其他与文件相关的信息。在使用 FatFs 文件系统库时,你可以使用 `FIL` 结构来执行各种文件操作,如打开、读取、写入、关闭等。
以下是 `FIL` 结构的一些常见成员:
1. `fp`:表示文件当前的读/写位置(文件指针),可以用于定位文件中的数据。
2. `obj`:包含与文件相关的一些对象信息,如文件名、文件大小、文件属性等。
3. `flag`:表示文件的状态标志,例如文件是否被打开、文件是否被修改等。
4. `err`:表示最后一次文件操作的错误代码,用于检查文件操作是否成功。
`FIL` 结构的具体定义和成员可能会因不同的 FatFs 版本或实现而有所不同,但通常它包含了上述成员以及其他与文件操作相关的信息。在使用 FatFs 文件系统库时,你会经常看到 `FIL` 结构的使用,以便进行文件的读写和管理。
## example code
``` cpp
/******************************************************************************
* Copyright (C) 2023 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*
******************************************************************************/
/**
* @file main.c
* @brief read and write sdhc
* @details This example uses the sdhc and ffat to read/write the file system on
* an SD card. The Fat library used supports long filenames (see ffconf.h)
* the max length is 256 characters.
*
* You must connect an sd card to the sd card slot.
*/
/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "board.h"
#include "mxc_delay.h"
#include "mxc_device.h"
#include "gpio.h"
#include "uart.h"
#include "ff.h"
#ifdef BOARD_EVKIT_V1
#warning This example is not supported by the MAX78000EVKIT.
#endif
/***** Definitions *****/
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define MAXLEN 256
/***** Globals *****/
FATFS *fs; //FFat Filesystem Object
FATFS fs_obj;
FIL file; //FFat File Object
FRESULT err; //FFat Result (Struct)
FILINFO fno; //FFat File Information Object
DIR dir; //FFat Directory Object
TCHAR message[MAXLEN], directory[MAXLEN], cwd[MAXLEN], filename[MAXLEN], volume_label[24],
volume = '0';
TCHAR *FF_ERRORS[20];
DWORD clusters_free = 0, sectors_free = 0, sectors_total = 0, volume_sn = 0;
UINT bytes_written = 0, bytes_read = 0, mounted = 0;
BYTE work[4096];
static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
mxc_gpio_cfg_t SDPowerEnablePin = { MXC_GPIO1, MXC_GPIO_PIN_12, MXC_GPIO_FUNC_OUT,
MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO };
/***** FUNCTIONS *****/
void generateMessage(unsigned length)
{
for (int i = 0; i < length; i++) {
/*Generate some random data to put in file*/
message[i] = charset[rand() % (sizeof(charset) - 1)];
}
}
int mount()
{
fs = &fs_obj;
if ((err = f_mount(fs, "", 1)) != FR_OK) { //Mount the default drive to fs now
printf("Error opening SD card: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
} else {
printf("SD card mounted.\n");
mounted = 1;
}
f_getcwd(cwd, sizeof(cwd)); //Set the Current working directory
return err;
}
int umount()
{
if ((err = f_mount(NULL, "", 0)) != FR_OK) { //Unmount the default drive from its mount point
printf("Error unmounting volume: %s\n", FF_ERRORS[err]);
} else {
printf("SD card unmounted.\n");
mounted = 0;
}
return err;
}
int formatSDHC()
{
printf("\n\n*****THE DRIVE WILL BE FORMATTED IN 5 SECONDS*****\n");
printf("**************PRESS ANY KEY TO ABORT**************\n\n");
MXC_UART_ClearRXFIFO(MXC_UART0);
MXC_Delay(MSEC(5000));
if (MXC_UART_GetRXFIFOAvailable(MXC_UART0) > 0) {
return E_ABORT;
}
printf("FORMATTING DRIVE\n");
if ((err = f_mkfs("", FM_ANY, 0, work, sizeof(work))) !=
FR_OK) { //Format the default drive to FAT32
printf("Error formatting SD card: %s\n", FF_ERRORS[err]);
} else {
printf("Drive formatted.\n");
}
mount();
if ((err = f_setlabel("MAXIM")) != FR_OK) {
printf("Error setting drive label: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
}
umount();
return err;
}
int getSize()
{
if (!mounted) {
mount();
}
if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) {
printf("Error finding free size of card: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
}
sectors_total = (fs->n_fatent - 2) * fs->csize;
sectors_free = clusters_free * fs->csize;
printf("Disk Size: %u bytes\n", sectors_total / 2);
printf("Available: %u bytes\n", sectors_free / 2);
return err;
}
int ls()
{
if (!mounted) {
mount();
}
printf("Listing Contents of %s - \n", cwd);
if ((err = f_opendir(&dir, cwd)) == FR_OK) {
while (1) {
err = f_readdir(&dir, &fno);
if (err != FR_OK || fno.fname[0] == 0) {
break;
}
printf("%s/%s", cwd, fno.fname);
if (fno.fattrib & AM_DIR) {
printf("/");
}
printf("\n");
}
f_closedir(&dir);
} else {
printf("Error opening directory!\n");
return err;
}
printf("\nFinished listing contents\n");
return err;
}
int createFile()
{
unsigned int length = 128;
if (!mounted) {
mount();
}
printf("Enter the name of the text file: \n");
scanf("%255s", filename);
printf("Enter the length of the file: (%d max)\n", MAXLEN);
scanf("%d", &length);
if (length > MAXLEN) {
printf("Error. File size limit for this example is %d bytes.\n", MAXLEN);
return FR_INVALID_PARAMETER;
}
printf("Creating file %s with length %d\n", filename, length);
if ((err = f_open(&file, (const TCHAR *)filename, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) {
printf("Error opening file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("File opened!\n");
generateMessage(length);
if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) {
printf("Error writing file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("%d bytes written to file!\n", bytes_written);
if ((err = f_close(&file)) != FR_OK) {
printf("Error closing file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("File Closed!\n");
return err;
}
int appendFile()
{
unsigned int length = 0;
if (!mounted) {
mount();
}
printf("Enter name of file to append: \n");
scanf("%255s", filename);
printf("Enter length of random data to append: (%d max)\n", MAXLEN);
scanf("%d", &length);
if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) {
printf("File %s doesn't exist!\n", (const TCHAR *)filename);
return err;
}
if (length > MAXLEN) {
printf("Error. Size limit for this example is %d bytes.\n", MAXLEN);
return FR_INVALID_PARAMETER;
}
if ((err = f_open(&file, (const TCHAR *)filename, FA_OPEN_APPEND | FA_WRITE)) != FR_OK) {
printf("Error opening file %s\n", FF_ERRORS[err]);
return err;
}
printf("File opened!\n");
generateMessage(length);
if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) {
printf("Error writing file: %s\n", FF_ERRORS[err]);
return err;
}
printf("%d bytes written to file\n", bytes_written);
if ((err = f_close(&file)) != FR_OK) {
printf("Error closing file: %s\n", FF_ERRORS[err]);
return err;
}
printf("File closed.\n");
return err;
}
int mkdir()
{
if (!mounted) {
mount();
}
printf("Enter directory name: \n");
scanf("%255s", directory);
err = f_stat((const TCHAR *)directory, &fno);
if (err == FR_NO_FILE) {
printf("Creating directory...\n");
if ((err = f_mkdir((const TCHAR *)directory)) != FR_OK) {
printf("Error creating directory: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
} else {
printf("Directory %s created.\n", directory);
}
} else {
printf("Directory already exists.\n");
}
return err;
}
int cd()
{
if (!mounted) {
mount();
}
printf("Directory to change into: \n");
scanf("%255s", directory);
if ((err = f_stat((const TCHAR *)directory, &fno)) == FR_NO_FILE) {
printf("Directory doesn't exist (Did you mean mkdir?)\n");
return err;
}
if ((err = f_chdir((const TCHAR *)directory)) != FR_OK) {
printf("Error in chdir: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("Changed to %s\n", directory);
f_getcwd(cwd, sizeof(cwd));
return err;
}
int delete ()
{
if (!mounted) {
mount();
}
printf("File or directory to delete (always recursive!)\n");
scanf("%255s", filename);
if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) {
printf("File or directory doesn't exist\n");
return err;
}
if ((err = f_unlink(filename)) != FR_OK) {
printf("Error deleting file\n");
return err;
}
printf("Deleted file %s\n", filename);
return err;
}
int example()
{
unsigned int length = 256;
if ((err = formatSDHC()) != FR_OK) {
printf("Error Formatting SD Card: %s\n", FF_ERRORS[err]);
return err;
}
//open SD Card
if ((err = mount()) != FR_OK) {
printf("Error opening SD Card: %s\n", FF_ERRORS[err]);
return err;
}
printf("SD Card Opened!\n");
if ((err = f_setlabel("MAXIM")) != FR_OK) {
printf("Error setting drive label: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) {
printf("Error finding free size of card: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
if ((err = f_getlabel(&volume, volume_label, &volume_sn)) != FR_OK) {
printf("Error reading drive label: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
if ((err = f_open(&file, "0:HelloWorld.txt", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) {
printf("Error opening file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("File opened!\n");
generateMessage(length);
if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) {
printf("Error writing file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("%d bytes written to file!\n", bytes_written);
if ((err = f_close(&file)) != FR_OK) {
printf("Error closing file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("File Closed!\n");
if ((err = f_chmod("HelloWorld.txt", 0, AM_RDO | AM_ARC | AM_SYS | AM_HID)) != FR_OK) {
printf("Error in chmod: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
err = f_stat("MaximSDHC", &fno);
if (err == FR_NO_FILE) {
printf("Creating Directory...\n");
if ((err = f_mkdir("MaximSDHC")) != FR_OK) {
printf("Error creating directory: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
}
printf("Renaming File...\n");
if ((err = f_rename("0:HelloWorld.txt", "0:MaximSDHC/HelloMaxim.txt")) !=
FR_OK) { //cr: clearify 0:file notation
printf("Error moving file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
if ((err = f_chdir("/MaximSDHC")) != FR_OK) {
printf("Error in chdir: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("Attempting to read back file...\n");
if ((err = f_open(&file, "HelloMaxim.txt", FA_READ)) != FR_OK) {
printf("Error opening file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
if ((err = f_read(&file, &message, bytes_written, &bytes_read)) != FR_OK) {
printf("Error reading file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("Read Back %d bytes\n", bytes_read);
printf("Message: ");
printf("%s", message);
printf("\n");
if ((err = f_close(&file)) != FR_OK) {
printf("Error closing file: %s\n", FF_ERRORS[err]);
f_mount(NULL, "", 0);
return err;
}
printf("File Closed!\n");
//unmount SD Card
//f_mount(fs, "", 0);
if ((err = f_mount(NULL, "", 0)) != FR_OK) {
printf("Error unmounting volume: %s\n", FF_ERRORS[err]);
return err;
}
return 0;
}
void waitCardInserted()
{
// On the MAX78000FTHR board, P0.12 will be pulled low when a card is inserted.
mxc_gpio_cfg_t cardDetect;
cardDetect.port = MXC_GPIO0;
cardDetect.mask = MXC_GPIO_PIN_12;
cardDetect.func = MXC_GPIO_FUNC_IN;
cardDetect.pad = MXC_GPIO_PAD_NONE;
cardDetect.vssel = MXC_GPIO_VSSEL_VDDIOH;
MXC_GPIO_Config(&cardDetect);
// Exit function if card is already inserted
if (MXC_GPIO_InGet(MXC_GPIO0, MXC_GPIO_PIN_12) == 0) {
return;
}
printf("Insert SD card to continue.\n");
while (MXC_GPIO_InGet(MXC_GPIO0, MXC_GPIO_PIN_12) != 0) {
// Spin waiting for card to be inserted.
}
// Card has been detected, exit the function.
}
/******************************************************************************/
int main(void)
{
FF_ERRORS[0] = "FR_OK";
FF_ERRORS[1] = "FR_DISK_ERR";
FF_ERRORS[2] = "FR_INT_ERR";
FF_ERRORS[3] = "FR_NOT_READY";
FF_ERRORS[4] = "FR_NO_FILE";
FF_ERRORS[5] = "FR_NO_PATH";
FF_ERRORS[6] = "FR_INVLAID_NAME";
FF_ERRORS[7] = "FR_DENIED";
FF_ERRORS[8] = "FR_EXIST";
FF_ERRORS[9] = "FR_INVALID_OBJECT";
FF_ERRORS[10] = "FR_WRITE_PROTECTED";
FF_ERRORS[11] = "FR_INVALID_DRIVE";
FF_ERRORS[12] = "FR_NOT_ENABLED";
FF_ERRORS[13] = "FR_NO_FILESYSTEM";
FF_ERRORS[14] = "FR_MKFS_ABORTED";
FF_ERRORS[15] = "FR_TIMEOUT";
FF_ERRORS[16] = "FR_LOCKED";
FF_ERRORS[17] = "FR_NOT_ENOUGH_CORE";
FF_ERRORS[18] = "FR_TOO_MANY_OPEN_FILES";
FF_ERRORS[19] = "FR_INVALID_PARAMETER";
srand(12347439);
int run = 1, input = -1;
printf("\n\n***** " TOSTRING(TARGET) " SDHC FAT Filesystem Example *****\n");
waitCardInserted();
printf("Card inserted.\n");
while (run) {
f_getcwd(cwd, sizeof(cwd));
printf("\nChoose one of the following options: \n");
printf("0. Find the Size of the SD Card and Free Space\n");
printf("1. Format the Card\n");
printf("2. Manually Mount Card\n");
printf("3. List Contents of Current Directory\n");
printf("4. Create a Directory\n");
printf("5. Move into a Directory (cd)\n");
printf("6. Create a File of Random Data\n");
printf("7. Add Random Data to an Existing File\n");
printf("8. Delete a File\n");
printf("9. Format Card and Run Exmaple of FatFS Operations\n");
printf("10. Unmount Card and Quit\n");
printf("%s>>", cwd);
input = -1;
scanf("%d", &input);
printf("%d\n", input);
err = 0;
switch (input) {
case 0:
getSize();
break;
case 1:
formatSDHC();
break;
case 3:
ls();
break;
case 6:
createFile();
break;
case 7:
appendFile();
break;
case 4:
mkdir();
break;
case 5:
cd();
break;
case 9:
example();
break;
case 10:
umount();
run = 0;
break;
case 2:
mount();
break;
case 8:
delete ();
break;
default:
printf("Invalid Selection %d!\n", input);
err = -1;
break;
}
if (err >= 0 && err <= 20) {
printf("Function Returned with code: %s\n", FF_ERRORS[err]);
} else {
printf("Function Returned with code: %d\n", err);
}
MXC_Delay(MSEC(500));
}
printf("End of example, please try to read the card.\n");
return 0;
}
```