Embedded - SD card - SPI - C -Codevision AVR - Creating and writing a file in an SD card

3.8k views Asked by At

I have an SD card (or SDHC card) connected to a microcontroller via SPI mode. I am using Chan’s FAT library. In this I used CodevisionAVR v2.05.3 example code from help. By using this I read a text document and opened the file using open existing.

However, when I created a new file or tried to write, I couldn't open the file (do f_open). Giving error ERROR: FR_INVALID_OBJECT.

How can I clear this issue?

And my code is:

/* ATmega128 I/O register definitions */
#include <io.h>
#if defined(_CHIP_ATMEGA32_)
#warning using ATMEGA32
#define TIMSK1   TIMSK
#define UCSR0A   UCSRA
#define UCSR0B   UCSRB
//#define UCSR0C   UCSRC    //this is commented out
#define UBRR0H   UBRRH
#define UBRR0L   UBRRL
#define TXEN0    TXEN
#endif

/* FAT on MMC/SD/SD HC card support */
#include <ff.h>


/* printf */
#include <stdio.h>


/* String functions */
#include <string.h>
#include <delay.h>


/* Timer1 overflow interrupt frequency [Hz] */
#define T1_OVF_FREQ 100

/* Timer1 clock prescaler value */
#define T1_PRESC 1024L

/* Timer1 initialization value after overflow */
#define T1_INIT (0x10000L-(_MCU_CLOCK_FREQUENCY_/(T1_PRESC*T1_OVF_FREQ)))


/* USART Baud rate */
#define BAUD_RATE 9600
#define BAUD_INIT (_MCU_CLOCK_FREQUENCY_/(BAUD_RATE*16L)-1)

/* Root directory path */
char path[] = "0:/fil.txt";

/* Text to be written to the file */
char text[]="I like CodeVisionAVR!";


/* 100 Hz timer interrupt generated by ATmega128 Timer1 overflow */
interrupt [TIM1_OVF] void timer_comp_isr(void)
{
    /* Re-initialize Timer1 */
    TCNT1H = T1_INIT >> 8;
    TCNT1L = T1_INIT & 0xFF;

    /* MMC/SD/SD HC card access low level timing function */
    disk_timerproc();
}


/* Error message list */
flash char *flash error_msg[] = {
    "",                         /* Not used */
    "FR_DISK_ERR",
    "FR_INT_ERR",
    "FR_INT_ERR",
    "FR_NOT_READY",
    "FR_NO_FILE",
    "FR_NO_PATH",
    "FR_INVALID_NAME",
    "FR_DENIED",
    "FR_EXIST",
    "FR_INVALID_OBJECT",
    "FR_WRITE_PROTECTED",
    "FR_INVALID_DRIVE",
    "FR_NOT_ENABLED",
    "FR_NO_FILESYSTEM",
    "FR_MKFS_ABORTED",
    "FR_TIMEOUT"
};


/* Display error message and stop */
void error(FRESULT res)
{
    if ((res >= FR_DISK_ERR) && (res <= FR_TIMEOUT))
        printf("ERROR: %p\r\n", error_msg[res]);

    /* Stop here */
    while (1);
}


void main(void)
{
    /* FAT function result */
    FRESULT res;

    /* Will hold the information for logical drive 0: */
    FATFS drive;

    /* Will hold the file information */
    FIL file;

    /* Number of bytes written/read to the file */
    unsigned int nbytes;

    /* File read buffer */
    char buffer[256];


    /* Initialize Timer1 overflow interrupts in Mode 0 (Normal) */
    TCCR1A = 0x00;

    /* clkio/1024 */
    TCCR1B = (1<<CS12)|(1<<CS10);

    /* Timer overflow interrupts will occur with 100Hz frequency */
    TCNT1H = T1_INIT >> 8;
    TCNT1L = T1_INIT & 0xFF;

    /* Enable Timer1 overflow interrupt */
    TIMSK1 = 1 << TOIE1;


    /* Initialize the USART0 TX, 8N1, Baud rate: 19200 */
    UCSR0A = 0;
    UCSR0B = 1 << TXEN0;
    //UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
    UBRR0H = BAUD_INIT >> 8;
    UBRR0L = BAUD_INIT & 0xFF;


    /* Globally enable interrupts */
    #asm("sei")

    PORTB.4 = 0;
    delay_ms(1000);

    printf("\n\nDirectory listing for root of logical drive 0:\r\n");


    /* Mount logical drive 0: */
    if ((res = f_mount(0, &drive)) == FR_OK)
        printf("Logical drive 0: mounted OK\r\n");
    else
        /* An error occurred, display it and stop */
        error(res);


    printf("%s \r\n", path);

    /* Open the file in read mode */
    if ((res = f_open(&file, path, FA_READ)) == FR_OK)
        printf("1_File %s opened OK\r\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Read and display the file's content.
       make sure to leave space for a NULL terminator
       in the buffer, so maximum sizeof(buffer)-1 bytes can be read */
    if ((res=f_read(&file,buffer,sizeof(buffer)-1,&nbytes))==FR_OK)
    {
        printf("%u bytes read\r\n", nbytes);

        /* NULL terminate the char string in the buffer */
        buffer[nbytes+1]=NULL;

        /* Display the buffer contents */
        printf("Read text: \"%s\"\r\n", buffer);
    }
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Close the file */
    if ((res = f_close(&file)) == FR_OK)
        printf("1_File %s closed OK\r\n\n\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Create a new file in the root of drive 0:
       and set write access mode */
    if ((res = f_open(&file,path, FA_OPEN_EXISTING)) == FR_OK)
        printf("File %s opened OK\r\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);

    /* Close the file */
    if ((res = f_close(&file)) == FR_OK)
        printf("2_File %s closed OK\r\n\n\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);

    if ((res = f_open(&file,path, FA_WRITE | FA_CREATE_ALWAYS)) == FR_OK)
        printf("File %s created OK\r\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);

    /* Write some text to the file,
       without the NULL string terminator sizeof(data)-1 */
    if ((res = f_write(&file, text, sizeof(text)-1,&nbytes)) == FR_OK)
        printf("%u bytes written of %u\r\n", nbytes, sizeof(text)-1);

    else
        /* An error occurred, display it and stop */
        error(res);


    /* Close the file */
    if ((res = f_close(&file)) == FR_OK)
        printf("3_File %s closed OK\r\n\n\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Open the file in read mode */
    if ((res = f_open(&file,path,FA_READ)) == FR_OK)
        printf("1_File %s opened OK\r\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Read and display the file's content.
       make sure to leave space for a NULL terminator
       in the buffer, so maximum sizeof(buffer)-1 bytes can be read */
    if ((res = f_read(&file, buffer, sizeof(buffer)-1, &nbytes)) == FR_OK)
    {
        printf("%u bytes read\r\n", nbytes);

        /* NULL terminate the char string in the buffer */
        buffer[nbytes+1] = NULL;

        /* Display the buffer contents */
        printf("Read text: \"%s\"\r\n", buffer);
    }
    else
        /* An error occurred, display it and stop */
        error(res);


    /* Close the file */
    if ((res = f_close(&file)) == FR_OK)
        printf("4_File %s closed OK\r\n", path);
    else
        /* An error occurred, display it and stop */
        error(res);

    printf("done\r\n");

    PORTB.4 = 1;

    /* Stop here */
    while (1);
}

1

There are 1 answers

3
Clifford On

From the documentation:

FR_INVALID_OBJECT

The file/directory object structure is invalid or a null pointer is given. All open objects of the logical drive are invalidated by the volume mount process.

Your file pointer is perhaps null?

Also to consider is that you have configured the library to actually support write operations. In ffconf.h you should have:

#define _FS_READONLY    0