From 930680f215dae56ea7f79e2ca627876e378b493a Mon Sep 17 00:00:00 2001 From: imi415 Date: Fri, 10 Jun 2022 01:26:20 +0800 Subject: [PATCH] Working FatFS. --- .gitmodules | 2 +- CMakeLists.txt | 9 ++ MK60DN512xxx10.mex | 28 +++- SDK | 2 +- board/clock_config.c | 22 ++- board/pin_mux.c | 26 ++++ include/ffconf.h | 301 +++++++++++++++++++++++++++++++++++++ include/sdhc_helpers.h | 6 + lib/{FatFS/fatfs => FatFS} | 0 src/fatfs_diskio.c | 143 ++++++++++++++++++ src/ip_stack_helpers.c | 5 +- src/main.c | 28 +++- src/sdhc_helpers.c | 185 +++++++++++++++++++++++ 13 files changed, 740 insertions(+), 17 deletions(-) create mode 100644 include/ffconf.h create mode 100644 include/sdhc_helpers.h rename lib/{FatFS/fatfs => FatFS} (100%) create mode 100644 src/fatfs_diskio.c create mode 100644 src/sdhc_helpers.c diff --git a/.gitmodules b/.gitmodules index ffc4f7b..c8e2b7b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,5 +17,5 @@ path = lib/LwIP/lwip url = https://git.savannah.nongnu.org/git/lwip.git [submodule "lib/FatFS/fatfs"] - path = lib/FatFS/fatfs + path = lib/FatFS url = https://git.minori.work/Embedded_SDK/FatFS.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 33988d7..582fcef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,8 @@ set(TARGET_SOURCES "SDK/devices/MK60D10/utilities/fsl_notifier.c" "SDK/devices/MK60D10/gcc/startup_MK60D10.S" "SDK/devices/MK60D10/system_MK60D10.c" + "SDK/middleware/sdmmc_2.1.2/src/fsl_sd.c" + "SDK/middleware/sdmmc_2.1.2/src/fsl_sdmmc.c" "board/board.c" "board/clock_config.c" "board/peripherals.c" @@ -62,10 +64,12 @@ set(TARGET_SOURCES "lib/LwIP/port/lwip_helpers.c" "lib/LwIP/port/sys_arch.c" "src/ethernetif.c" + "src/fatfs_diskio.c" "src/freertos_helpers.c" "src/fsl_phy.c" "src/ip_stack_helpers.c" "src/main.c" + "src/sdhc_helpers.c" "src/syscalls.c" "src/system_utilities.c" ) @@ -82,6 +86,7 @@ set(TARGET_C_INCLUDES "SDK/devices/MK60D10" "SDK/devices/MK60D10/drivers" "SDK/devices/MK60D10/utilities" + "SDK/middleware/sdmmc_2.1.2/inc" "board" "include" ) @@ -91,6 +96,7 @@ set(TARGET_LIBS "freertos_kernel" "lwip" "mbedtls" + "fatfs" ) # Shared library and linker script search paths @@ -129,6 +135,9 @@ add_subdirectory(lib/LwIP) add_subdirectory(lib/MbedTLS) +set(FATFS_CONFIG_DIRECTORY "${CMAKE_SOURCE_DIR}/include" CACHE STRING "") +add_subdirectory(lib/FatFS) + # Shared sources, includes and definitions add_compile_definitions(${TARGET_C_DEFINES}) include_directories(${TARGET_C_INCLUDES}) diff --git a/MK60DN512xxx10.mex b/MK60DN512xxx10.mex index f9b2c59..c2580af 100644 --- a/MK60DN512xxx10.mex +++ b/MK60DN512xxx10.mex @@ -52,6 +52,11 @@ true + + + true + + true @@ -127,6 +132,12 @@ + + + + + + @@ -190,18 +201,20 @@ - + - - + + + + @@ -213,9 +226,12 @@ - - - + + + + + + true diff --git a/SDK b/SDK index 84eb98d..ede33dc 160000 --- a/SDK +++ b/SDK @@ -1 +1 @@ -Subproject commit 84eb98d82ff012cfc45852b0589e0b11024d16e4 +Subproject commit ede33dcf057746da396088a4d9dcea87b02f3b25 diff --git a/board/clock_config.c b/board/clock_config.c index e6f39df..c78a493 100644 --- a/board/clock_config.c +++ b/board/clock_config.c @@ -55,6 +55,7 @@ processor_version: 11.0.1 #define SIM_ENET_RMII_CLK_SEL_EXTAL_CLK 0U /*!< SDHC clock select: Core/system clock */ #define SIM_OSC32KSEL_OSC32KCLK_CLK 0U /*!< OSC32KSEL select: OSC32KCLK clock */ #define SIM_PLLFLLSEL_MCGFLLCLK_CLK 0U /*!< PLLFLL select: MCGFLLCLK clock */ +#define SIM_SDHC_CLK_SEL_OSCERCLK_CLK 2U /*!< SDHC clock select: OSCERCLK clock */ /******************************************************************************* * Variables @@ -130,17 +131,19 @@ void BOARD_InitBootClocks(void) name: BOARD_BootClockRUN called_from_default_init: true outputs: -- {id: Bus_clock.outFreq, value: 50 MHz} +- {id: Bus_clock.outFreq, value: 12.5 MHz} - {id: Core_clock.outFreq, value: 100 MHz} -- {id: Flash_clock.outFreq, value: 25 MHz} -- {id: FlexBus_clock.outFreq, value: 50 MHz} +- {id: Flash_clock.outFreq, value: 12.5 MHz} +- {id: FlexBus_clock.outFreq, value: 12.5 MHz} - {id: LPO_clock.outFreq, value: 1 kHz} - {id: MCGFFCLK.outFreq, value: 39.0625 kHz} - {id: OSCERCLK.outFreq, value: 50 MHz} - {id: RMIICLK.outFreq, value: 50 MHz} +- {id: SDHCCLK.outFreq, value: 50 MHz} - {id: System_clock.outFreq, value: 100 MHz} settings: - {id: MCGMode, value: PEE} +- {id: MCG.FLL_mul.scale, value: '640', locked: true} - {id: MCG.FRDIV.scale, value: '1280'} - {id: MCG.IREFS.sel, value: MCG.FRDIV} - {id: MCG.PLLS.sel, value: MCG.PLL} @@ -152,9 +155,12 @@ settings: - {id: RMIISrcConfig, value: 'yes'} - {id: RTC_CR_OSCE_CFG, value: Enabled} - {id: RTC_CR_OSC_CAP_LOAD_CFG, value: SC12PF} -- {id: SIM.OUTDIV2.scale, value: '2'} -- {id: SIM.OUTDIV3.scale, value: '2'} -- {id: SIM.OUTDIV4.scale, value: '4'} +- {id: SDHCClkConfig, value: 'yes'} +- {id: SIM.OUTDIV1.scale, value: '1', locked: true} +- {id: SIM.OUTDIV2.scale, value: '8'} +- {id: SIM.OUTDIV3.scale, value: '8'} +- {id: SIM.OUTDIV4.scale, value: '8'} +- {id: SIM.SDHCSRCSEL.sel, value: OSC.OSCERCLK} sources: - {id: OSC.OSC.outFreq, value: 50 MHz, enabled: true} - {id: RTC.RTC32kHz.outFreq, value: 32.768 kHz, enabled: true} @@ -185,7 +191,7 @@ const sim_clock_config_t simConfig_BOARD_BootClockRUN = { .pllFllSel = SIM_PLLFLLSEL_MCGFLLCLK_CLK, /* PLLFLL select: MCGFLLCLK clock */ .er32kSrc = SIM_OSC32KSEL_OSC32KCLK_CLK, /* OSC32KSEL select: OSC32KCLK clock */ - .clkdiv1 = 0x1130000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /2, OUTDIV3: /2, OUTDIV4: /4 */ + .clkdiv1 = 0x7770000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /8, OUTDIV3: /8, OUTDIV4: /8 */ }; const osc_config_t oscConfig_BOARD_BootClockRUN = { @@ -222,5 +228,7 @@ void BOARD_BootClockRUN(void) SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; /* Set RMII clock source. */ CLOCK_SetRmii0Clock(SIM_ENET_RMII_CLK_SEL_EXTAL_CLK); + /* Set SDHC clock source. */ + CLOCK_SetSdhc0Clock(SIM_SDHC_CLK_SEL_OSCERCLK_CLK); } diff --git a/board/pin_mux.c b/board/pin_mux.c index 811e34e..e9baae4 100644 --- a/board/pin_mux.c +++ b/board/pin_mux.c @@ -94,6 +94,12 @@ BOARD_InitPins: - {pin_num: '69', peripheral: ENET, signal: RMII_TXD1, pin_signal: ADC1_SE17/PTA17/SPI0_SIN/UART0_RTS_b/RMII0_TXD1/MII0_TXD1/I2S0_MCLK} - {pin_num: '67', peripheral: ENET, signal: rmii_txen, pin_signal: PTA15/SPI0_SCK/UART0_RX/RMII0_TXEN/MII0_TXEN/I2S0_RXD0} - {pin_num: '72', peripheral: ENET, signal: RMII_CLKIN, pin_signal: EXTAL0/PTA18/FTM0_FLT2/FTM_CLKIN0} + - {pin_num: '4', peripheral: SDHC, signal: CMD, pin_signal: ADC1_SE7a/PTE3/SPI1_SIN/UART1_RTS_b/SDHC0_CMD/SPI1_SOUT} + - {pin_num: '2', peripheral: SDHC, signal: 'D, 0', pin_signal: ADC1_SE5a/PTE1/LLWU_P0/SPI1_SOUT/UART1_RX/SDHC0_D0/I2C1_SCL/SPI1_SIN} + - {pin_num: '1', peripheral: SDHC, signal: 'D, 1', pin_signal: ADC1_SE4a/PTE0/SPI1_PCS1/UART1_TX/SDHC0_D1/I2C1_SDA/RTC_CLKOUT} + - {pin_num: '7', peripheral: SDHC, signal: 'D, 3', pin_signal: PTE4/LLWU_P2/SPI1_PCS0/UART3_TX/SDHC0_D3} + - {pin_num: '8', peripheral: SDHC, signal: 'D, 2', pin_signal: PTE5/SPI1_PCS2/UART3_RX/SDHC0_D2} + - {pin_num: '3', peripheral: SDHC, signal: DCLK, pin_signal: ADC1_SE6a/PTE2/LLWU_P1/SPI1_SCK/UART1_CTS_b/SDHC0_DCLK} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** */ /* clang-format on */ @@ -114,6 +120,8 @@ void BOARD_InitPins(void) CLOCK_EnableClock(kCLOCK_PortC); /* Port D Clock Gate Control: Clock enabled */ CLOCK_EnableClock(kCLOCK_PortD); + /* Port E Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortE); gpio_pin_config_t BUZZER_config = { .pinDirection = kGPIO_DigitalOutput, @@ -284,6 +292,24 @@ void BOARD_InitPins(void) /* PORTD9 (pin 138) is configured as FB_A17 */ PORT_SetPinMux(PORTD, 9U, kPORT_MuxAlt6); + /* PORTE0 (pin 1) is configured as SDHC0_D1 */ + PORT_SetPinMux(PORTE, 0U, kPORT_MuxAlt4); + + /* PORTE1 (pin 2) is configured as SDHC0_D0 */ + PORT_SetPinMux(PORTE, 1U, kPORT_MuxAlt4); + + /* PORTE2 (pin 3) is configured as SDHC0_DCLK */ + PORT_SetPinMux(PORTE, 2U, kPORT_MuxAlt4); + + /* PORTE3 (pin 4) is configured as SDHC0_CMD */ + PORT_SetPinMux(PORTE, 3U, kPORT_MuxAlt4); + + /* PORTE4 (pin 7) is configured as SDHC0_D3 */ + PORT_SetPinMux(PORTE, 4U, kPORT_MuxAlt4); + + /* PORTE5 (pin 8) is configured as SDHC0_D2 */ + PORT_SetPinMux(PORTE, 5U, kPORT_MuxAlt4); + SIM->SOPT2 = ((SIM->SOPT2 & /* Mask bits to zero which are setting */ (~(SIM_SOPT2_RMIISRC_MASK))) diff --git a/include/ffconf.h b/include/ffconf.h new file mode 100644 index 0000000..4a0cba8 --- /dev/null +++ b/include/ffconf.h @@ -0,0 +1,301 @@ +/*---------------------------------------------------------------------------/ +/ FatFs Functional Configurations +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 86631 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 1 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_STRFUNC 0 +#define FF_PRINT_LLI 0 +#define FF_PRINT_FLOAT 0 +#define FF_STRF_ENCODE 0 +/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). +/ +/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. +/ +/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 + makes f_printf() support floating point argument. These features want C99 or later. +/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character +/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE +/ to be read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 932 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 2 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be suffcient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk, but a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_LBA64 0 +/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) +/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ + + +#define FF_MIN_GPT 0x10000000 +/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and +/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 1 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2020 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +/* #include // O/S definitions */ +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +#define FF_SYNC_t HANDLE +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + + + +/*--- End of configuration options ---*/ diff --git a/include/sdhc_helpers.h b/include/sdhc_helpers.h new file mode 100644 index 0000000..2ac39d9 --- /dev/null +++ b/include/sdhc_helpers.h @@ -0,0 +1,6 @@ +#ifndef SDHC_HELPERS_H +#define SDHC_HELPERS_H + +int sdhc_helper_init(void); + +#endif \ No newline at end of file diff --git a/lib/FatFS/fatfs b/lib/FatFS similarity index 100% rename from lib/FatFS/fatfs rename to lib/FatFS diff --git a/src/fatfs_diskio.c b/src/fatfs_diskio.c new file mode 100644 index 0000000..e21c32f --- /dev/null +++ b/src/fatfs_diskio.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "fsl_card.h" +#include "ff.h" +#include "diskio.h" + +/******************************************************************************* + * Definitons + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/*! @brief Card descriptor */ +static sd_card_t g_sd; + +/******************************************************************************* + * Code + ******************************************************************************/ +DRESULT disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) +{ + if (kStatus_Success != SD_WriteBlocks(&g_sd, buff, sector, count)) + { + return RES_ERROR; + } + + return RES_OK; +} + +DRESULT disk_read(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) +{ + if (kStatus_Success != SD_ReadBlocks(&g_sd, buff, sector, count)) + { + return RES_ERROR; + } + + return RES_OK; +} + +DRESULT disk_ioctl(uint8_t physicalDrive, uint8_t command, void *buffer) +{ + DRESULT result = RES_OK; + + switch (command) + { + case GET_SECTOR_COUNT: + if (buffer) + { + *(uint32_t *)buffer = g_sd.blockCount; + } + else + { + result = RES_PARERR; + } + break; + case GET_SECTOR_SIZE: + if (buffer) + { + *(uint32_t *)buffer = g_sd.blockSize; + } + else + { + result = RES_PARERR; + } + break; + case GET_BLOCK_SIZE: + if (buffer) + { + *(uint32_t *)buffer = g_sd.csd.eraseSectorSize; + } + else + { + result = RES_PARERR; + } + break; + case CTRL_SYNC: + result = RES_OK; + break; + default: + result = RES_PARERR; + break; + } + + return result; +} + +DSTATUS disk_status(BYTE pdrv) +{ + return 0; +} + +DSTATUS disk_initialize(BYTE pdrv) +{ + /* Save host information. */ + g_sd.host.base = SD_HOST_BASEADDR; + g_sd.host.sourceClock_Hz = SD_HOST_CLK_FREQ; + + if (kStatus_Success != SD_Init(&g_sd)) + { + SD_Deinit(&g_sd); + memset(&g_sd, 0U, sizeof(g_sd)); + return STA_NOINIT; + } + + return 0; +} diff --git a/src/ip_stack_helpers.c b/src/ip_stack_helpers.c index 965b2b0..9c90584 100644 --- a/src/ip_stack_helpers.c +++ b/src/ip_stack_helpers.c @@ -1,5 +1,8 @@ #include +/* Device drivers */ +#include "fsl_sysmpu.h" + /* FreeRTOS */ #include "FreeRTOS.h" #include "task.h" @@ -86,7 +89,7 @@ static void ip_stack_enable_sntp(void) { void ip_stack_setup(void) { ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw; - SYSMPU->CESR &= ~(SYSMPU_CESR_VLD_MASK); /* Disable MPU */ + SYSMPU_Enable(SYSMPU, false); tcpip_init(NULL, NULL); diff --git a/src/main.c b/src/main.c index f4f7454..bf5244d 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,9 @@ #include #include +/* SDK drivers */ +#include "fsl_sdhc.h" + /* HW Related */ #include "board.h" #include "clock_config.h" @@ -18,6 +21,9 @@ #include "FreeRTOS.h" #include "task.h" +/* FatFS */ +#include "ff.h" + /* MbedTLS */ #include "mbedtls/aes.h" #include "mbedtls/gcm.h" @@ -39,7 +45,7 @@ int main(void) { print_hardware(); sram_test(); - mtls_selftests(1); + // mtls_selftests(1); xTaskCreate(vTaskHello, "HELLO", 256, NULL, 32, NULL); @@ -51,6 +57,26 @@ int main(void) { } static void vTaskHello(void *pvParameters) { + FATFS fs; /* File system object */ + + + + if (f_mount(&fs, "0:/", 0U)) { + PRINTF("Mount volume failed.\r\n"); + vTaskDelete(NULL); + } + + FRESULT error = f_mkdir(_T("0:/dir_1")); + + if (error) { + if (error == FR_EXIST) { + PRINTF("Directory exists.\r\n"); + } else { + PRINTF("Make directory failed.\r\n"); + vTaskDelete(NULL); + } + } + ip_stack_setup(); time_t t; diff --git a/src/sdhc_helpers.c b/src/sdhc_helpers.c new file mode 100644 index 0000000..c728234 --- /dev/null +++ b/src/sdhc_helpers.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "FreeRTOS.h" +#include "board.h" +#include "fsl_host.h" +#include "fsl_port.h" +#include "fsl_sysmpu.h" +#include "semphr.h" +#include "task.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +static sdhc_handle_t g_sdhcHandle; +static uint32_t g_sdhcAdmaTable[SDHC_ADMA_TABLE_WORDS]; +static volatile bool g_sdhcTransferSuccessFlag = true; + +static SemaphoreHandle_t s_cd_semphr = NULL; +static SemaphoreHandle_t s_transfer_semphr = NULL; + +/******************************************************************************* + * Code + ******************************************************************************/ + +static bool DetectCardByHost(void) { + if (SDHC->PRSSTAT & SDHC_PRSSTAT_CINS_MASK) { + return true; + } + + return false; +} + +/* Card detect. */ +status_t CardInsertDetect(HOST_TYPE *hostBase) { + if (DetectCardByHost() == true) { + return kStatus_Success; + } + + SDHC_EnableInterruptSignal(SDHC, kSDHC_CardDetectFlag); + + for (;;) { + if (xSemaphoreTake(s_cd_semphr, portMAX_DELAY) == pdPASS) { + if (DetectCardByHost() == true) { + break; + } + } + } + + /* Delay some time to make card stable. */ + vTaskDelay(pdMS_TO_TICKS(1000)); + + return kStatus_Success; +} + +/* Card detect pin port interrupt handler. */ +void CardInsertDetectHandle(void) { + BaseType_t task_woken; + + SDHC_DisableInterruptSignal(SDHC, kSDHC_CardDetectFlag); + + if (s_cd_semphr == NULL) return; + + xSemaphoreGiveFromISR(s_cd_semphr, &task_woken); + + portYIELD_FROM_ISR(task_woken); +} + +/* SDHC transfer complete callback function. */ +static void SDHC_TransferCompleteCallback(SDHC_Type *base, sdhc_handle_t *handle, status_t status, void *userData) { + if (status == kStatus_Success) { + g_sdhcTransferSuccessFlag = true; + } else { + g_sdhcTransferSuccessFlag = false; + } + + BaseType_t task_woken; + + xSemaphoreGiveFromISR(s_transfer_semphr, &task_woken); + + portYIELD_FROM_ISR(task_woken); +} + +/* User defined transfer function. */ +static status_t SDHC_TransferFunction(SDHC_Type *base, sdhc_transfer_t *content) { + status_t error = kStatus_Success; + + do { + error = SDHC_TransferNonBlocking(base, &g_sdhcHandle, g_sdhcAdmaTable, SDHC_ADMA_TABLE_WORDS, content); + } while (error == kStatus_SDHC_BusyTransferring); + + if (error != kStatus_Success) { + return kStatus_Fail; + } + + if (xSemaphoreTake(s_transfer_semphr, pdMS_TO_TICKS(1000)) != pdPASS) { + return kStatus_Fail; + } + + if (!g_sdhcTransferSuccessFlag) { + return kStatus_Fail; + } + + return error; +} + +status_t HOST_Init(void *host) { + sdhc_transfer_callback_t sdhcCallback = {0}; + sdhc_host_t *sdhcHost = (sdhc_host_t *)host; + + NVIC_SetPriority(SDHC_IRQn, 6); + SYSMPU_Enable(SYSMPU, false); + + /* Initializes SDHC. */ + sdhcHost->config.cardDetectDat3 = true; + sdhcHost->config.endianMode = SDHC_ENDIAN_MODE; + sdhcHost->config.dmaMode = SDHC_DMA_MODE; + sdhcHost->config.readWatermarkLevel = SDHC_READ_WATERMARK_LEVEL; + sdhcHost->config.writeWatermarkLevel = SDHC_WRITE_WATERMARK_LEVEL; + SDHC_Init(sdhcHost->base, &(sdhcHost->config)); + + /* Create handle for SDHC driver */ + sdhcCallback.TransferComplete = SDHC_TransferCompleteCallback; + sdhcCallback.CardInserted = CardInsertDetectHandle; + sdhcCallback.CardRemoved = CardInsertDetectHandle; + SDHC_TransferCreateHandle(sdhcHost->base, &g_sdhcHandle, &sdhcCallback, NULL); + + /* Create transfer complete event. */ + s_cd_semphr = xSemaphoreCreateBinary(); + if (s_cd_semphr == NULL) { + return kStatus_Fail; + } + + s_transfer_semphr = xSemaphoreCreateBinary(); + if (s_transfer_semphr == NULL) { + return kStatus_Fail; + } + + /* Define transfer function. */ + sdhcHost->transfer = SDHC_TransferFunction; + + return kStatus_Success; +} + +void HOST_Deinit(void *host) { + sdhc_host_t *sdhcHost = (sdhc_host_t *)host; + SDHC_Deinit(sdhcHost->base); + vSemaphoreDelete(s_cd_semphr); + vSemaphoreDelete(s_transfer_semphr); +}