Skip to content

Commit

Permalink
Add FatFs, fatfs diskio and example
Browse files Browse the repository at this point in the history
  • Loading branch information
yh-sb committed Nov 29, 2024
1 parent 05288b2 commit 8b5e238
Show file tree
Hide file tree
Showing 103 changed files with 31,185 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE periph/stm32f4/include)
add_subdirectory(third_party/FreeRTOS-Kernel)

add_subdirectory(third_party/FatFs)
add_subdirectory(fatfs_diskio)

add_subdirectory(third_party/printf)

add_executable(${CMAKE_PROJECT_NAME}
Expand All @@ -67,6 +70,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
periph_stm32f4
drivers
freertos_kernel
fatfs_diskio
)

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX ".elf")
Expand Down
3 changes: 3 additions & 0 deletions examples/stm32f0/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE periph/stm32f0/include)
add_subdirectory(third_party/FreeRTOS-Kernel)

#add_subdirectory(third_party/FatFs)
#add_subdirectory(fatfs_diskio)

add_subdirectory(third_party/printf)

add_executable(${CMAKE_PROJECT_NAME}
Expand Down
3 changes: 3 additions & 0 deletions examples/stm32f1/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE periph/stm32f1/include)
add_subdirectory(third_party/FreeRTOS-Kernel)

#add_subdirectory(third_party/FatFs)
#add_subdirectory(fatfs_diskio)

add_subdirectory(third_party/printf)

add_executable(${CMAKE_PROJECT_NAME}
Expand Down
4 changes: 4 additions & 0 deletions examples/stm32f4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE periph/stm32f4/include)
add_subdirectory(third_party/FreeRTOS-Kernel)

add_subdirectory(third_party/FatFs)
add_subdirectory(fatfs_diskio)

add_subdirectory(third_party/printf)

add_executable(${CMAKE_PROJECT_NAME}
Expand All @@ -67,6 +70,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
periph_stm32f4
drivers
freertos_kernel
fatfs_diskio
)

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX ".elf")
Expand Down
128 changes: 128 additions & 0 deletions examples/stm32f4/fatfs_diskio-example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Example for STM32F4DISCOVERY development board
// SD card connected to SPI1: PA7-MOSI, PA6-MISO, PA5-CLK, PA4-CS, PA3-CD

#include <cstring>
#include "FreeRTOS.h"
#include "task.h"
#include "ff.h"
#include "fatfs_diskio.hpp"
#include "periph/systick.hpp"
#include "periph/gpio_stm32f4.hpp"
#include "periph/dma_stm32f4.hpp"
#include "periph/spi_stm32f4.hpp"
#include "drivers/gpio_pin_debouncer.hpp"
#include "drivers/sd_spi.hpp"

struct task_params_t
{
drv::gpio_pin_debouncer &button;
drv::sd &sd;
periph::gpio &led;
};

static void card_detection_callback(bool new_state)
{
if(new_state)
{
f_unmount("SD");
return;
}

FATFS fs;
FRESULT ff_res = f_mount(&fs, "SD", 1);
if(ff_res)
{
BYTE work_area[FF_MAX_SS] = {};
const MKFS_PARM opt { .fmt = FM_FAT32 };
ff_res = f_mkfs("SD", &opt, work_area, sizeof(work_area));
if(ff_res)
{
return;
}
ff_res = f_mount(&fs, "SD", 1);
if(ff_res)
{
return;
}
}

FIL file;
ff_res = f_open(&file, "SD:test.txt", FA_WRITE | FA_CREATE_ALWAYS);
if(ff_res)
{
return;
}

size_t size = strlen("abcdefgh-1234567890");
ff_res = f_write(&file, "abcdefgh-1234567890", size, &size);
f_close(&file);
if(ff_res)
{
return;
}

ff_res = f_open(&file, "SD:test.txt", FA_READ);
if(ff_res)
{
return;
}

char buff[64] = {};
size = 0;
ff_res = f_read(&file, buff, sizeof(buff), &size);
f_close(&file);
}

static void button_1_task(void *pvParameters)
{
task_params_t *task_params = (task_params_t *)pvParameters;
drv::gpio_pin_debouncer &button_1 = task_params->button;
drv::sd &sd = task_params->sd;
periph::gpio &green_led = task_params->led;

while(1)
{
bool new_state;
if(button_1.poll_1ms(new_state))
{
if(new_state)
{
green_led.toggle();

card_detection_callback(new_state);
}
}
vTaskDelay(1);
}
}

int main(void)
{
periph::systick::init();

// Green LED
periph::gpio_stm32f4 green_led(periph::gpio_stm32f4::port::d, 12, periph::gpio::mode::digital_output, 1);

// Button 1
periph::gpio_stm32f4 button_1_gpio(periph::gpio_stm32f4::port::a, 0, periph::gpio::mode::digital_input);
drv::gpio_pin_debouncer button_1(button_1_gpio, std::chrono::milliseconds(50), 1);

// SD card over SPI interface
periph::gpio_stm32f4 spi1_mosi(periph::gpio_stm32f4::port::a, 7, periph::gpio::mode::alternate_function);
periph::gpio_stm32f4 spi1_miso(periph::gpio_stm32f4::port::a, 6, periph::gpio::mode::alternate_function);
periph::gpio_stm32f4 spi1_clk(periph::gpio_stm32f4::port::a, 5, periph::gpio::mode::alternate_function);
periph::gpio_stm32f4 spi1_cs(periph::gpio_stm32f4::port::a, 4, periph::gpio::mode::digital_output, 1);
periph::gpio_stm32f4 spi1_cd(periph::gpio_stm32f4::port::a, 3, periph::gpio::mode::digital_input, 1);
periph::dma_stm32f4 spi1_read_dma(2, 0, 3, periph::dma_stm32f4::direction::periph_to_memory, 8);
periph::dma_stm32f4 spi1_write_dma(2, 3, 3, periph::dma_stm32f4::direction::memory_to_periph, 8);
periph::spi_stm32f4 spi1(1, 1000000, periph::spi::cpol::low, periph::spi::cpha::leading,
periph::spi::bit_order::msb, spi1_write_dma, spi1_read_dma, spi1_mosi, spi1_miso, spi1_clk);
drv::sd_spi sd_spi_1(spi1, spi1_cs, &spi1_cd);

fatfs_diskio_add(0, sd_spi_1);

task_params_t task_params = {button_1, sd_spi_1, green_led};
xTaskCreate(button_1_task, "button_1", configMINIMAL_STACK_SIZE + 200, &task_params, 1, nullptr);

vTaskStartScheduler();
}
16 changes: 16 additions & 0 deletions fatfs_diskio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_library(fatfs_diskio STATIC
fatfs_diskio.cpp
fatfs_diskio_dataflash.cpp
fatfs_diskio_sd.cpp
)

target_include_directories(fatfs_diskio
PUBLIC
.
)

target_link_libraries(fatfs_diskio
PUBLIC
drivers
fatfs
)
67 changes: 67 additions & 0 deletions fatfs_diskio/fatfs_diskio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

#include <cassert>
#include "fatfs_diskio.hpp"
#include "fatfs_diskio_dataflash.hpp"
#include "fatfs_diskio_sd.hpp"
#include "diskio.h"
#include "ffconf.h"

static void *ctxs[FF_VOLUMES];
static fatfs_diskio_t *diskios[FF_VOLUMES];

void fatfs_diskio_add(uint8_t pdrv, drv::dataflash &df)
{
assert(pdrv < FF_VOLUMES);

diskios[pdrv] = fatfs_diskio_dataflash();
ctxs[pdrv] = (void *)&df;
}

void fatfs_diskio_add(uint8_t pdrv, drv::sd &sd)
{
assert(pdrv < FF_VOLUMES);

diskios[pdrv] = fatfs_diskio_sd();
ctxs[pdrv] = (void *)&sd;
}

// FatFs handler goes below
DSTATUS disk_status(BYTE pdrv)
{
assert(diskios[pdrv]);

return diskios[pdrv]->status(ctxs[pdrv]);
}

DSTATUS disk_initialize(BYTE pdrv)
{
assert(diskios[pdrv]);

return diskios[pdrv]->initialize(ctxs[pdrv]);
}

DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
assert(diskios[pdrv]);

return diskios[pdrv]->read(ctxs[pdrv], buff, sector, count);
}

DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
assert(diskios[pdrv]);

return diskios[pdrv]->write(ctxs[pdrv], buff, sector, count);
}

DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
assert(diskios[pdrv]);

return diskios[pdrv]->ioctl(ctxs[pdrv], cmd, buff);
}

DWORD get_fattime(void)
{
return 0;
}
18 changes: 18 additions & 0 deletions fatfs_diskio/fatfs_diskio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "ff.h"
#include "diskio.h"
#include "drivers/dataflash.hpp"
#include "drivers/sd.hpp"

struct fatfs_diskio_t
{
DSTATUS (*status)(void *ctx);
DSTATUS (*initialize)(void *ctx);
DRESULT (*read)(void *ctx, BYTE *buff, DWORD sector, UINT count);
DRESULT (*write)(void *ctx, const BYTE *buff, DWORD sector, UINT count);
DRESULT (*ioctl)(void *ctx, BYTE cmd, void *buff);
};

void fatfs_diskio_add(uint8_t pdrv, drv::dataflash &df);
void fatfs_diskio_add(uint8_t pdrv, drv::sd &sd);
105 changes: 105 additions & 0 deletions fatfs_diskio/fatfs_diskio_dataflash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include <cassert>
#include "fatfs_diskio_dataflash.hpp"
#include "diskio.h"
#include "drivers/dataflash.hpp"

static DSTATUS status(void *ctx);
static DSTATUS initialize(void *ctx);
static DRESULT read(void *ctx, BYTE *buff, DWORD sector, UINT count);
static DRESULT write(void *ctx, const BYTE *buff, DWORD sector, UINT count);
static DRESULT ioctl(void *ctx, BYTE cmd, void *buff);

fatfs_diskio_t *fatfs_diskio_dataflash()
{
static fatfs_diskio_t diskio =
{
.status = status, .initialize = initialize, .read = read,
.write = write, .ioctl = ioctl
};

return &diskio;
}

static DSTATUS status(void *ctx)
{
drv::dataflash *_df = (drv::dataflash *)ctx;

drv::dataflash::info_t info = _df->info();

return (info.page_size && info.pages) ? STA_NOINIT : 0;
}

static DSTATUS initialize(void *ctx)
{
drv::sd *_sd = (drv::sd *)ctx;

switch(_sd->init())
{
case drv::sd::res::ok: return 0;
case drv::sd::res::locked: return STA_PROTECT | STA_NOINIT;
default: return STA_NOINIT;
}
}

static DRESULT read(void *ctx, BYTE *buff, DWORD sector, UINT count)
{
drv::dataflash *_df = (drv::dataflash *)ctx;

switch(_df->read(buff, sector, count))
{
case drv::dataflash::res::ok: return RES_OK;
default: return RES_ERROR;
}
}

static DRESULT write(void *ctx, const BYTE *buff, DWORD sector, UINT count)
{
drv::dataflash *_df = (drv::dataflash *)ctx;

switch(_df->write((BYTE *)buff, sector, count))
{
case drv::dataflash::res::ok: return RES_OK;
default: return RES_ERROR;
}
}

static DRESULT ioctl(void *ctx, BYTE cmd, void *buff)
{
drv::dataflash *_df = (drv::dataflash *)ctx;
DRESULT res = RES_OK;

switch(cmd)
{
case CTRL_SYNC:
break;

case GET_SECTOR_COUNT:
*(DWORD *)buff = (DWORD)_df->info().pages;
break;

case GET_SECTOR_SIZE:
*(WORD *)buff = (WORD)_df->info().page_size;
break;

case GET_BLOCK_SIZE:
*(DWORD *)buff = (DWORD)_df->info().page_size;
break;

case CTRL_TRIM:
{
DWORD start = ((DWORD *)buff)[0];
DWORD end = ((DWORD *)buff)[1];

if(_df->erase(start, end - start) != drv::dataflash::res::ok)
{
res = RES_ERROR;
}
}
break;

default:
assert(0);
}

return res;
}
Loading

0 comments on commit 8b5e238

Please sign in to comment.