Using FatFs causes infinite loop in f_write on PIC18F46J50 uC

1

Im trying to implement the FatFs module for a project for several days now. My low-level I/O configurations are correctly implemented as i can see the signals using an oscilloscope. But i cant seem to get a proper write working on the SD-Card. All i get is an empty file on my SD-Card which gets created correctly. Also a read of the files works just fine. As i was debugging using MPLAB X i found that the f_write function never leaves a for loop.

Here is my main.c code:

/*
Main application
*/

 FATFS FatFs;
 FIL fil1, fil2;

void main(void)
{
            SYSTEM_Init();

            BYTE buffer[4];
            UINT bw, br;
            FRESULT fr;

            if(f_mount(&FatFs, "", 1) == FR_OK)
            {
                    //open source file
                   fr = f_open(&fil1, "READ.TXT", FA_READ); 
                   if(fr) return; 

                   //create destination file
                   fr = f_open(&fil2, "WRITE.TXT", FA_WRITE | FA_CREATE_ALWAYS);
                   if(fr) return;

                   //copy 1 to 2

                   for(;;){

                       fr = f_read(&fil1, buffer, sizeof buffer, &br);
                       if(fr || br == 0) break;

                       fr = f_write(&fil2, buffer, br, &bw);
                       if(fr || bw < br) break;

                   }
//                      const char *writedata = &write;
//                       //f_printf(&fil, "%d", 1234);
//                       f_write(&fil, writedata, strlen(writedata), &bw);

                       f_close(&fil1);
                       f_close(&fil2);

                       f_mount(NULL, "", 0);

                   }

    return;
}

Here is my diskio.c code:

/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/

#ifdef __XC8
#include <p18f46j50.h>
#endif

#ifndef __XC8
#include <p18cxxx.h>
#endif

#include "diskio.h" /* FatFs lower layer API */
#include "sdspi.h"
#include "sdctrl.h"

/* Definitions of physical drive number for each drive */
#define DEV_RAM     0   /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC     1   /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB     2   /* Example: Map USB MSD to physical drive 2 */

#define _XTAL_FREQ 8000000


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

   Module Private Functions

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

/* Definitions for 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 */


/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC      0x01        /* MMC ver 3 */
#define CT_SD1      0x02        /* SD ver 1 */
#define CT_SD2      0x04        /* SD ver 2 */
#define CT_SDC      (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK    0x08        /* Block addressing */


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

static
BYTE CardType;          /* Card type flags */



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

static
BYTE wait_ready (void)  /* 1:Ready, 0:Timeout */
{
    UINT tmr;


    for (tmr = 5000; tmr; tmr--) {  /* Wait for ready in timeout of 500ms */
        if (sdspi_rxByte() == 0xFF) break;
        __delay_us(100);
    }

    return tmr ? 1 : 0;
}



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

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



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

static
BYTE select (void)  /* 1:Successful, 0:Timeout */
{
    sd_select();    /* Set CS# low */
    sdspi_rxByte(); /* Dummy clock (force DO enabled) */
    if (wait_ready()) return 1; /* Wait for card ready */

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



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

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


    for (tmr = 2000; tmr; tmr--) {  /* Wait for data packet in timeout of 200ms */
        token = sdspi_rxByte();
        if (token != 0xFF) break;
//      __delay_us(100);
    }
    if (token != 0xFE) return 0;    /* If not valid data token, retutn with error */

    do
        *buff++ = sdspi_rxByte();       /* Receive the data block into buffer */
    while (--btr);
    sdspi_rxByte();                 /* Discard CRC */
    sdspi_rxByte();

    return 1;                   /* Return with success */
}



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

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


    if (!wait_ready()) return 0;

    sdspi_txByte(token);            /* Xmit data token */
    if (token != 0xFD) {    /* Is data token */
        i = 512;
        do
        {
            sdspi_txByte(*buff++);              /* Xmit the data block to the MMC */
            __delay_us(100);
        }while (--i);


        sdspi_rxByte();                     /* CRC (Dummy) */
        sdspi_rxByte();

        resp = sdspi_rxByte();                  /* Reveive data response */
        if ((resp & 0x1F) != 0x05)      /* If not accepted, return with error */
            return 0;
    }

    return 1;
}
#endif



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

/* NOTE: XC8 compiler is unable to allow recursion,
/  so the send_cmd function had to be divided */

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


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

    /* Send command packet */
    sdspi_txByte(0x40 | cmd);               /* Start + Command index */
    sdspi_txByte((BYTE)(arg >> 24));        /* Argument[31..24] */
    sdspi_txByte((BYTE)(arg >> 16));        /* Argument[23..16] */
    sdspi_txByte((BYTE)(arg >> 8));     /* Argument[15..8] */
    sdspi_txByte((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 */
    sdspi_txByte(n);

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

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

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


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

#ifdef __XC8
    return __send_cmd(cmd, arg);    /* Return with the response value */
#else
    /* Select the card and wait for ready except to stop multiple block read */
    if (cmd != CMD12) {
        sd_deselect();
        if (!select()) return 0xFF;
    }

    /* Send command packet */
    sdspi_txByte(0x40 | cmd);               /* Start + Command index */
    sdspi_txByte((BYTE)(arg >> 24));        /* Argument[31..24] */
    sdspi_txByte((BYTE)(arg >> 16));        /* Argument[23..16] */
    sdspi_txByte((BYTE)(arg >> 8));     /* Argument[15..8] */
    sdspi_txByte((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 */
    sdspi_txByte(n);

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

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



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

   Public Functions

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


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

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


    if (pdrv) return STA_NOINIT;        /* Supports only single drive */

    if (Stat & STA_NODISK) return Stat; /* No card in the socket */

    sdspi_enable();                         /* Enable the SPI port */
    sdspi_setSlowMode();                    /* Setup for slow mode */
    for (n = 10; n; n--) sdspi_rxByte();    /* 80 dummy clocks */

    ty = 0;
    if (send_cmd(CMD0, 0) == 1) {           /* Enter Idle state */
        if (send_cmd(CMD8, 0x1AA) == 1) {   /* SDv2? */
            for (n = 0; n < 4; n++) ocr[n] = sdspi_rxByte();    /* 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 */
                for (tmr = 1000; tmr; tmr--) {          /* Wait for leaving idle state (ACMD41 with HCS bit) */
                    if (send_cmd(ACMD41, 1UL << 30) == 0) break;
                    __delay_ms(1);
                }
                if (tmr && send_cmd(CMD58, 0) == 0) {       /* Check CCS bit in the OCR */
                    for (n = 0; n < 4; n++) ocr[n] = sdspi_rxByte();
                    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 */
            }
            for (tmr = 1000; tmr; tmr--) {          /* Wait for leaving idle state */
                if (send_cmd(cmd, 0) == 0) break;
                __delay_ms(1);
            }
            if (!tmr || 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 */
        sdspi_setFastMode();
    }

    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 */
                sdspi_rxByte();
                if (rcvr_datablock(csd, 16)) {              /* Read partial block */
                    for (n = 64 - 16; n; n--) sdspi_rxByte();   /* 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++ = sdspi_rxByte();
            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 */
            sdspi_rxByte();
            if (rcvr_datablock(ptr, 64))
                res = RES_OK;
        }
        break;

    default:
        res = RES_PARERR;
    }

    deselect();

    return res;
}
//#endif

Here is the f_write() function from the ff.c

FRESULT f_write (
    FIL* fp,            /* Pointer to the file object */
    const void* buff,   /* Pointer to the data to be written */
    UINT btw,           /* Number of bytes to write */
    UINT* bw            /* Pointer to number of bytes written */
)
{
    FRESULT res;
    FATFS *fs;
    DWORD clst, sect;
    UINT wcnt, cc, csect;
    const BYTE *wbuff = (const BYTE*)buff;


    *bw = 0;    /* Clear write byte counter */
    res = validate(&fp->obj, &fs);          /* Check validity of the file object */
    if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);   /* Check validity */
    if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);    /* Check access mode */

    /* Check fptr wrap-around (file size cannot reach 4GiB on FATxx) */
    if ((!_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
        btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
    }



// HERE DOES THE LOOP HAPPEN

    for ( ;  btw;                           /* Repeat until all data written */
        wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize, *bw += wcnt, btw -= wcnt) {
        if (fp->fptr % SS(fs) == 0) {       /* On the sector boundary? */
            csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1);    /* Sector offset in the cluster */
            if (csect == 0) {               /* On the cluster boundary? */
                if (fp->fptr == 0) {        /* On the top of the file? */
                    clst = fp->obj.sclust;  /* Follow from the origin */
                    if (clst == 0) {        /* If no cluster is allocated, */
                        clst = create_chain(&fp->obj, 0);   /* create a new cluster chain */
                    }
                } else {                    /* On the middle or end of the file */
#if _USE_FASTSEEK
                    if (fp->cltbl) {
                        clst = clmt_clust(fp, fp->fptr);    /* Get cluster# from the CLMT */
                    } else
#endif
                    {
                        clst = create_chain(&fp->obj, fp->clust);   /* Follow or stretch cluster chain on the FAT */
                    }
                }
                if (clst == 0) break;       /* Could not allocate a new cluster (disk full) */
                if (clst == 1) ABORT(fs, FR_INT_ERR);
                if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
                fp->clust = clst;           /* Update current cluster */
                if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */
            }
#if _FS_TINY
            if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);    /* Write-back sector cache */
#else
            if (fp->flag & FA_DIRTY) {      /* Write-back sector cache */
                if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
                fp->flag &= (BYTE)~FA_DIRTY;
            }
#endif
            sect = clust2sect(fs, fp->clust);   /* Get current sector */
            if (!sect) ABORT(fs, FR_INT_ERR);
            sect += csect;
            cc = btw / SS(fs);              /* When remaining bytes >= sector size, */
            if (cc) {                       /* Write maximum contiguous sectors directly */
                if (csect + cc > fs->csize) {   /* Clip at cluster boundary */
                    cc = fs->csize - csect;
                }
                if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
#if _FS_MINIMIZE <= 2
#if _FS_TINY
                if (fs->winsect - sect < cc) {  /* Refill sector cache if it gets invalidated by the direct write */
                    mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
                    fs->wflag = 0;
                }
#else
                if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
                    mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
                    fp->flag &= (BYTE)~FA_DIRTY;
                }
#endif
#endif
                wcnt = SS(fs) * cc;     /* Number of bytes transferred */
                continue;
            }
#if _FS_TINY
            if (fp->fptr >= fp->obj.objsize) {  /* Avoid silly cache filling on the growing edge */
                if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
                fs->winsect = sect;
            }
#else
            if (fp->sect != sect &&         /* Fill sector cache with file data */
                fp->fptr < fp->obj.objsize &&
                disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) {
                    ABORT(fs, FR_DISK_ERR);
            }
#endif
            fp->sect = sect;
        }
        wcnt = SS(fs) - (UINT)fp->fptr % SS(fs);    /* Number of bytes left in the sector */
        if (wcnt > btw) wcnt = btw;                 /* Clip it by btw if needed */
#if _FS_TINY
        if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
        mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt);  /* Fit data to the sector */
        fs->wflag = 1;
#else
        mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt);  /* Fit data to the sector */
        fp->flag |= FA_DIRTY;
#endif
    }

    fp->flag |= FA_MODIFIED;                /* Set file change flag */

    LEAVE_FF(fs, FR_OK);
}
c
sd-card
fatfs
asked on Stack Overflow May 12, 2017 by keko • edited May 19, 2017 by Quentin

2 Answers

2

Believe it or not, I had the same exact problem and messed with this for hours... It has something to do with how the XC8 compiler is interpreting the for loop iterator expressions. It looks like there's a hard limit on the number of expressions it will execute. It would be nice if the compiler at least threw a warning... to fix it, add

    fp->fptr += wcnt;
    fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize;
    *bw += wcnt;
    btw -= wcnt;

to the bottom of the for loop, and change the for loop to

    for ( ;  btw; wbuff += wcnt){//, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize, *bw += wcnt, btw -= wcnt) {
answered on Stack Overflow May 12, 2017 by James • edited May 16, 2017 by James
0

(edit) This issue semms to be corrected in FF13 (/edit)

Same problem here. FF12c, XC8 compiler (v1.43) really seems to have a problem with the reinitialisation arguments. If you change the order and move the conditional operator ? : term to the end it works.

//  wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize, *bw += wcnt, btw -= wcnt) 
    wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) 

The previous solution shown obove does not work for me if the first write access is for a complete sector. Because of the continue instruction the program does not execute the added code at the bottom of the loop!

-vloki-

answered on Stack Overflow Jan 29, 2019 by user10984475 • edited Jan 29, 2019 by user10984475

User contributions licensed under CC BY-SA 3.0