#include "sys_config.h" #include "integer.h" #include "diskio.h" #include "ff.h" #include #include "osal/sleep.h" #include "typesdef.h" #include "osal/task.h" #include "osal/semaphore.h" #include "osal/mutex.h" #include "list.h" #include "dev.h" #include "sdhost.h" #include "devid.h" #include "osal/string.h" #include "osal/work.h" // #include "osal.h" #define FAT_INFO_SHOW(...) //printf(__VA_ARGS__) // #define FAT_TIME #if FS_EN static uint8_t fat_ready = 0; uint8_t get_fat_isready() { return fat_ready; } void set_fat_ready(uint8_t ready) { fat_ready = ready; } static DSTATUS fatfs_status(void *status); static DSTATUS fatfs_init(void *init_dev); static DRESULT fatfs_read(void *dev, BYTE *buf, DWORD sector, UINT count); static DRESULT fatfs_write(void *dev, BYTE *buf, DWORD sector, UINT count); static DRESULT fatfs_ioctl(void *init_dev, BYTE cmd, void *buf); uint32 get_sdhost_status(struct sdh_device *host); uint32 sd_tran_stop(struct sdh_device *host); static const struct fatfs_diskio sdcdisk_driver = { .status = fatfs_status, .init = fatfs_init, .read = fatfs_read, .write = fatfs_write, .ioctl = fatfs_ioctl}; static FATFS fatfs[1]; DWORD get_fatbase(int num) { return fatfs[num].fatbase; } DWORD get_fatfree(int num) { DWORD fre_clust, fre_sect, tot_sect; FATFS *fs = &fatfs[num]; fre_clust = fs->free_clst; tot_sect = (fs->n_fatent - 2) * fs->csize; fre_sect = fre_clust * fs->csize; printf("%s %ldKB\n", __FUNCTION__, fre_sect >> 1); return fre_sect >> 1; } static DSTATUS fatfs_status(void *status) { // FAT_INFO_SHOW ("fatfs_status_test\r\n"); uint32 err = get_sdhost_status(status); return err; } static DSTATUS fatfs_init(void *init_dev){ printf ("fatfs_init_test\r\n"); uint32 err = get_sdhost_status(init_dev); if(err) { err = sdhost_init(48 * 1000 * 1000, 0); } return err; } #if USE_FAT_CACHE // 内存分配函数 static void *fat_malloc(int size) { #ifdef PSRAM_HEAP return os_malloc_psram(size); #else return os_malloc(size); #endif } // 内存释放函数 static void fat_free(void *p) { #ifdef PSRAM_HEAP os_free_psram(p); #else os_free(p); #endif } struct fat_data_t { // uint8 data[FAT_CACHE_SIZE * 512]; // 32KB 缓存 BYTE *data; // 32KB 缓存 DWORD start_sector; // 缓存起始扇区 DWORD fat_start; // FAT起始扇区 DWORD fat_end; DWORD offset; DWORD max_offset; }; struct fat_cache_t { BYTE fat_info_ready; // BYTE fat_init; BYTE fs_type; BYTE fs_fats; DWORD fs_size; DWORD fat_tick; #ifdef FAT_TIME os_timer_t fat_timer; #else struct os_work fat_wk; #endif struct os_mutex lock; struct fat_data_t fat1; }; struct fat_cache_t fat_cache = { // lock和time初始化标志位,1是未初始化,0是已经初始化 .fat_init = 1, .fat_info_ready = 1, }; signed char update_fat_info(BYTE fmt, BYTE n_fats, DWORD sz_fat,DWORD fatbase, DWORD b_vol) { if (fat_cache.fat_init != RET_OK){ return RET_ERR; } os_mutex_lock(&fat_cache.lock, osWaitForever); fat_cache.fs_type = fmt; fat_cache.fs_fats = n_fats; fat_cache.fs_size = sz_fat; fat_cache.fat1.fat_start = fatbase; fat_cache.fat1.fat_end = fat_cache.fat1.fat_start + fat_cache.fs_size - 1; fat_cache.fat_info_ready = RET_OK; // 计算逻辑地址(扇区号) //UINT fat1_logical = fatbase - b_vol; // FAT1 logical start //UINT fat2_logical = fat1_logical + sz_fat; // FAT2 logical start // 计算物理地址(加上分区偏移) //UINT partition_start = b_vol; // 分区起始扇区 //UINT fat1_physical = partition_start + fat1_logical; //UINT fat2_physical = partition_start + fat2_logical; // if (fat_cache.fs_type == FS_EXFAT) // FS_EXFAT文件系统不需要优化 // { // fat_cache.fat_info_ready = 0; // } if (fmt == FS_FAT12) FAT_INFO_SHOW("Filesystem Type: FS_FAT12 \r\n"); else if (fmt == FS_FAT16) FAT_INFO_SHOW("Filesystem Type: FS_FAT16 \r\n"); else if (fmt == FS_FAT32) FAT_INFO_SHOW("Filesystem Type: FS_FAT32 \r\n"); else if (fmt == FS_EXFAT) FAT_INFO_SHOW("Filesystem Type: FS_EXFAT \r\n"); FAT_INFO_SHOW("Filesystem fat_num %u \r\n", n_fats); FAT_INFO_SHOW("Filesystem fat_size %u \r\n", sz_fat); FAT_INFO_SHOW("Physical Address ===> fat1_start %u , fat1_end %u \r\n", fat_cache.fat1.fat_start, fat_cache.fat1.fat_end); FAT_INFO_SHOW("Logical Address ====> fat1_start %u , fat1_end %u \r\n", fat1_logical, fat1_logical + sz_fat - 1); if (n_fats > 1) { FAT_INFO_SHOW("Physical Address ===> fat2_start %u , fat2_end %u \r\n", fat2_physical, fat2_physical + sz_fat - 1); FAT_INFO_SHOW("Logical Address ====> fat2_start %u , fat2_end %u \r\n", fat2_logical, fat2_logical + sz_fat - 1); } os_mutex_unlock(&fat_cache.lock); return RET_OK; } void update_io_timestamp() { if (fat_cache.fat_init != RET_OK || fat_cache.fat_info_ready != RET_OK){ return; } os_mutex_lock(&fat_cache.lock, osWaitForever); fat_cache.fat_tick = os_jiffies(); os_mutex_unlock(&fat_cache.lock); } // fat回写SD static void fat_cache_sync(struct sdh_device *host) { struct sdh_device *sdh = NULL; sdh = (struct sdh_device *)dev_get(HG_SDIOHOST_DEVID); if (fat_cache.fat_init != RET_OK || fat_cache.fat_info_ready != RET_OK){ return; } os_mutex_lock(&fat_cache.lock, osWaitForever); FAT_INFO_SHOW("############# CTRL_SYNC max_offset %d\r\n", fat_cache.fat1.max_offset); if (fat_cache.fat1.max_offset > 0) { sd_multiple_write((struct sdh_device *)host, fat_cache.fat1.start_sector, fat_cache.fat1.max_offset * 512, fat_cache.fat1.data); if (fat_cache.fs_fats > 1) { sd_multiple_write((struct sdh_device *)host, (fat_cache.fat1.start_sector + fat_cache.fs_size), fat_cache.fat1.max_offset * 512, fat_cache.fat1.data); } fat_cache.fat1.max_offset = 0; } os_mutex_unlock(&fat_cache.lock); } #ifdef FAT_TIME static void fat_loop(void *arg) #else static int32 fat_loop(struct os_work *work) #endif { if (fat_cache.fat_init != RET_OK || fat_cache.fat_info_ready != RET_OK){ goto fat_loop_end; } uint8 ret = 0; struct sdh_device *sdh = NULL; sdh = (struct sdh_device *)dev_get(HG_SDIOHOST_DEVID); ret = os_mutex_lock(&sdh->lock, 0); if (ret != RET_OK) { fat_cache.fat_tick = os_jiffies(); goto fat_loop_end; // 获取锁失败 } os_mutex_unlock(&sdh->lock); ret = os_mutex_lock(&fat_cache.lock, 0); if (ret != RET_OK) { goto fat_loop_end; // 获取锁失败 } // 检测到200ms没有操作SD卡,并SD卡在线,fat信息回写SD if (os_jiffies() - fat_cache.fat_tick > 200 && SD_OFF != sdh->sd_opt) { fat_cache.fat_tick = os_jiffies(); if (fat_cache.fat1.max_offset > 0) { FAT_INFO_SHOW(" fat_loop write back max_offset %d\r\n", fat_cache.fat1.max_offset); sd_multiple_write(sdh, fat_cache.fat1.start_sector, fat_cache.fat1.max_offset * 512, fat_cache.fat1.data); if (fat_cache.fs_fats > 1) // 写入FAT2 { sd_multiple_write(sdh, (fat_cache.fat1.start_sector + fat_cache.fs_size), fat_cache.fat1.max_offset * 512, fat_cache.fat1.data); } fat_cache.fat1.max_offset = 0; } } os_mutex_unlock(&fat_cache.lock); fat_loop_end: #ifdef FAT_TIME return; #else os_run_work_delay(work, 50); return 0; #endif } static void init_fat_cache(FATFS *fs) { if (update_fat_info(fs->fs_type, fs->n_fats, fs->fsize,fs->fatbase, fs->volbase) != RET_OK){ return; } FAT_INFO_SHOW("init_fat_cache \r\n"); struct sdh_device *sdh = NULL; sdh = (struct sdh_device *)dev_get(HG_SDIOHOST_DEVID); // 初始化后第一次读fat1 fat_cache.fat1.start_sector = fs->fatbase; sd_multiple_read(sdh, fat_cache.fat1.start_sector, FAT_CACHE_SIZE * 512, fat_cache.fat1.data); } static void del_fat_cache(void) { if (fat_cache.fat_init != RET_OK){ return; } fat_cache.fat_init = 1; fat_cache.fat_info_ready = 1; os_mutex_lock(&fat_cache.lock, osWaitForever); FAT_INFO_SHOW("########### del_fat_cache \r\n"); #ifdef FAT_TIME os_timer_stop(&fat_cache.fat_timer); os_timer_del(&fat_cache.fat_timer);// 先卸载定时器 #else os_work_cancle(&fat_cache.fat_wk,1); #endif // 释放fat缓存 if (fat_cache.fat1.data) { FAT_INFO_SHOW("%s %d fat free \r\n", __func__, __LINE__); fat_free(fat_cache.fat1.data); fat_cache.fat1.data = NULL; } os_mutex_unlock(&fat_cache.lock); os_mutex_del(&fat_cache.lock); } static DRESULT read_from_fat_cache(void *dev, struct fat_data_t *cache, BYTE *buf, DWORD sector, UINT count) { int ret = 0; if (fat_cache.fat_init != RET_OK || fat_cache.fat_info_ready != RET_OK){ return sd_multiple_read((struct sdh_device *)dev, sector, count * 512, buf); } os_mutex_lock(&fat_cache.lock, osWaitForever); if (sector >= cache->start_sector && sector + count <= cache->start_sector + FAT_CACHE_SIZE) { // 从缓存读取 cache->offset = (sector - cache->start_sector); memcpy(buf, &cache->data[cache->offset * 512], count * 512); } // 未命中缓存,把旧缓存写入SD,重新预读 16KB 到缓存 else { // 把旧缓存写入fat if (cache->max_offset > 0) { FAT_INFO_SHOW("read_from_fat_cache write back max_offset %d sector %d\r\n", cache->max_offset, sector); sd_multiple_write((struct sdh_device *)dev, cache->start_sector, cache->max_offset * 512, cache->data); if (fat_cache.fs_fats > 1) { sd_multiple_write((struct sdh_device *)dev, (cache->start_sector + fat_cache.fs_size), cache->max_offset * 512, cache->data); } cache->max_offset = 0; // memset(cache->data, 0, FAT_CACHE_SIZE * 512); } // 重新预读数据到缓存 ret = sd_multiple_read((struct sdh_device *)dev, sector, FAT_CACHE_SIZE * 512, cache->data); cache->start_sector = sector; memcpy(buf, &cache->data[0], count * 512); } // __end: os_mutex_unlock(&fat_cache.lock); return ret; } static DRESULT write_to_fat_cache(void *dev, struct fat_data_t *cache, BYTE *buf, DWORD sector, UINT count) { int ret = 0; if (fat_cache.fat_init != RET_OK || fat_cache.fat_info_ready != RET_OK){ return sd_multiple_write((struct sdh_device *)dev, sector, count * 512, buf); } os_mutex_lock(&fat_cache.lock, osWaitForever); // 检查是否命中缓存 if (sector >= cache->start_sector && sector + count <= cache->start_sector + FAT_CACHE_SIZE) { cache->offset = (sector - cache->start_sector); memcpy(&cache->data[cache->offset * 512], buf, count * 512); if (cache->max_offset < (cache->offset + 1)) { cache->max_offset = cache->offset + 1; } } else { // 把旧缓存写入fat if (cache->max_offset > 0) { FAT_INFO_SHOW("write_to_fat_cache write back max_offset %d sector %d\r\n", cache->max_offset, sector); sd_multiple_write((struct sdh_device *)dev, cache->start_sector, cache->max_offset * 512, cache->data); if (fat_cache.fs_fats > 1) { sd_multiple_write((struct sdh_device *)dev, (cache->start_sector + fat_cache.fs_size), cache->max_offset * 512, cache->data); } cache->max_offset = 0; // memset(cache->data, 0, FAT_CACHE_SIZE * 512); } // 重新预读数据到缓存 ret = sd_multiple_read((struct sdh_device *)dev, sector, FAT_CACHE_SIZE * 512, cache->data); cache->start_sector = sector; cache->offset = 0; memcpy(&cache->data[cache->offset * 512], buf, count * 512); if (cache->max_offset < (cache->offset + 1)) { cache->max_offset = cache->offset + 1; } } // __end: os_mutex_unlock(&fat_cache.lock); return ret; } #endif DRESULT fatfs_read(void *dev, BYTE *buf, DWORD sector, UINT count) { #if USE_FAT_CACHE update_io_timestamp(); if (sector >= fat_cache.fat1.fat_start && sector <= fat_cache.fat1.fat_end) { return read_from_fat_cache((struct sdh_device *)dev, &fat_cache.fat1, buf, sector, count); } #endif return sd_multiple_read((struct sdh_device *)dev, sector, count * 512, buf); } static DRESULT fatfs_write(void *dev, BYTE *buf, DWORD sector, UINT count) { #if USE_FAT_CACHE update_io_timestamp(); if (sector >= fat_cache.fat1.fat_start && sector <= fat_cache.fat1.fat_end) { return write_to_fat_cache((struct sdh_device *)dev, &fat_cache.fat1, buf, sector, count); } #endif return sd_multiple_write((struct sdh_device *)dev, sector, count * 512, buf); } extern unsigned int sd_dwCap; extern uint32 fatfs_sd_tran_stop(struct sdh_device *host); static DRESULT fatfs_ioctl(void *init_dev, BYTE cmd, void *buf) { uint8 ret = RES_OK; switch (cmd) { case CTRL_SYNC: fatfs_sd_tran_stop(init_dev); #if USE_FAT_CACHE fat_cache_sync(init_dev); #endif break; case GET_SECTOR_COUNT: *(DWORD *)buf = sd_dwCap * 2; ret = RES_OK; break; case GET_SECTOR_SIZE: *(WORD *)buf = 512; ret = RES_OK; break; case GET_BLOCK_SIZE: *(DWORD *)buf = 4; // printf("*0B:%d\n",*B); ret = RES_OK; break; default: ret = RES_ERROR; // not finish printf("rtos_sd_ioctl err\n"); break; } return ret; } bool fatfs_register() { int ret = 1; struct sdh_device *fatfs_sdh; // printf(">>>>>>>>>> enter %s test\r\n", __func__); fatfs_sdh = (struct sdh_device *)dev_get(HG_SDIOHOST_DEVID); #if USE_FAT_CACHE if (fat_cache.fat_init) { // 分配 fat1 缓存 fat_cache.fat1.data = fat_malloc(FAT_CACHE_SIZE * 512); if( fat_cache.fat1.data != NULL && os_mutex_init(&fat_cache.lock) == RET_OK && #ifdef FAT_TIME os_timer_init(&fat_cache.fat_timer, fat_loop, OS_FAT_TIMER_MODE_PERIODIC, 0) == RET_OK #else OS_WORK_INIT(&fat_cache.fat_wk, fat_loop, 0) == RET_OK #endif ) { fat_cache.fat_init = RET_OK; FAT_INFO_SHOW("fat_init success\r\n"); #ifdef FAT_TIME os_timer_start(&fat_cache.fat_timer, 50); #else os_run_work_delay(&fat_cache.fat_wk, 50); #endif } else { os_printf("fat init err \r\n"); } } #endif if (fatfs_sdh) { fatfs_register_drive(0, (struct fatfs_diskio*)&sdcdisk_driver, fatfs_sdh); ret = f_mount(&fatfs[0], _SYSDSK_, 1); if (ret) { printf("%s ret:%d\n", __FUNCTION__, ret); f_mount(NULL, _SYSDSK_, 0); return ret; } FAT_INFO_SHOW("f_mount success\r\n"); set_fat_ready(1); #if USE_FAT_CACHE init_fat_cache(&fatfs[0]); #endif } return ret; } void fatfs_unregister() { int ret = 1; FAT_INFO_SHOW(">>>>>>>>>>enter %s test\r\n", __func__); struct sdh_device *fatfs_sdh; fatfs_sdh = (struct sdh_device *)dev_get(HG_SDIOHOST_DEVID); if (fatfs_sdh) { fatfs_register_drive(0, (struct fatfs_diskio*)&sdcdisk_driver, fatfs_sdh); ret = f_mount(NULL, _SYSDSK_, 0); if (ret) { printf("%s ret:%d\n", __FUNCTION__, ret); return; } set_fat_ready(0); #if USE_FAT_CACHE del_fat_cache(); #endif } } #endif