FatFs AtMega328P

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone, I'm new here.

 

I want to create a TXT or CSV file in a SD Card with FatFs library and the ATMEGA328P; i've tried with some examples but i haven't gotten anything sad. I've tried some tutorials and used older versions (http://web.archive.org/web/20150715053300/http://elm-chan.org/fsw/ff/ffsample.zip) because i read in this post that newer versions have some problems ( https://www.avrfreaks.net/forum/implementing-fatfs-library-avr-micro). Also I tried to configurate it by myself but honestly i dont understand how to do it for this microcontroller, whenever i tried i got the following error: id returned 1 exit status collect2.exe.  

 

 

The closest I was to achieving it was using another library, with this one I could create the file but I coudn´t write into it (https://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html). 

 

Please if anyone could help me to configurate the library or with an example it would be fantastic (i don't want to use Arduino Software).  

 

Thanks guys.

PostScript:
Sorry, I think this is not the correct forum but I don’t know how to move my publication.

Last Edited: Mon. May 13, 2019 - 06:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FatFs works very well for most of us so you should probably try to diagnose why there's a problem for you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you por reply 

 

Do you know any tutorial? I repeat, I don't know how how to solve this error: id returned 1 exit status collect2.exe

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is not the whole error. Quote the WHOLE error (not that pointless "error list" thing). I'm guessing it's really just an undef ref?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With only 2K of SRAM, wouldn't it be sort of tight to try to do a full FATFS implementation?  Maybe PetitFS would be more workable?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FatFs is fine in 2K

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've read this interesting tutorial:  https://www.avrfreaks.net/forum/tut-c-getting-sdmmc-card-working-painlessly-fatfs  and used a code based on a ATmega1284p (https://github.com/jambu-aj/FatFS )

 

I already tried to configurate my SD pins into diskio.c. My SD pins are SLK-PB5, MISO-PB4, MOSI-PB3 and SS-PD4

 

#define SS        (1<<DDD4)
#define MOSI    (1<<DDB3)
#define MISO    (1<<DDB4)
#define SCK        (1<<DDB5)
#define CS_LOW()    PORTD &= ~SS        /* CS=low */
#define    CS_HIGH()    PORTD |= SS            /* CS=high */
#define SOCKINS        (!(PINB & 0x02))    /* Card detected.   yes:true, no:false, default:true */
#define SOCKWP        (PINB & 0x01)        /* Write protected. yes:true, no:false, default:false */
#define    FCLK_SLOW()    SPCR = 0x52        /* Set slow clock (F_CPU / 64) */
#define    FCLK_FAST()    SPCR = 0x50        /* Set fast clock (F_CPU / 2) */

 

Also i configurated this part in diskio.c:

/*-----------------------------------------------------------------------*/
/* Power Control  (Platform dependent)                                   */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there   */
/* is nothing to do in these functions and chk_power always returns 1.   */

 

static
int power_status (void)        /* Socket power state: 0=off, 1=on */
{
    return 1;//(PORTE & _BV(7)) ? 0 : 1;
}

 

static
void power_on (void)
{
    
    PORTB |= MOSI;    /* Configure SCK/MOSI/CS as output */
    PORTD |= SS;
    DDRB  |= MOSI|SCK;
    DDRD |= SS;
    /* Enable SPI, Master, set clock rate fck/16 */
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

 

static
void power_off (void)
{
    SPCR = 0;                /* Disable SPI function */

    DDRB  &= ~(MOSI|SCK);    /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
    DDRD  &= ~(SS);    /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
    
    PORTB &= ~(MOSI|SCK);
    PORTD  &= ~(SS);    /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
    

}

 

The main code is this, it already complies but gets stuck in f_open.

 

// External 16MHz crystal
 #define F_CPU 16000000UL

 

 // Define baud-rate of the serial port
 #define BAUD 9600
 #define MYUBRR F_CPU/16/BAUD-1

#include <avr/io.h>
#include <string.h>
#include "ff.h"
#include "diskio.h"

 

FIL file;                                               /* Opened file object */
FATFS *fatfs;                                            /* File system object */
DIR dir;                                                /* Directory object   */
FRESULT errCode;                                        /* Error code object  */
FRESULT res;                                            /* Result object      */
UINT bytesRead;                                         /* Bytes read object  */
UINT read;                                              /* Read bytes object  */

int result=1;
char buff[] = "helloworld";
int buff_stat;

 

// function to initialize my USART port on the ATMEGA328P
void USART_Init(unsigned int ubrr)
{
    // Set baud rate
    UBRR0H = (unsigned char)(ubrr>>8);
    // Set frame format to 8 data bits, no parity, 1 stop bit
    UBRR0L = (unsigned char)ubrr;
    // Enable receiver and transmitter
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    // Set frame format: 8data, 1 stop bit
    UCSR0C = (1<<UCSZ00) | (1 << UCSZ01);
}

 

// function to transmit/TX stuff out of the ATMEGA328P and into my laptop
void USART_Transmit(unsigned char data)
{
    // Wait for empty transmit buffer
    while ( !( UCSR0A & (1<<UDRE0)) );
    // Put data into buffer, sends the data
    UDR0 = data;
}

 

// function to transmit/write a whole null terminated string to serial port
void serial_write_str(char* str)
{
    while(*str != 0x00) {
        USART_Transmit(*str);
        str++;
    }
}

 

int main(void)
{

        USART_Init(MYUBRR); // initialize USART
        serial_write_str("PORGRAM INIT\r\n");
        
        errCode = f_mount(0, &fatfs);                       //mount drive number 0
        if(errCode == FR_OK){
            serial_write_str("F_MOUNT\r\n");
        }
        
        /*
        errCode = f_opendir(&dir, "/");                        //root directory
        if(errCode == FR_OK){
            serial_write_str("F_OPENDIR\r\n");
        }
        */
        errCode = f_open(&file, "/data.txt", FA_CREATE_ALWAYS | FA_WRITE);
        if(errCode == FR_OK){
            serial_write_str("F_OPEN OK\r\n");
        }
        else {
            serial_write_str("F_OPEN FAIL\r\n");
        }
        
        serial_write_str("FINISH!\r\n");

    while(1){

    }
}

 This is the complete ZIP, any clue? The tutorial also says that i need to configurate this part in mmc.c

 

/*SPI configuration*/
#define DD_MOSI	DDB5
#define DD_SCK	DDB7
#define DDR_SPI	DDRB
#define DD_SS	4

/* Defines for SD card SPI access */
#define SD_CS_PIN	1
#define SD_CS_PORT	PORTC
#define SD_PWR_PIN	0
#define SD_PWR_PORT	PORTC

 but this example doesn't have it and i couldn't find it in other files (i only have diskio.h, diskio.c, ff.c, ff.h, ffconf.h and integer.h). 

 

Thank you guys.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

When I try to build that I see:

		.././GccApplication1_FatFS_SDCard.c: In function 'main':
D:\GccApplication1_FatFS_SDCard\GccApplication1_FatFS_SDCard\GccApplication1_FatFS_SDCard.c(71,24): warning: passing argument 2 of 'f_mount' from incompatible pointer type [-Wincompatible-pointer-types]
		   errCode = f_mount(0, &fatfs);                       //mount drive number 0
		                        ^

This goes back to:

FATFS *fatfs;                                            /* File system object */

why is this being defined as a pointer to FATFS and not simply an instance of FATFS? Is this because of the example in the user manual?

int main (void)
{
    FATFS *fs;     /* Ponter to the filesystem object */


    fs = malloc(sizeof (FATFS));           /* Get work area for the volume */
    f_mount(fs, "", 0);                    /* Mount the default drive */

Sure, you have two options here - one is to actually just create one (my preference) the other is to create a pointer to one and then malloc() it (like in the manual). I would not advise that. So just change to:

FATFS fatfs;                                            /* File system object */

(no asterisk).

 

One thing this shows is that you must NEVER ignore any build warnings unless you 100% know the reason and why it doesn't matter (but in that case you should fix things so it does not occur).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your response clawson, now the program partially works, sometimes f_open, f_sync and f_close functions return error and sometimes they return ok (i know that because of the message i send to serial port). Most of times microcontroller creates the file when previusly i create another with Arduino's library and i dont know why. I am testing the Atmel Studio 7's Project in an Arduino Nano with this microSD module ( http://datalogger.pbworks.com/w/file/fetch/89507207/Datalogger%20-%20SD%20Memory%20Reader%20Datasheet.pdf ) and a Class-10 32GB microSD. My SD pins are SLK-PB5, MISO-PB4, MOSI-PB3 and SS-PD4

 

Let me explain myself better, when i load the AtmelStudio7's Project i only receive (most of times) this messages:

 

After that, if i load Arduino's SD Library (obviously it always works) with the Arduino IDE to my Arduino Nano these are the messages:

 

 

The interesting part comes here, if i load the AS7's Project to the arduino again (without disconnecting) now it works and i can change my program and load it again and it still working

 

 

The problem comes when i disconnect and reconnect the Arduino Nano to the computer without changing the AS7 project that previously worked. Surprise when i reconnect the program doesnt work

 

 

Any clue?

 

After solving that silly error (fat object was defined as a pointer) the program was still stuck in f_open so i thought that it could be a problem with the SPI communication, i looked at some libraries and one of them said this:

 

DDRB |= (1<<PORTB1) | (1<<PORTB2); // CS on pin 9 SS output //SS as output B2 pin 10

In a forum ( https://www.avrfreaks.net/forum/fatfs-atmega328p-16mhz-can-you-use-fatfs-and-avr-example-16mhz-clock-am-i-wasting-my-time) someone wrote this:

 

IMPORTANT

 

With AVR8 you must make /SS (PB2) an output or ensure that it is a high input to use master SPI.

 

When i added (1<<PORTB2) to my SPI-code now it partially works as i told you. Now it looks like this:

 

 

static
void power_on (void)
{
    /*
    {    // Remove this block if no socket power control
        PORTE &= ~_BV(7);    // Socket power on (PE7=low) 
        DDRE |= _BV(7);
        for (Timer1 = 2; Timer1; );    // Wait for 20ms 
    }
    */
    
    PORTB |= 0b00001000;    /* Configure SCK/MOSI/CS/SS=(1<<PORTB2) as output */
    PORTD |= 0b00010000;    
    
    DDRB  |= 0b00101000;
    DDRB |= (1<<PORTB2);
    DDRD  |= 0b00010000;

    //SPEED 16MHZ/4, uncomment SPSR = (1<<SPI2X) for 16Mhz/2 speed
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);    /* Enable SPI function in mode 0 */
    //SPSR = (1<<SPI2X);            /* SPI 2x mode */
}

 

 Also I added an interruption with the timer in the main program but honestly i dont know if that is really necessary

ISR(TIMER1_COMPA_vect)
{
    disk_timerproc();    
}

Here is the complete ZIP in case you want to check it, could the problem be in the SPI communication yet?

 

Thank you :) 

Attachment(s): 

Last Edited: Tue. May 14, 2019 - 08:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like you aren't doing SCK speed adjustment during the disk_initialize (but it works if the Arduino stuff has already succeeded in card init)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Excuse me but how can i fix that? frown

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have changed this in my mmc_avr.c, I noted that MMC_WP and MMC_CD were not used in all the mmc_avr.c file

/* Port controls  (Platform dependent) */
#define CS        (1<<DDD4)
#define SS        (1<<DDB2)
#define MOSI    (1<<DDB3)
#define MISO    (1<<DDB4)
#define SCK        (1<<DDB5)

 

#define CS_LOW()    PORTD &= ~CS            /* CS=low */
#define    CS_HIGH()    PORTD |= CS            /* CS=high */

 

//#define MMC_CD        (!(PINB & 0x10))    /* Card detected.   yes:true, no:false, default:true */
//#define MMC_WP        (PINB & 0x20)        /* Write protected. yes:true, no:false, default:false */

 

#define    FCLK_SLOW()    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(1<<SPR1);        /* Set slow clock (F_CPU / 64) */
#define    FCLK_FAST()    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);        /* Set fast clock (F_CPU / 4) */

These are my power on and power off functions:

/*-----------------------------------------------------------------------*/
/* Power Control  (Platform dependent)                                   */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there   */
/* is nothing to do in these functions and chk_power always returns 1.   */

 

static
void power_on (void)
{
    /*
    {    // Remove this block if no socket power control
        PORTE &= ~_BV(7);    // Socket power on (PE7=low) 
        DDRE |= _BV(7);
        for (Timer1 = 2; Timer1; );    // Wait for 20ms 
    }
    */
    

    PORTB |= MOSI;    /* Configure SCK/MOSI/CS as output */
    PORTD |= CS;
    
    DDRB  |= MOSI|SCK|SS;
    DDRD |= CS;

    

    //SPEED 16MHZ/4, uncomment SPSR = (1<<SPI2X) for 16Mhz/2 speed
    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR0);    /* Enable SPI function in mode 0 */
    //SPSR = (1<<SPI2X);            /* SPI 2x mode */
}

 

 

static

void power_off (void)
{
    

    SPCR = 0;                /* Disable SPI function */

 

    DDRB  &= ~(MOSI|SCK);    /* Set SCK/MOSI/CS as hi-z, INS#/WP */
    DDRD  &= ~(CS);    /* Set SCK/MOSI/CS as pull-up */
    

    PORTB &= ~(MOSI|SCK);
    PORTD  &= ~(CS);
    
    //PORTB |=  0b00110000;

    

     /*
    {    // Remove this block if no socket power control 
        PORTE |= _BV(7);        // Socket power off (PE7=high) 
        for (Timer1 = 20; Timer1; );    // Wait for 20ms 
    }
    */
}

This is my disk_initialize fuction; i don't know if this is correct but disk_initialize function calls first FCLK_SLOW() and after FCLK_FAST() (why this fuction changes the SPI's speed?): 

DSTATUS disk_initialize (
    BYTE pdrv        /* Physical drive nmuber (0) */
)
{
    BYTE n, cmd, ty, ocr[4];

    if (pdrv) return STA_NOINIT;        /* Supports only single drive */
    power_off();                        /* Turn off the socket power to reset the card */
    if (Stat & STA_NODISK) return Stat;    /* No card in the socket */
    power_on();                            /* Turn on the socket power */
    
FCLK_SLOW();
    for (n = 10; n; n--) xchg_spi(0xFF);    /* 80 dummy clocks */

    ty = 0;
    if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
        
Timer1 = 100;                        /* Initialization timeout of 1000 msec */
        if (send_cmd(CMD8, 0x1AA) == 1) {    /* SDv2? */
            for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);        /* Get trailing return value of R7 resp */
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {                /* The card can work at vdd range of 2.7-3.6V */
                while (Timer1 && send_cmd(ACMD41, 1UL << 30));    /* Wait for leaving idle state (ACMD41 with HCS bit) */
                if (Timer1 && send_cmd(CMD58, 0) == 0) {        /* Check CCS bit in the OCR */
                    for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
                    ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;    /* SDv2 */
                }
            }
        } else {                            /* SDv1 or MMCv3 */
            if (send_cmd(ACMD41, 0) <= 1)     {
                ty = CT_SD1; cmd = ACMD41;    /* SDv1 */
            } else {
                ty = CT_MMC; cmd = CMD1;    /* MMCv3 */
            }
            while (Timer1 && send_cmd(cmd, 0));            /* Wait for leaving idle state */
            if (!Timer1 || send_cmd(CMD16, 512) != 0)    /* Set R/W block length to 512 */
                ty = 0;
        }
    }
    CardType = ty;
    deselect();

    if (ty) {            /* Initialization succeded */
        Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
        
FCLK_FAST();
       } else {            /* Initialization failed */
        power_off();
    }

    return Stat;
}

Also I decided to include a new serial message in my main code to see what was happening with disck_initialize(0) function:

errCode= disk_initialize(0);
    if(errCode == STA_NOINIT){
        serial_write_str("STA_NOINIT\r\n");
    }

and these are the messages that i recieve by serial port:

 

 

Again here is the complete ZIP and complete mmc_avr file in case you want to check them out. I'm confused because it works sometimes. 

 

/*-----------------------------------------------------------------------*/
/* MMCv3/SDv1/SDv2 (in SPI mode) control module                          */
/*-----------------------------------------------------------------------*/
/*
/  Copyright (C) 2014, ChaN, all right reserved.
/
/ * This software is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-------------------------------------------------------------------------*/

#include <avr/io.h>
#include "diskio.h"

/* Port controls  (Platform dependent) */
#define CS        (1<<DDD4)
#define SS        (1<<DDB2)
#define MOSI    (1<<DDB3)
#define MISO    (1<<DDB4)
#define SCK        (1<<DDB5)

#define CS_LOW()    PORTD &= ~CS            /* CS=low */
#define    CS_HIGH()    PORTD |= CS            /* CS=high */

 

//#define MMC_CD        (!(PINB & 0x10))    /* Card detected.   yes:true, no:false, default:true */
//#define MMC_WP        (PINB & 0x20)        /* Write protected. yes:true, no:false, default:false */

 

#define    FCLK_SLOW()    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(1<<SPR1);        /* Set slow clock (F_CPU / 64) */
#define    FCLK_FAST()    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);        /* Set fast clock (F_CPU / 4) */

/*--------------------------------------------------------------------------

   Module Private Functions

---------------------------------------------------------------------------*/

/* Definitions for MMC/SDC command */
#define CMD0    (0)            /* GO_IDLE_STATE */
#define CMD1    (1)            /* SEND_OP_COND (MMC) */
#define    ACMD41    (0x80+41)    /* SEND_OP_COND (SDC) */
#define CMD8    (8)            /* SEND_IF_COND */
#define CMD9    (9)            /* SEND_CSD */
#define CMD10    (10)        /* SEND_CID */
#define CMD12    (12)        /* STOP_TRANSMISSION */
#define ACMD13    (0x80+13)    /* SD_STATUS (SDC) */
#define CMD16    (16)        /* SET_BLOCKLEN */
#define CMD17    (17)        /* READ_SINGLE_BLOCK */
#define CMD18    (18)        /* READ_MULTIPLE_BLOCK */
#define CMD23    (23)        /* SET_BLOCK_COUNT (MMC) */
#define    ACMD23    (0x80+23)    /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24    (24)        /* WRITE_BLOCK */
#define CMD25    (25)        /* WRITE_MULTIPLE_BLOCK */
#define CMD32    (32)        /* ERASE_ER_BLK_START */
#define CMD33    (33)        /* ERASE_ER_BLK_END */
#define CMD38    (38)        /* ERASE */
#define CMD55    (55)        /* APP_CMD */
#define CMD58    (58)        /* READ_OCR */

static volatile
DSTATUS Stat = STA_NOINIT;    /* Disk status */

 

static volatile
BYTE Timer1, Timer2;    /* 100Hz decrement timer */

 

static
BYTE CardType;            /* Card type flags */

/*-----------------------------------------------------------------------*/
/* Power Control  (Platform dependent)                                   */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there   */
/* is nothing to do in these functions and chk_power always returns 1.   */

 

static
void power_on (void)
{
    /*
    {    // Remove this block if no socket power control
        PORTE &= ~_BV(7);    // Socket power on (PE7=low) 
        DDRE |= _BV(7);
        for (Timer1 = 2; Timer1; );    // Wait for 20ms 
    }
    */
    
    
PORTB |= MOSI;    /* Configure SCK/MOSI/CS as output */
    PORTD |= CS;
    
    DDRB  |= MOSI|SCK|SS;
    DDRD |= CS;

    

    //SPEED 16MHZ/4, uncomment SPSR = (1<<SPI2X) for 16Mhz/2 speed
    SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR0);    /* Enable SPI function in mode 0 */
    //SPSR = (1<<SPI2X);            /* SPI 2x mode */
}

 

static
void power_off (void)
{
    
SPCR = 0;                /* Disable SPI function */

    

    DDRB  &= ~(MOSI|SCK);    /* Set SCK/MOSI/CS as hi-z, INS#/WP */
    DDRD  &= ~(CS);    /* Set SCK/MOSI/CS as pull-up */
    PORTB &= ~(MOSI|SCK);
    PORTD  &= ~(CS);
    
    //PORTB |=  0b00110000;

    /*
    {    // Remove this block if no socket power control 
        PORTE |= _BV(7);        // Socket power off (PE7=high) 
        for (Timer1 = 20; Timer1; );    // Wait for 20ms 
    }
    */
}

 

/*-----------------------------------------------------------------------*/
/* Transmit/Receive data from/to MMC via SPI  (Platform dependent)       */
/*-----------------------------------------------------------------------*/

/* Exchange a byte */
static
BYTE xchg_spi (        /* Returns received data */
    BYTE dat        /* Data to be sent */
)
{
    SPDR = dat;
    loop_until_bit_is_set(SPSR, SPIF);
    return SPDR;
}

/* Send a data block fast */
static
void xmit_spi_multi (
    const BYTE *p,    /* Data block to be sent */
    UINT cnt        /* Size of data block (must be multiple of 2) */
)
{
    do {
        SPDR = *p++; loop_until_bit_is_set(SPSR,SPIF);
        SPDR = *p++; loop_until_bit_is_set(SPSR,SPIF);
    } while (cnt -= 2);
}

/* Receive a data block fast */
static
void rcvr_spi_multi (
    BYTE *p,    /* Data buffer */
    UINT cnt    /* Size of data block (must be multiple of 2) */
)
{
    do {
        SPDR = 0xFF; loop_until_bit_is_set(SPSR,SPIF); *p++ = SPDR;
        SPDR = 0xFF; loop_until_bit_is_set(SPSR,SPIF); *p++ = SPDR;
    } while (cnt -= 2);
}

 

/*-----------------------------------------------------------------------*/
/* Wait for card ready                                                   */
/*-----------------------------------------------------------------------*/

static
int wait_ready (    /* 1:Ready, 0:Timeout */
    UINT wt            /* Timeout [ms] */
)
{
    BYTE d;

    Timer2 = wt / 10;
    do
        d = xchg_spi(0xFF);
    while (d != 0xFF && Timer2);

    return (d == 0xFF) ? 1 : 0;
}

 

/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus                                 */
/*-----------------------------------------------------------------------*/

static
void deselect (void)
{
    CS_HIGH();        /* Set CS# high */
    xchg_spi(0xFF);    /* Dummy clock (force DO hi-z for multiple slave SPI) */
}

 

/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready                                    */
/*-----------------------------------------------------------------------*/

static
int select (void)    /* 1:Successful, 0:Timeout */
{
    CS_LOW();        /* Set CS# low */
    xchg_spi(0xFF);    /* Dummy clock (force DO enabled) */
    if (wait_ready(500)) return 1;    /* Wait for card ready */

    deselect();
    return 0;    /* Timeout */
}

 

/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC                                        */
/*-----------------------------------------------------------------------*/

static
int rcvr_datablock (
    BYTE *buff,            /* Data buffer to store received data */
    UINT btr            /* Byte count (must be multiple of 4) */
)
{
    BYTE token;

    Timer1 = 20;
    do {                            /* Wait for data packet in timeout of 200ms */
        token = xchg_spi(0xFF);
    } while ((token == 0xFF) && Timer1);
    if (token != 0xFE) return 0;    /* If not valid data token, retutn with error */

    rcvr_spi_multi(buff, btr);        /* Receive the data block into buffer */
    xchg_spi(0xFF);                    /* Discard CRC */
    xchg_spi(0xFF);

    return 1;                        /* Return with success */
}

 

/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC                                             */
/*-----------------------------------------------------------------------*/

#if    _USE_WRITE
static
int xmit_datablock (
    const BYTE *buff,    /* 512 byte data block to be transmitted */
    BYTE token            /* Data/Stop token */
)
{
    BYTE resp;

    if (!wait_ready(500)) return 0;

    xchg_spi(token);                    /* Xmit data token */
    if (token != 0xFD) {    /* Is data token */
        xmit_spi_multi(buff, 512);        /* Xmit the data block to the MMC */
        xchg_spi(0xFF);                    /* CRC (Dummy) */
        xchg_spi(0xFF);
        resp = xchg_spi(0xFF);            /* Reveive data response */
        if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
            return 0;
    }

    return 1;
}
#endif

 

/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC                                          */
/*-----------------------------------------------------------------------*/

static
BYTE send_cmd (        /* Returns R1 resp (bit7==1:Send failed) */
    BYTE cmd,        /* Command index */
    DWORD arg        /* Argument */
)
{
    BYTE n, res;

    if (cmd & 0x80) {    /* ACMD<n> is the command sequense of CMD55-CMD<n> */
        cmd &= 0x7F;
        res = send_cmd(CMD55, 0);
        if (res > 1) return res;
    }

    /* Select the card and wait for ready except to stop multiple block read */
    if (cmd != CMD12) {
        deselect();
        if (!select()) return 0xFF;
    }

    /* Send command packet */
    xchg_spi(0x40 | cmd);                /* Start + Command index */
    xchg_spi((BYTE)(arg >> 24));        /* Argument[31..24] */
    xchg_spi((BYTE)(arg >> 16));        /* Argument[23..16] */
    xchg_spi((BYTE)(arg >> 8));            /* Argument[15..8] */
    xchg_spi((BYTE)arg);                /* Argument[7..0] */
    n = 0x01;                            /* Dummy CRC + Stop */
    if (cmd == CMD0) n = 0x95;            /* Valid CRC for CMD0(0) + Stop */
    if (cmd == CMD8) n = 0x87;            /* Valid CRC for CMD8(0x1AA) Stop */
    xchg_spi(n);

    /* Receive command response */
    if (cmd == CMD12) xchg_spi(0xFF);        /* Skip a stuff byte when stop reading */
    n = 10;                                /* Wait for a valid response in timeout of 10 attempts */
    do
        res = xchg_spi(0xFF);
    while ((res & 0x80) && --n);

    return res;            /* Return with the response value */
}

 

/*--------------------------------------------------------------------------

   Public Functions

---------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive                                                 */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
    BYTE pdrv        /* Physical drive nmuber (0) */
)
{
    BYTE n, cmd, ty, ocr[4];

    if (pdrv) return STA_NOINIT;        /* Supports only single drive */
    power_off();                        /* Turn off the socket power to reset the card */
    if (Stat & STA_NODISK) return Stat;    /* No card in the socket */
    power_on();                            /* Turn on the socket power */
    
FCLK_SLOW();
    for (n = 10; n; n--) xchg_spi(0xFF);    /* 80 dummy clocks */

    ty = 0;
    if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
        
Timer1 = 100;                        /* Initialization timeout of 1000 msec */
        if (send_cmd(CMD8, 0x1AA) == 1) {    /* SDv2? */
            for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);        /* Get trailing return value of R7 resp */
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {                /* The card can work at vdd range of 2.7-3.6V */
                while (Timer1 && send_cmd(ACMD41, 1UL << 30));    /* Wait for leaving idle state (ACMD41 with HCS bit) */
                if (Timer1 && send_cmd(CMD58, 0) == 0) {        /* Check CCS bit in the OCR */
                    for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
                    ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;    /* SDv2 */
                }
            }
        } else {                            /* SDv1 or MMCv3 */
            if (send_cmd(ACMD41, 0) <= 1)     {
                ty = CT_SD1; cmd = ACMD41;    /* SDv1 */
            } else {
                ty = CT_MMC; cmd = CMD1;    /* MMCv3 */
            }
            while (Timer1 && send_cmd(cmd, 0));            /* Wait for leaving idle state */
            if (!Timer1 || send_cmd(CMD16, 512) != 0)    /* Set R/W block length to 512 */
                ty = 0;
        }
    }
    CardType = ty;
    deselect();

    if (ty) {            /* Initialization succeded */
        Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
        
FCLK_FAST();
    } else {            /* Initialization failed */
        power_off();
    }

    return Stat;
}

 

/*-----------------------------------------------------------------------*/
/* Get Disk Status                                                       */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
    BYTE pdrv        /* Physical drive nmuber (0) */
)
{
    if (pdrv) return STA_NOINIT;    /* Supports only single drive */
    return Stat;
}

 

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    BYTE pdrv,            /* Physical drive nmuber (0) */
    BYTE *buff,            /* Pointer to the data buffer to store read data */
    DWORD sector,        /* Start sector number (LBA) */
    UINT count            /* Sector count (1..128) */
)
{
    BYTE cmd;

    if (pdrv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;

    if (!(CardType & CT_BLOCK)) sector *= 512;    /* Convert to byte address if needed */

    cmd = count > 1 ? CMD18 : CMD17;            /*  READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
    if (send_cmd(cmd, sector) == 0) {
        do {
            if (!rcvr_datablock(buff, 512)) break;
            buff += 512;
        } while (--count);
        if (cmd == CMD18) send_cmd(CMD12, 0);    /* STOP_TRANSMISSION */
    }
    deselect();

    return count ? RES_ERROR : RES_OK;
}

 

/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if _USE_WRITE
DRESULT disk_write (
    BYTE pdrv,            /* Physical drive nmuber (0) */
    const BYTE *buff,    /* Pointer to the data to be written */
    DWORD sector,        /* Start sector number (LBA) */
    UINT count            /* Sector count (1..128) */
)
{
    if (pdrv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;
    if (Stat & STA_PROTECT) return RES_WRPRT;

    if (!(CardType & CT_BLOCK)) sector *= 512;    /* Convert to byte address if needed */

    if (count == 1) {    /* Single block write */
        if ((send_cmd(CMD24, sector) == 0)    /* WRITE_BLOCK */
            && xmit_datablock(buff, 0xFE))
            count = 0;
    }
    else {                /* Multiple block write */
        if (CardType & CT_SDC) send_cmd(ACMD23, count);
        if (send_cmd(CMD25, sector) == 0) {    /* WRITE_MULTIPLE_BLOCK */
            do {
                if (!xmit_datablock(buff, 0xFC)) break;
                buff += 512;
            } while (--count);
            if (!xmit_datablock(0, 0xFD))    /* STOP_TRAN token */
                count = 1;
        }
    }
    deselect();

    return count ? RES_ERROR : RES_OK;
}
#endif

/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL
DRESULT disk_ioctl (
    BYTE pdrv,        /* Physical drive nmuber (0) */
    BYTE cmd,        /* Control code */
    void *buff        /* Buffer to send/receive control data */
)
{
    DRESULT res;
    BYTE n, csd[16], *ptr = buff;
    DWORD csize;

    if (pdrv) return RES_PARERR;

    res = RES_ERROR;

    if (Stat & STA_NOINIT) return RES_NOTRDY;

    switch (cmd) {
    case CTRL_SYNC :        /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
        if (select()) res = RES_OK;
        break;

    case GET_SECTOR_COUNT :    /* Get number of sectors on the disk (DWORD) */
        if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
            if ((csd[0] >> 6) == 1) {    /* SDC ver 2.00 */
                csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
                *(DWORD*)buff = csize << 10;
            } else {                    /* SDC ver 1.XX or MMC*/
                n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
                csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
                *(DWORD*)buff = csize << (n - 9);
            }
            res = RES_OK;
        }
        break;

    case GET_BLOCK_SIZE :    /* Get erase block size in unit of sector (DWORD) */
        if (CardType & CT_SD2) {    /* SDv2? */
            if (send_cmd(ACMD13, 0) == 0) {    /* Read SD status */
                xchg_spi(0xFF);
                if (rcvr_datablock(csd, 16)) {                /* Read partial block */
                    for (n = 64 - 16; n; n--) xchg_spi(0xFF);    /* Purge trailing data */
                    *(DWORD*)buff = 16UL << (csd[10] >> 4);
                    res = RES_OK;
                }
            }
        } else {                    /* SDv1 or MMCv3 */
            if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {    /* Read CSD */
                if (CardType & CT_SD1) {    /* SDv1 */
                    *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
                } else {                    /* MMCv3 */
                    *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
                }
                res = RES_OK;
            }
        }
        break;

    /* Following commands are never used by FatFs module */

    case MMC_GET_TYPE :        /* Get card type flags (1 byte) */
        *ptr = CardType;
        res = RES_OK;
        break;

    case MMC_GET_CSD :        /* Receive CSD as a data block (16 bytes) */
        if (send_cmd(CMD9, 0) == 0        /* READ_CSD */
            && rcvr_datablock(ptr, 16))
            res = RES_OK;
        break;

    case MMC_GET_CID :        /* Receive CID as a data block (16 bytes) */
        if (send_cmd(CMD10, 0) == 0        /* READ_CID */
            && rcvr_datablock(ptr, 16))
            res = RES_OK;
        break;

    case MMC_GET_OCR :        /* Receive OCR as an R3 resp (4 bytes) */
        if (send_cmd(CMD58, 0) == 0) {    /* READ_OCR */
            for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
            res = RES_OK;
        }
        break;

    case MMC_GET_SDSTAT :    /* Receive SD statsu as a data block (64 bytes) */
        if (send_cmd(ACMD13, 0) == 0) {    /* SD_STATUS */
            xchg_spi(0xFF);
            if (rcvr_datablock(ptr, 64))
                res = RES_OK;
        }
        break;

    case CTRL_POWER_OFF :    /* Power off */
        power_off();
        Stat |= STA_NOINIT;
        res = RES_OK;
        break;

    default:
        res = RES_PARERR;
    }

    deselect();

    return res;
}
#endif

 

/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure                                      */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms                        */

void disk_timerproc (void)
{
     BYTE n;
     n = Timer1;                /* 100Hz decrement timer */
     if (n) Timer1 = --n;
     n = Timer2;
     if (n) Timer2 = --n;
}
 

 

Thank you :)

 

Attachment(s): 

Last Edited: Wed. May 15, 2019 - 05:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which version of FatFs is this? The most recent ones say you must not cal disk_initialize() directly.

 

While as a test during initial setup I guess it's OK to call the initialize function just to get an immediate return code - when that is OK then remove everything to do with calling disk_initialize().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's 2015 version, ff_conf.h version: 

/*---------------------------------------------------------------------------/
/  FatFs - FAT file system module configuration file  R0.11 (C)ChaN, 2015
/---------------------------------------------------------------------------*/

 

Last Edited: Wed. May 15, 2019 - 07:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for not answering sooner, but i was a little bit busy, anyway... I think i got something interesting, now i can create a TXT file and it always works!!!

 

How did i "fixed it"? -I say "fixed it" because i'm not pretty sure if that is the correct solution-. After watching all signals in osciloscope i noted that the problem was my CS pin, when it was working it had 5 volts and 0 when it wasn't. So i decided to comment the select and deselect fuctions in mmc_avr.c and as i told you now i can create a file. 

 

I commented everything related to this two functions:

 

/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus                                 */
/*-----------------------------------------------------------------------*/

//static
//void deselect (void)
//{
//    CS_HIGH();        /* Set CS# high */
//    xchg_spi(0xFF);    /* Dummy clock (force DO hi-z for multiple slave SPI) */
//}

/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready                                    */
/*-----------------------------------------------------------------------*/

//static
//int select (void)    /* 1:Successful, 0:Timeout */
//{
//    CS_LOW();        /* Set CS# low */
//    xchg_spi(0xFF);    /* Dummy clock (force DO enabled) */
//    if (wait_ready(500)) return 1;    /* Wait for card ready */

//    deselect();
//    return 0;    /* Timeout */
//}

 

 

Now is time to write into the file but i can't. When i'm trying to write into my file f_write and f_sync functions return FR_DISK_ERR; if i don't use f_write, f_sync works perfectly (returns FR_OK). I tried using only f_write without f_sync but i have the same problem (FR_DISK_ERR). Here is my main code and the complete .ZIP:

 

/*
 * SD_atmega328p.c
 *
 * Created: 13/05/2019 09:23:51 p. m.
 * Author : MoustachedBird
 */ 

 

 // External 16MHz crystal
 #define F_CPU 16000000UL

  // Define baud-rate of the serial port
 #define BAUD 9600
 #define MYUBRR F_CPU/16/BAUD-1

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include "ff.h"

#include "ffconf.h"
#include "integer.h"
#include "diskio.h"

 

 

// setup timer 100 hz
void setupTimer(void)
{
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;
    
    TCCR1B |=(1<<WGM12);      //CTC mode; clock timer comare
    TIMSK1 |= (1<<OCIE1A);  //ENABLE INTERUPTs
    
    OCR1A = 0x4E20; 
    TCCR1B |=  (1<<CS11); //PRESCALER 
    
    //Start interupt
    sei();
}

 

 

// function to initialize my USART port on the ATMEGA328P
void USART_Init(unsigned int ubrr)
{
    // Set baud rate
    UBRR0H = (unsigned char)(ubrr>>8);
    // Set frame format to 8 data bits, no parity, 1 stop bit
    UBRR0L = (unsigned char)ubrr;
    // Enable receiver and transmitter
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    // Set frame format: 8data, 1 stop bit
    UCSR0C = (1<<UCSZ00) | (1 << UCSZ01);
}

 

 

// function to transmit/TX stuff out of the ATMEGA328P and into my laptop
void USART_Transmit(unsigned char data)
{
    // Wait for empty transmit buffer
    while ( !( UCSR0A & (1<<UDRE0)) );
    // Put data into buffer, sends the data
    UDR0 = data;
}

 

 

// function to transmit/write a whole null terminated string to serial port
void serial_write_str(char* str)
{
    while(*str != 0x00) {
        USART_Transmit(*str);
        str++;
    }
}

 

 

int main(void)
{
       FIL file;               /* Opened file object */
       FATFS fatfs;           /* File system object */
       DIR dir;               /* Directory object   */
       FRESULT errCode;       /* Result object      */
       UINT bw;             /* Bytes object  */

      

       setupTimer();
       USART_Init(MYUBRR); // initialize USART
       serial_write_str("PROGRAM INIT\r\n");
       

       errCode= disk_initialize(0);
       serial_write_str("disk_initialize: ");
       if(errCode == STA_NOINIT){
           serial_write_str("STA_NOINIT\r\n");
       }
       else if (errCode == STA_NODISK){
           serial_write_str("STA_NODISK\r\n");
       }
       else if (errCode == STA_PROTECT){
           serial_write_str("STA_PROTECT\r\n");
       }
       else {
           serial_write_str("DONE\r\n");
       }
       
       
       errCode = f_mount(&fatfs,"",0);   //Mount Fat object
       serial_write_str("f_mount: \r");
       if(errCode == FR_OK){
           serial_write_str("FR_OK\r\n");
       }
       if (errCode == FR_INVALID_DRIVE){
           serial_write_str("FR_INVALID_DRIVE\r\n");
       }
       if (errCode == FR_DISK_ERR){
           serial_write_str("FR_DISK_ERR\r\n");
       }
       if (errCode==  FR_NOT_READY){
           serial_write_str("FR_NOT_READY\r\n");
       }
       if (errCode== FR_NOT_ENABLED){
           serial_write_str("FR_NOT_ENABLED\r\n");
       }
       if (errCode==FR_NO_FILESYSTEM){
           serial_write_str("FR_NO_FILESYSTEM\r\n");
       }

 

 

       errCode = f_open(&file, "Sample1.txt",  FA_CREATE_ALWAYS | FA_WRITE );  

       serial_write_str("f_open: \r");
       if(errCode == FR_OK){
           serial_write_str("FR_OK\r\n");
       }
       else if (errCode == FR_DISK_ERR) {
           serial_write_str("FR_DISK_ERR\r\n");
       }
       else if (errCode == FR_INT_ERR) {
           serial_write_str("FR_INT_ERR\r\n");
       }
       else if (errCode == FR_NOT_READY) {
           serial_write_str("FR_NOT_READY\r\n");
       }
       else if (errCode == FR_NO_FILE) {
           serial_write_str("FR_NO_FILE\r\n");
       }
       else if (errCode == FR_NO_PATH) {
           serial_write_str("FR_NO_PATH\r\n");
       }
       else if (errCode == FR_INVALID_NAME) {
           serial_write_str("FR_INVALID NAME\r\n");
       }
       else if (errCode == FR_DENIED) {
           serial_write_str("FR_DENIED\r\n");
       }
       else if (errCode == FR_INVALID_OBJECT) {
           serial_write_str("FR_INVALID_OBJECT\r\n");
       }
       else if (errCode == FR_WRITE_PROTECTED) {
           serial_write_str("FR_WRITE_PROTECTED\r\n");
       }
       else if (errCode == FR_INVALID_DRIVE) {
           serial_write_str("FR_INVALID_DRIVE\r\n");
       }
       else if (errCode == FR_NOT_ENABLED) {
           serial_write_str("FR_NOT_ENABLED\r\n");
       }
       else if (errCode == FR_NO_FILESYSTEM) {
           serial_write_str("FR_NO_FILESYSTEM\r\n");
       }
       else if (errCode == FR_TIMEOUT){
           serial_write_str("FR_TIMEOUT\r\n");
       }
       else if (errCode == FR_LOCKED){
           serial_write_str("FR_LOOKED\r\n");
       }
       else if (errCode == FR_NOT_ENOUGH_CORE){
           serial_write_str("FR_NOT_ENOUGH_CORE\r\n");
       }
       else if (errCode==FR_TOO_MANY_OPEN_FILES){
           serial_write_str("FR_TOO_MANY_OPEN_FILES\r\n");
       }

       
 

       errCode = f_write(&file, "hello_world", 11, &bw);    /* Write data to the file */
       serial_write_str("f_write: \r");
        if(errCode == FR_OK){
            serial_write_str("FR_OK\r\n");
        }
        else if(errCode == FR_DISK_ERR){
            serial_write_str("FR_DISK_ERR\r\n");
        }
        else if(errCode == FR_INT_ERR){
            serial_write_str("FR_INT_ERR\r\n");
        }
        else if(errCode == FR_DENIED){
            serial_write_str("FR_INT_ERR\r\n");
        }
        else if(errCode == FR_INVALID_OBJECT){
            serial_write_str("FR_INVALID_OBJECT\r\n");
        }
        else if(errCode == FR_TIMEOUT){
            serial_write_str("FR_TIMEOUT\r\n");
        }

       
 

       errCode=f_sync(&file);  //Flush cache
       serial_write_str("f_sync: \r");
       if(errCode == FR_OK){
           serial_write_str("FR_OK\r\n");
       }
       else if(errCode == FR_DISK_ERR){
           serial_write_str("FR_DISK_ERR\r\n");
       }
       else if(errCode == FR_INT_ERR){
           serial_write_str("FR_INT_ERR\r\n");
       }
       else if(errCode == FR_INVALID_OBJECT){
           serial_write_str("FR_INVALID_OBJECT\r\n");
       }
       else if(errCode == FR_TIMEOUT){
           serial_write_str("FR_TIMEOUT\r\n");
       }
       

 

       errCode=f_close(&file); //Close the file
       serial_write_str("f_close: \r");
       if(errCode == FR_OK){
           serial_write_str("FR_OK\r\n");
       }
       else if(errCode == FR_DISK_ERR){
           serial_write_str("FR_DISK_ERR\r\n");
       }
       else if(errCode == FR_INT_ERR){
           serial_write_str("FR_INT_ERR\r\n");
       }
       else if(errCode == FR_INVALID_OBJECT){
           serial_write_str("FR_INVALID_OBJECT\r\n");
       }
       else if(errCode == FR_TIMEOUT){
           serial_write_str("FR_TIMEOUT\r\n");
       }

 

 

       serial_write_str("FINISH!\r\n");
      

       while (1) 
       {
        /* Replace with your application code */
        
       }
}

 

 

ISR(TIMER1_COMPA_vect)
{
    disk_timerproc();    
}

 

Thank you :)

Attachment(s): 

Last Edited: Sat. Jun 22, 2019 - 07:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So to be short....

you have put 5V supply on a Sd card that is only supposed to get 3V3 AND eventhough you have not actually selected the card to be interfaced with ( CS line is logical high ( so 3V3 or in your case perhaps even 5V ) ) you have managed to interface with it....