This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

creating a new file after calling fsfat_example()

I am trying to create a datalogger onto a uSD card with a fat file system. I have been able to run the fatfs example which creates a file on the uSD card, NORDIC.TXT. The file has some test text inside. 

My question, if the fatfs_example(), initializes the system and presumably does uninitialize it then why does the my application hang when trying to write a second file onto the uSD card? It does not return from the function afilewrite(); I have seen error codes equivalent to 12 and have followed this to work area not established or does not exist.

I have taken out the static variables pertaining to the files and the disk and made then global in order to reuse what is working in the fatfs_example. Attached is the file that has been created in order to write the initial NORDIC.TXT and the attempt at the subsequent files. 

Also, I am interested in some documentation on utilizing the app_sdcard.c?

#include "fat_memory.h"

FIL file;
uint32_t bytes_written;
FRESULT ff_result;

/**
 * @brief Function for demonstrating FAFTS usage.
 */
void fatfs_example(char * cfilename)
{
    static FATFS fs;
    static DIR dir;
    static FILINFO fno;
    
    DSTATUS disk_state = STA_NOINIT;

    // Initialize FATFS disk I/O interface by providing the block device.
    static diskio_blkdev_t drives[] =
    {
            DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
    };

    diskio_blockdev_register(drives, ARRAY_SIZE(drives));

    NRF_LOG_INFO("Initializing disk 0 (SDC)...");
    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
        disk_state = disk_initialize(0);
    }
    if (disk_state)
    {
        NRF_LOG_INFO("Disk initialization failed.");
        SEGGER_RTT_printf(0, "Disk intialization failed.\n");
        return;
    }

    uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
    uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
    NRF_LOG_INFO("Capacity: %d MB", capacity);
    SEGGER_RTT_printf(0, "Capacity: %d MB.\n",capacity);
    NRF_LOG_INFO("Mounting volume...");
    ff_result = f_mount(&fs, "", 1);
    if (ff_result)
    {
        NRF_LOG_INFO("Mount failed.");
        return;
    }

    NRF_LOG_INFO("\r\n Listing directory: /");
    ff_result = f_opendir(&dir, "/");
    if (ff_result)
    {
        NRF_LOG_INFO("Directory listing failed!");
        return;
    }

    do
    {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Directory read failed.");
            return;
        }

        if (fno.fname[0])
        {
            if (fno.fattrib & AM_DIR)
            {
                NRF_LOG_RAW_INFO("   <DIR>   %s",(uint32_t)fno.fname);
            }
            else
            {
                NRF_LOG_RAW_INFO("%9lu  %s", fno.fsize, (uint32_t)fno.fname);
            }
        }
    }
    while (fno.fname[0]);
    NRF_LOG_RAW_INFO("");

    NRF_LOG_INFO("Writing to file %s", cfilename);
    ff_result = f_open(&file, cfilename, FA_READ | FA_WRITE | FA_OPEN_APPEND);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Unable to open or create file: %s", cfilename);
        return;
    }

    ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT *) &bytes_written);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Write failed\r\n.");
    }
    else
    {
        NRF_LOG_INFO("%d bytes written.", bytes_written);
    }

    (void) f_close(&file);
    return;
}


void afilewrite(char * afilename,uint16_t * filebuf)
{
    ff_result = f_open(&file, afilename, FA_OPEN_APPEND | FA_WRITE);
    if (ff_result != FR_OK)
    {
        SEGGER_RTT_printf(0, "unable to create file: %s %x\n",afilename,ff_result);
        return;
    }

    ff_result = f_write(&file, filebuf, sizeof(filebuf) - 1, (UINT *) &bytes_written);
    
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Write failed\r\n.");
        SEGGER_RTT_printf(0,"Write failed\r\n.");
    }
    else
    {
        NRF_LOG_INFO("%d bytes written.", bytes_written);
        SEGGER_RTT_printf(0,"%d bytes written.", bytes_written);
    }

    (void) f_close(&file);
    return;
}
 

Parents
  • I see. Where do you call afilewrite() from? and with what arguments? Have you mounted the volume first?

    Can you try to call f_readdir() first (like in the fatfs example)? Also, can you try to add FA_READ to your f_open() input parameters? E.g. ff_result = f_open(... , FA_OPEN_APPEND | FA_WRITE);

    If that doesn't work, what does f_mount(&fs, "", 1); return if you try to add it before f_open() and f_readdir()?

    BR,

    Edvin

Reply
  • I see. Where do you call afilewrite() from? and with what arguments? Have you mounted the volume first?

    Can you try to call f_readdir() first (like in the fatfs example)? Also, can you try to add FA_READ to your f_open() input parameters? E.g. ff_result = f_open(... , FA_OPEN_APPEND | FA_WRITE);

    If that doesn't work, what does f_mount(&fs, "", 1); return if you try to add it before f_open() and f_readdir()?

    BR,

    Edvin

Children
  • I was trying to call the afilewrite from the button interrupt handler but with no success. I now set a flag in the button_handler and call afilewrite from the main.c loop. The parameters I call afilewrite with are two buffers a filename and a buffer containing the data. But this is only after I have called the fatfs example, which has called f_mount(&fs,"",1), so I assume the disk is mounted until unmounted which I do not see has ever been called.

    I am now writing to the open file consistently with 20 bytes as I have set a flag inside the button handler and call the afilewrite with the two buffers for file name and data. I have also hard coded the number of bytes to write as opposed to getting the number of bytes from the call to sizeof(buffer), with 20.

    I am still unsure as to why I can not call afilewrite from within the button interrupt handler? 

  • It sounds like you are using different instances of &fs., or that fs is not volatile. 

    I don't know where you declare fs, but I see that the example does it in the function fatfs_example().

    Try to declare it as a volatile near the top of your main:

    static volatile FATFS fs;

    The same with your other fatfs variables: dir, fno and file.

    If they are not volatile, they may still think that they use the same instance, but optimization may optimize out the check of the fs. It will think that since the button handler has not updated the fatfs variable, it must be the same as when initialized, and hence not mounted.

Related