Troubleshooting TF Card Write Operations on Zynq Platforms

Troubleshooting TF Card Write Operations on Zynq Platforms

1. Fundamental Concepts

Previous experiments with Zynq TF card read/write operations demonstrated expected behaviors through serial port outputs. However, deeper investigation into common functions within the "ff.h" header file reveals significant differences when implementing TF card operations. This document outlines frequent challenges encountered during TF card implementation on Zynq platforms, serving as a reference for future development.

2. Practical Implementation Issues

Consider the following complete code example:
#include 
#include "xil_printf.h"
#include "xdevcfg.h"
#include "xparameters.h"
#include "ff.h"

int memory_card_init(void);
int sd_card_test_write(void);

int main()
{
    memory_card_init();
    sd_card_test_write();
    
    while(1)
    {
        ;
    }
    return 0;
}

static FATFS fs_object;

int memory_card_init()
{
    FRESULT result;
    result = f_mount(&fs_object, "", 0);
    
    if(result != FR_OK)
    {
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}

int sd_card_test_write()
{
    FILE file_obj;
    FRESULT result;
    UINT bytes_written;
    const char test_data[] = "t\n";
    
    result = f_open(&file_obj, "test.txt", FA_OPEN_ALWAYS | FA_WRITE);
    
    if(result != FR_OK)
    {
        return XST_FAILURE;
    }
    
    result = f_lseek(&file_obj, f_size(&file_obj));
    result = f_write(&file_obj, test_data, sizeof(test_data), &bytes_written);
    result = f_lseek(&file_obj, f_size(&file_obj));
    result = f_write(&file_obj, "t/n", sizeof("t/n"), &bytes_written);
    
    // Optional: result = f_sync(&file_obj);
    result = f_close(&file_obj);
    
    return result;
}
Key components of this implementation are explained below: The memory_card_init function utilizes f_mount to initialize the SD card partition. This operation typically needs to be performed only once and facilitates subsequent access to the SD card's memory space. The return value verification ensures successful mounting. The f_mount function can also be used to unmount a workspace by calling f_mount(0, NULL), which unmounts the root directory workspace. The sd_card_test_write function contains several critical operations: f_open, f_lseek, f_write, f_sync, f_close, and f_size.

(1) f_open

This function opens or creates files. The first parameter is the address of the file object, the second is the filename string, and the third specifies the access mode. FA_OPEN_ALWAYS: Always opens the file. Creates a new file if it doesn't exist, otherwise opens the existing file. FA_OPEN_EXISTING: Opens only if the file exists. Fails if the file doesn't exist. FA_CREATE_NEW: Creates a new file. Fails if the file already exists. FA_CREATE_ALWAYS: Always creates a new file, overwriting any existing file. FA_WRITE: Write permission mode, allowing data modification. FA_READ: Read permission mode, allowing data access. Note that the first four modes are operational modes, while the last two are permission modes. These can be combined as needed. The distinction between FA_OPEN_ALWAYS and FA_CREATE_ALWAYS is significant: both result in a file, but FA_OPEN_ALWAYS preserves existing content, while FA_CREATE_ALWAYS overwrites it.

(2) f_lseek

This function sets the file operation pointer. The first parameter is the file object address, and the second can be a numerical offset or a special class representing file size. It's commonly used with f_size to position the pointer at the end of the file for append operations.

(3) f_write

This function writes data to the file. The parameters are: file object address, data source address (string, array, etc.), data length, and a pointer to a UINT variable for counting bytes written. A critical consideration is that multiple f_write operations may encounter data corruption if the data blocks are too large. To mitigate this, increase the data size to multiples of 256 bytes (determined through testing). This limitation makes f_write less efficient for SD card operations. Alternative approaches like f_printf may offer better performance.

(4) f_sync

This function flushes cached data to the physical storage, ensuring data integrity. It takes the file object address as its parameter. While not demonstrated in this example, it's recommended for critical applications where data consistency is essential.

(5) f_close

This function closes the file and releases resources. It requires only the file object address as its parameter.
test my_sd function!
test my_sd function!
test my_sd function!
t
t
t
t/n
This sample output demonstrates the contents generated by the code above.

3. Summary

The basic steps for file writing operations can be mapped to PC file operations as follows: Create workspace == Mount storage device Open file == Open file (can create directories with escape characters) Set write position == Click cursor at specific location Write data == Input text via keyboard Verify file == Confirm input correctness Close file == Save and close file Unmount workspace == Eject storage device This parallel illustrates the fundamental workflow of file writing operations. For read operations, the principle remains similar, with f_write replaced by f_read. Both functions share identical parameter structures, with the primary difference being the access mode specified in f_open. When storing data, ensure proper use of string arrays for data containment.

Tags: Zynq TF Card SD Card file operations Embedded Systems

Posted on Wed, 27 May 2026 20:28:09 +0000 by hoffmeister