1 /*-----------------------------------------------------------------------*/ 2 /* Forward data to the stream directly (available on only tiny cfg) */ 3 /*-----------------------------------------------------------------------*/ 4 5 FRESULT f_forward ( 6 FIL *fp, /* Pointer to the file object */ 7 UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ 8 UINT btr, /* Number of bytes to forward */ 9 UINT *bf /* Pointer to number of bytes forwarded */ 10 ) 11 { 12 FRESULT res; 13 DWORD remain, clst, sect; 14 UINT rcnt; 15 BYTE csect; 16 17 18 *bf = 0; /* Initialize byte counter */ 19 20 res = validate(fp->fs, fp->id); /* Check validity of the object */ 21 if (res != FR_OK) LEAVE_FF(fp->fs, res); 22 if (fp->flag & FA__ERROR) /* Check error flag */ 23 LEAVE_FF(fp->fs, FR_INT_ERR); 24 if (!(fp->flag & FA_READ)) /* Check access mode */ 25 LEAVE_FF(fp->fs, FR_DENIED); 26 27 remain = fp->fsize - fp->fptr; 28 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ 29 30 for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ 31 fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { 32 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ 33 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ 34 if (!csect) { /* On the cluster boundary? */ 35 clst = (fp->fptr == 0) ? /* On the top of the file? */ 36 fp->sclust : get_fat(fp->fs, fp->clust); 37 if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); 38 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); 39 fp->clust = clst; /* Update current cluster */ 40 } 41 } 42 sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ 43 if (!sect) ABORT(fp->fs, FR_INT_ERR); 44 sect += csect; 45 if (move_window(fp->fs, sect)) /* Move sector window */ 46 ABORT(fp->fs, FR_DISK_ERR); 47 fp->dsect = sect; 48 rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ 49 if (rcnt > btr) rcnt = btr; 50 rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); 51 if (!rcnt) ABORT(fp->fs, FR_INT_ERR); 52 } 53 54 LEAVE_FF(fp->fs, FR_OK); 55 }
函数功能:读取文件数据并将其转发到数据流设备。
描述:
f_forward函数当_USE_FORWARD == 1并且_FS_TINY == 1时可用。
f_forward函数从文件中读取数据并将数据转发到输出流,而不使用数据缓冲区。这适用于小存储系统,因为它在应用模块中不需要任何数据缓冲区。文件对象的文件指针以转发的字节数增加。如果*ByteFwd <ByteToFwd并且没有错误,则意味着由于文件结束或在数据传输过程中流忙,请求的字节不能被传输。
例(音频播放):
1 /*-----------------------------------------------------------------------*/ 2 /* 示例代码:数据传输函数,将被f_forward函数调用 */ 3 /*-----------------------------------------------------------------------*/ 4 5 UINT out_stream ( /* 返回已发送字节数或流状态 */ 6 const BYTE *p, /* 将被发送的数据块的指针 */ 7 UINT btf /* >0: 传输调用(将被发送的字节数)。0: 检测调用 */ 8 ) 9 { 10 UINT cnt = 0; 11 12 if (btf == 0) { /* 检测调用 */ 13 /* 返回流状态(0: 忙,1: 就绪) */ 14 /* 当检测调用时,一旦它返回就绪,那么在后续的传输调用时,它必须接收至少一个字节,或者f_forward将以FR_INT_ERROR而失败。 */ 15 if (FIFO_READY) cnt = 1; 16 } 17 else { /* 传输调用 */ 18 do { /* 当有数据要发送并且流就绪时重复 */ 19 FIFO_PORT = *p++; 20 cnt++; 21 } while (cnt < btf && FIFO_READY); 22 } 23 24 return cnt; 25 } 26 27 28 /*-----------------------------------------------------------------------*/ 29 /* 示例代码:使用f_forward函数 */ 30 /*-----------------------------------------------------------------------*/ 31 32 FRESULT play_file ( 33 char *fn /* 待播放的音频文件名的指针 */ 34 ) 35 { 36 FRESULT rc; 37 FIL fil; 38 UINT dmy; 39 40 /* 以只读模式打开音频文件 */ 41 rc = f_open(&fil, fn, FA_READ); 42 43 /* 重复,直到文件指针到达文件结束位置 */ 44 while (rc == FR_OK && fil.fptr < fil.fsize) { 45 46 /* 任何其他处理... */ 47 48 /* 定期或请求式填充输出流 */ 49 rc = f_forward(&fil, out_stream, 1000, &dmy); 50 } 51 52 /* 该只读的音频文件对象不需要关闭就可以被丢弃 */ 53 return rc; 54 }
FATFS 初学之 f_forward
时间: 2024-11-05 21:37:39