2017-05-12 24 views
1

에서 f_write에 무한 루프가 발생합니다. 지금 며칠 동안 FatFs 모듈을 프로젝트에 구현하려고합니다. 오실로스코프를 사용하여 신호를 볼 수 있으므로 로우 레벨 I/O 구성이 올바르게 구현되었습니다. 하지만 난 제대로 쓰기가 SD-Card에서 작동하는 것 같습니다. 내가 얻은 모든 것은 정확하게 생성 된 내 SD-Card에 빈 파일입니다. 또한 파일의 읽기는 잘 작동합니다. 내가 MPLAB X를 사용하여 디버깅을 할 때, f_write 함수는 결코 루프 for을 남기지 않는다는 것을 발견했습니다. 여기 FatFs를 사용하면 PIC18F46J50 uC

/* 
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; 
} 

내 diskio.c 코드 : 여기

내 main.c의 코드

다음
/*-----------------------------------------------------------------------*/ 
/* 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 

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); 
} 
+0

무엇 f_write에 for 루프를 변경할 것)? f_write를 볼 수 없습니까? 두 개의 코드 벽과 실패한 함수가 둘 다 있지 않습니까? – ThingyWotsit

+0

죄송합니다, 아마도 옳은 것 같습니다. 주 코드를 단축하고 FatFs 라이브러리에서 f_write 함수 코드를 추가했습니다. 당신의 도움을 주셔서 감사합니다! – keko

+0

해결 된 질문의 제목을 편집 할 필요가 없습니다. 이미 다르게 표시되었습니다. – Quentin

답변

1

에서 f_write() 기능이다 믿어 그것 또는 아닙니다, 나는 동일한 정확한 문제가 있고 이것을 몇 시간 동안 망쳤다 ... 그것은있다 XC8 컴파일러가 for 루프 반복자 식을 해석하는 방법과 관련이 있습니다. 실행될 표현식의 수에는 엄격한 제한이있는 것 같습니다. 이 컴파일러는 적어도 경고 ... 그것을 해결하기 위해 던진 경우, 좋은 루프의 바닥에

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

을 추가하고 (

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

감사의 말을 전합니다. 너는 나의 하루를 보냈다! 제발 같은 질문에 직면 수있는 다른 사람이있을 것 같아서 질문을 upvote! – keko