0
\$\begingroup\$

I have an STM32F7 discovery board and have an image in the SDRAM which I want to store on the SD card as BMP file.

I am using chan's FATFS module with the sddiskio module and the BSP library from ST, like here: http://mikrocontroller.bplaced.net/wordpress/wp-content/uploads/2015/08/f746_fatfs_v100.zip

Initializing, mounting and creating a file works fine, but when writing the actual image data, the f_write function fails after some time with the FR_DISK_ERR error (hard error in the low level diskio layer).

Here is my current testcode, which should give me a 640x480 RGB565 image with 1 pixel wide vertical bars:

  void SD_write_image(void)
{
    FIL file; //file object
    char file_str[30] = "image01.bmp";//filename

    int32_t i, j;
    //uint32_t tmp = 0;

    uint16_t img_buf[640];

    uint32_t bytes_written;

    FATFS_t fs_status;
    FRESULT fs_error;

    file_str[6] = (char)((img_counter % 10) + 48);//increase the filename
    file_str[5] = (char)(((img_counter/10) % 10) + 48);

    fs_status = SD_Mount();
    if(fs_status != FATFS_OK) Filesystem_ErrorHandler();

    fs_status = SD_OpenFile(&file, file_str, F_WR_CLEAR);
    if(fs_status != FATFS_OK) Filesystem_ErrorHandler();

    fs_error = f_write(&file, bmp_fileheader640, 138, &bytes_written);

    if(fs_error != FR_OK)
    {
        Filesystem_ErrorHandler();
    }

    for(j = 0; j < 640; j++)
    {
        if((j%2) == 0) img_buf[j] = 0xfb54;
        else img_buf[j] = 0xF7E0;
    }

    for(i = 0; i < 480; i++)//480 lines
    {
        fs_error = f_write(&file, img_buf, 1280, &bytes_written);
        if(fs_error != FR_OK)
        {
            Filesystem_ErrorHandler();
        }
        //tmp = tmp + 640*sizeof(uint8_t);
    }

    fs_status = SD_CloseFile(&file);
    if(fs_status != FATFS_OK) Filesystem_ErrorHandler();

    fs_status = SD_UnMount();
    if(fs_status != FATFS_OK) Filesystem_ErrorHandler();

    img_counter++;
    sprintf((char*)text, "Images stored: %d", (int)img_counter);
    BSP_LCD_DisplayStringAt(5, LINE(9), (uint8_t*)text, LEFT_MODE);
}

If it succeeds, the image looks like this:

Correct test image

However, the SD card interface is very unstable, sometimes it works, sometimes it does not.

Update:

I was able to track down the SD Low Level Error. It occurs in the HAL_SD_WriteBlocks function. The error code is SD_TX_UNDERRUN which means there is an underrun in the transmit FIFO of the SD card interface.

What can be the reason for this?


2nd Update:

Here is my bmp header, but I think the mistake is not in here:

uint8_t bmp_fileheader320[138]=
{
        0x42, 0x4D,
        0x8A, 0x58,
        0x02, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x8A, 0x00,
        0x00, 0x00,
        0x7C, 0x00,
        0x00, 0x00,
        0x40, 0x01,
        0x00, 0x00,
        0xf0, 0x00,
        0x00, 0x00,
        0x01, 0x00,
        0x10, 0x00,
        0x03, 0x00,
        0x00, 0x00,
        0x00, 0x58,
        0x02, 0x00,
        0x13, 0x0B,
        0x00, 0x00,
        0x13, 0x0B,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0xF8,
        0x00, 0x00,
        0xE0, 0x07,
        0x00, 0x00,
        0x1F, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x42, 0x47,
        0x52, 0x73,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x02, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00,
        0x00, 0x00
};
\$\endgroup\$
9
  • 2
    \$\begingroup\$ Why do you open & close the file inside the for loop? Couldn't you just open it once before you start and then close it at the end? Just seems like you're looking for trouble with all the open/close/open/close... \$\endgroup\$
    – brhans
    Commented Jan 27, 2016 at 14:38
  • \$\begingroup\$ I also tried it this way, the error is still present. \$\endgroup\$
    – deinoppa
    Commented Jan 27, 2016 at 14:45
  • \$\begingroup\$ Try another sd card. Those can have bad sectors, too. \$\endgroup\$
    – Turbo J
    Commented Jan 27, 2016 at 18:37
  • \$\begingroup\$ Show us your BMP header. Where is it created? \$\endgroup\$ Commented Jan 27, 2016 at 19:06
  • \$\begingroup\$ You have a File System issue, and you have an image format issue. Separate these problems, and fix them one at a time. Create file with some test pattern, probably text so you can recognize an issue. Once you've established that you can reliably write a file, move on to the image issue. Unless you can pin down the file issue, you're not going to know where your image problem is. \$\endgroup\$ Commented Jan 27, 2016 at 19:33

2 Answers 2

1
\$\begingroup\$

Try moving this part:

for(j = 0; j < 640; j++) { 
    if((j%2) == 0) 
        img_buf[j] = 0xfb54; 
    else 
        img_buf[j] = 0xF7E0; 
}

To the position immediately before the SD_Mount() call at the top. If this doesnt work, comment out the error-checking IF blocks (after your f_writes) and try again. Underrun usually means the TX fifo buffer isnt getting filled fast enough with data, so this might be a solution.

\$\endgroup\$
2
  • \$\begingroup\$ This does not chage the behaviour. The problem is if an error occurs in the low level diskio functions, f_write aborts the write task and locks the file. Out of 11 attempts I got 6 complete files (with 601kB size) and 5 incomplete (ranging from 3 kB to 482 kB). The error seems to be quite random to me... \$\endgroup\$
    – deinoppa
    Commented Jan 28, 2016 at 13:11
  • \$\begingroup\$ Yes, I tried it without my error handler section. That gives me the results I described in my first comment. \$\endgroup\$
    – deinoppa
    Commented Jan 28, 2016 at 13:27
1
\$\begingroup\$

I have had the exact same problem. Try to disable INTERRUPT service routine before to call the f_write and when you have finished writing, enable the INTERRUPT.

For example:

__disable_irq();
if (f_write(....)==FR_OK)
{
}
else
{
}
__enable_irq();
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.