F746NG fatfs and micro sd example

Dependencies:   BSP_DISCO_F746NG FatFS mbed

This is a quick and dirty example about how to use micro sd card module with FatFs on STM32746G Discovery board. I simply use the FatFs library downloaded with DFP for STM32F7. The project shows how to read PPM image file from sd card, display on LCD and writing image to sd card.

main.cpp

Committer:
buyukesmeli
Date:
2018-02-04
Revision:
2:19c2835ce409
Parent:
1:28e2f24b11b3

File content as of revision 2:19c2835ce409:

#include "mbed.h"
#define USE_STM32746G_DISCOVERY
#include "stm32f7xx_hal.h"
#include "stm32746g_discovery.h"
#include "stm32746g_discovery_sd.h"
#include "string.h"
#include "stm32746g_discovery_lcd.h"
#include "ff_gen_drv.h"
#include "sd_diskio.h"

#define FRAME_BUFFER    0xC0000000
#define SD_IN_BUFFER    0xC0140000
#define SD_OUT_BUFFER   0xC0280000

FATFS SDFatFs;
FIL MyFile;




static void LCD_LL_ConvertFrameToARGB8888(void *pSrc, void *pDst);
static void LCD_LL_ConvertFrameToRGB888(void *pSrc, void *pDst);
extern SD_HandleTypeDef uSdHandle;
DMA2D_HandleTypeDef hdma2d_disco;

Serial pc(USBTX, USBRX);
uint32_t i = 0, image_width = 0, image_height = 0;
const char image_header[] = "P6\n# Generated by STM32\n480 272\n255\n";

char SDPath[4];
char text [40];
char c;
int main(void)
{
    FRESULT res;
    uint32_t  bytesread;
    uint32_t line_cnt=0;
    pc.baud(115200);

    BSP_LCD_Init();
    BSP_LCD_DisplayOff();
    BSP_LCD_LayerDefaultInit(0, FRAME_BUFFER);
    BSP_LCD_SelectLayer(0);
    BSP_LCD_DisplayOn();

    FATFS_LinkDriver(&SD_Driver, SDPath);

    res = f_mount(&SDFatFs, (TCHAR const*)SDPath, 0);
    if(res!= FR_OK)
        pc.printf("Failed to mount SD\n");

    res = f_open(&MyFile, "image.ppm",  FA_READ);
    if(res!= FR_OK)
        pc.printf("Failed to open file\n");
    
    // Read image header and get image size
    while(res==FR_OK) {
        res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
        if (c!='#')
            line_cnt++;
        if(line_cnt==2) {
            text[0] = c;
            res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
            i = 1;
            while(c!=' ') {
                text[i]=c;
                res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
                i++;
            }
            text[i]=0;
            image_width = atoi(text);
            res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
            i = 0;
            while(c!='\n') {
                text[i]=c;
                res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
                i++;
            }
            text[i]=0;
            image_height = atoi(text);
        } else {
            while(c!='\n')
                res = f_read(&MyFile, &c, 1, (UINT*)&bytesread);
        }
        if(line_cnt == 3)
            break;

    }

    if(image_width != 480 || image_height != 272)
        pc.printf("Image size should be 480x272");
        
    // Read image as 512 byte blocks
    for(i = 0; i < image_width*image_width*3; i = i + 512) {
        res = f_read(&MyFile, (uint8_t *)(SD_IN_BUFFER+i) , 512, (UINT*)&bytesread);
    }
    
    // Correct color order
    for(i = 0; i < image_width*image_width*3; i = i + 3) {
        c = *(char *)(SD_IN_BUFFER+i+2);
        *(char *)(SD_IN_BUFFER+i+2)= *(char *)(SD_IN_BUFFER+i);
        *(char *)(SD_IN_BUFFER+i) = c;
    }
    f_close(&MyFile);
    
    // Print image on LCD
    LCD_LL_ConvertFrameToARGB8888((uint32_t *)(SD_IN_BUFFER), (uint32_t *)(FRAME_BUFFER));

    
    // Transfer image to a buffer
    LCD_LL_ConvertFrameToRGB888((uint32_t *)(FRAME_BUFFER), (uint32_t *)(SD_OUT_BUFFER));
    
    // Correct color order
    for(i = 0; i < image_width*image_width*3; i = i + 3) {
        c = *(char *)(SD_OUT_BUFFER+i+2);
        *(char *)(SD_OUT_BUFFER+i+2)= *(char *)(SD_OUT_BUFFER+i);
        *(char *)(SD_OUT_BUFFER+i) = c;
    }
    
    res = f_open(&MyFile, "image_ou.ppm",   FA_CREATE_ALWAYS | FA_WRITE);
    if(res!= FR_OK)
        pc.printf("Failed to open file\n");

    // Write image header
    res = f_write(&MyFile, image_header, sizeof(image_header), &bytesread);
    if(res!= FR_OK)
        pc.printf("Failed to write file 1\n");
        
    // Write image as 512 byte blocks
    for(i = 0; i < 480*272*3; i = i + 512) {
        res = f_write(&MyFile, (uint8_t *)(SD_OUT_BUFFER+i), 512, &bytesread);
        if(res!= FR_OK)
            pc.printf("Failed to write file\n");
    }

    pc.printf("Done!\n");
    f_close(&MyFile);
    FATFS_UnLinkDriver(SDPath);

    while (1) {
    }
}
extern "C" {
    void BSP_SDMMC_IRQHandler(void)
    {
        HAL_SD_IRQHandler(&uSdHandle);
    }
    void BSP_SDMMC_DMA_Tx_IRQHandler(void)
    {
        HAL_DMA_IRQHandler(uSdHandle.hdmatx);
    }
    void BSP_SDMMC_DMA_Rx_IRQHandler(void)
    {
        HAL_DMA_IRQHandler(uSdHandle.hdmarx);
    }
    static void LCD_LL_ConvertFrameToARGB8888(void *pSrc, void *pDst)
    {
        /* Enable DMA2D clock */
        __HAL_RCC_DMA2D_CLK_ENABLE();

        /* Configure the DMA2D Mode, Color Mode and output offset */
        hdma2d_disco.Init.Mode         = DMA2D_M2M_PFC;
        hdma2d_disco.Init.ColorMode    = DMA2D_ARGB8888;
        hdma2d_disco.Init.OutputOffset = 0;

        /* Foreground Configuration */
        hdma2d_disco.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
        hdma2d_disco.LayerCfg[1].InputAlpha = 0xFF;
        hdma2d_disco.LayerCfg[1].InputColorMode = CM_RGB888;
        hdma2d_disco.LayerCfg[1].InputOffset = 0;

        hdma2d_disco.Instance = DMA2D;

        /* DMA2D Initialization */
        if(HAL_DMA2D_Init(&hdma2d_disco) == HAL_OK) {
            if(HAL_DMA2D_ConfigLayer(&hdma2d_disco, 1) == HAL_OK) {
                if (HAL_DMA2D_Start(&hdma2d_disco, (uint32_t)pSrc, (uint32_t)pDst, 480, 272) == HAL_OK) {
                    /* Polling For DMA transfer */
                    HAL_DMA2D_PollForTransfer(&hdma2d_disco, 10);
                }
            }
        } else {

        }
    }
    static void LCD_LL_ConvertFrameToRGB888(void *pSrc, void *pDst)
    {
        /* Enable DMA2D clock */
        __HAL_RCC_DMA2D_CLK_ENABLE();

        /* Configure the DMA2D Mode, Color Mode and output offset */
        hdma2d_disco.Init.Mode         = DMA2D_M2M_PFC;
        hdma2d_disco.Init.ColorMode    = DMA2D_RGB888;
        hdma2d_disco.Init.OutputOffset = 0;

        /* Foreground Configuration */
        hdma2d_disco.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
        hdma2d_disco.LayerCfg[1].InputAlpha = 0xFF;
        hdma2d_disco.LayerCfg[1].InputColorMode = CM_ARGB8888;
        hdma2d_disco.LayerCfg[1].InputOffset = 0;

        hdma2d_disco.Instance = DMA2D;

        /* DMA2D Initialization */
        if(HAL_DMA2D_Init(&hdma2d_disco) == HAL_OK) {
            if(HAL_DMA2D_ConfigLayer(&hdma2d_disco, 1) == HAL_OK) {
                if (HAL_DMA2D_Start(&hdma2d_disco, (uint32_t)pSrc, (uint32_t)pDst, 480, 272) == HAL_OK) {
                    /* Polling For DMA transfer */
                    HAL_DMA2D_PollForTransfer(&hdma2d_disco, 10);
                }
            }
        } else {

        }
    }

}