#include "at32f403a_407.h" #include "user_fatfs.h" #include "common_config.h" #include "common.h" #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "spi_flash.h" #include #include #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #define MAX_DRV_NUM 2 // Текущее число поддерживаемых дисков SemaphoreHandle_t spiFlashMutex; FIL update_file; // Файл прошивки FATFS *disks[MAX_DRV_NUM]; static unsigned long writePtr[MAX_DRV_NUM] = {0, 0}; // Указатель на позицию для записи в файл static uint32_t strCount = 0; // Число строк в файле static uint32_t pageCount = 0; // Число страниц в файле char file_path[32]; static bool fSecDrvEn = false; // Флаг присутствия второстепенного диска static bool fPrimDrvEn = false; // Флаг присутствия основного диска static bool fatfs_init = false; // bool InitFS(BYTE drv) { FRESULT res; FATFS *disk; DWORD free; uint32_t space; spiFlashMutex = xSemaphoreCreateMutex(); snprintf(file_path, sizeof(file_path), "%u:", drv); disk = pvPortMalloc(sizeof(FATFS)); if (disk == NULL) { printf("DRIVE %u: malloc error\n\r", drv); fatfs_init = true; return false; } // Монтировать диск res = f_mount(disk, "", 1); // Создать файловую систему if (res != FR_OK) { res = f_mkfs(file_path,0,0); } f_getfree("/", &free, &disk); space = free * disk->ssize; if (space == 0) { f_mkfs(file_path,0,0); f_getfree("/", &free, &disk); space = free * disk->ssize; } res = f_chdir(file_path); if (res == FR_NO_FILESYSTEM) { printf("DRIVE %u: no filesystem found\n\r", drv); switch(drv) { case SPI_FLASH: spi_flash_erase_sector(0,0); spi_flash_erase_sector(1,0); spi_flash_erase_sector(2,0); spi_flash_erase_sector(3,0); break; } f_mkfs(file_path,0,0); if (f_chdir(file_path) != FR_OK) { printf("DRIVE %u: filesystem error\n\r", drv); vPortFree(disk); fatfs_init = true; return false; } else { printf("DRIVE %u: filesystem created successfully\n\r", drv); } } else if (res == FR_NOT_READY) { printf("DRIVE %u: not ready\n\r", drv); printf("DRIVE %u: File system is not initialized. Error!\n\r", drv); vPortFree(disk); fatfs_init = true; return false; } else if(res == FR_OK) { // Проверка файла лога res = f_open(&update_file, LOG_NAME, FA_READ); if (res != FR_OK) { res = f_open(&update_file, LOG_NAME, FA_WRITE | FA_CREATE_NEW); if (res != FR_OK) { f_close(&update_file); printf("DRIVE %u: File system is not initialized. Error!\n\r", drv); fatfs_init = true; return false; } } f_close(&update_file); } printf("DRIVE %u: filesystem initialized successfully\n\r", drv); fatfs_init = true; return true; } /** * @brief Возвращает число файлов в папке * @param *path имя папки в виде "/LOG" * @retval */ uint32_t GetFilesCount(char *path) { FRESULT res; FILINFO fno; DIR dir; char *fn; uint32_t fileCount; res = f_opendir(&dir, path); if (res != FR_OK) return 0; // Не удалось открыть директорию for (;;) { res = f_readdir(&dir, &fno); // Чтение объекта директории // Останов цикла при ошибке или при достижении конца списка директории if (res != FR_OK || fno.fname[0] == 0) return fileCount; if (fno.fname[0] == '.') continue; // Игнорирование элемента 'точка' fn = fno.fname; if (!(fno.fattrib & AM_DIR)) { // Это директория fileCount++; DBG printf("%s\r\n",fn); } else { DBG printf("%s/%s\r\n", path, fn); } } } /* Get fs file raw data */ uint32_t GetFileData(BYTE drv, char *file_name, unsigned long ptr, char *str, uint32_t size) { unsigned long readPtr; FRESULT res; uint32_t count = 0; res = f_open(&update_file, file_name, FA_WRITE); if (res != FR_OK) { f_close(&update_file); return 0; } readPtr = ptr; res = f_lseek(&update_file, readPtr); if (res != FR_OK) { f_close(&update_file); return 0; } res = f_read(&update_file, str, size, (UINT *)&count); if (res != FR_OK) { f_close(&update_file); return 0; } f_close(&update_file); return count; } /* Put fs file raw data */ uint32_t PutFileData(BYTE drv, char *file_name, unsigned long ptr, char *str, uint32_t size, bool truncate) { FRESULT res; uint32_t count = 0; if (xSemaphoreTake(spiFlashMutex, 2000) != pdTRUE) return 0; res = f_open(&update_file, file_name, FA_WRITE); if (res != FR_OK) { f_close(&update_file); xSemaphoreGive(spiFlashMutex); return 0; } if( ptr == 1 ){ res = f_lseek(&update_file, 0); } else{ res = f_lseek(&update_file, update_file.fsize); } if (res != FR_OK) { f_close(&update_file); xSemaphoreGive(spiFlashMutex); return 0; } res = f_write(&update_file, str, size, (UINT *)&count); if (res != FR_OK) { f_close(&update_file); xSemaphoreGive(spiFlashMutex); return 0; } if (truncate) { res = f_truncate(&update_file); if (res != FR_OK) { xSemaphoreGive(spiFlashMutex); } } f_close(&update_file); xSemaphoreGive(spiFlashMutex); return count; } // void EraseFlash() { if (xSemaphoreTake(spiFlashMutex, 10000) != pdTRUE) return; spi_flash_erase_sector(0,0); spi_flash_erase_sector(1,0); spi_flash_erase_sector(2,0); spi_flash_erase_sector(3,0); xSemaphoreGive(spiFlashMutex); } // void flash_check_space(FATFS *fs) { DWORD fre_clust, fre_sect; // Получение информации о томе и количество свободных кластеров f_getfree(0, &fre_clust, &fs); fre_sect = fre_clust * fs->csize; //availableSpace = fre_sect/2; } // bool fatfs_isinit(void) { return fatfs_init; }