From 69433ff94c7890e4e2a0f8df746a846d8158ad97 Mon Sep 17 00:00:00 2001 From: Martin Guy Date: Wed, 13 Jul 2011 18:53:18 +0200 Subject: [PATCH] Fix MMCFS timeout code to wait for >= the required timeout MMCFS timeouts work by counting ticks of the virtual timer, which is free-running and could tick immediately, giving a zero timeout. This fixes the calculation of the number of ticks to wait for to set up an N-millisecond timeout, ensuring that the actual timeout used is >= N. --- src/elua_mmc.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/elua_mmc.c b/src/elua_mmc.c index f62939ce..2208682a 100644 --- a/src/elua_mmc.c +++ b/src/elua_mmc.c @@ -67,6 +67,25 @@ BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */ static BYTE PowerFlag = 0; /* indicates if "power" is on */ +/*-----------------------------------------------------------------------*/ +/* Find the value to set in Timer1 or Timer2 to obtain a timeout of at */ +/* least N milliseconds. */ +/* */ +/* Timer1 and Timer2 are decremented by the virtual timer interrupt, */ +/* which is free-running and will sometimes decrement TimerN immediately */ +/* so to wait for N ms to pass, you need to wait for N+1 ticks to occur. */ +/* */ +/* Usage example: */ +/* Timer1 = set_Timer_ms(N); */ +/* do { whatever } while (Timer1); */ +/*-----------------------------------------------------------------------*/ + +static UINT set_Timer_ms(UINT ms) +{ + UINT ticks = ms / MMCFS_TICK_MS; + return (ticks > 0 ? ticks : 1) + 1; +} + /*-----------------------------------------------------------------------*/ /* Transmit a byte to MMC via SPI (Platform dependent) */ /*-----------------------------------------------------------------------*/ @@ -109,7 +128,7 @@ BYTE wait_ready (void) { BYTE res; - Timer2 = 500/MMCFS_TICK_MS; /* Wait for ready in timeout of 500ms */ + Timer2 = set_Timer_ms(500); /* Wait for ready in timeout of 500ms. */ rcvr_spi(); do res = rcvr_spi(); @@ -205,8 +224,7 @@ BOOL rcvr_datablock ( { BYTE token; - - Timer1 = 100/MMCFS_TICK_MS ? 100/MMCFS_TICK_MS : 1; + Timer1 = set_Timer_ms(100); do { /* Wait for data packet in timeout of 100ms */ token = rcvr_spi(); } while ((token == 0xFF) && Timer1); @@ -326,7 +344,7 @@ DSTATUS disk_initialize ( SELECT(); /* CS = L */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ - Timer1 = 1000/MMCFS_TICK_MS; /* Initialization timeout of 1000 msec */ + Timer1 = set_Timer_ms(1000); /* Initialization timeout of 1000 msec */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */ for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ @@ -583,6 +601,7 @@ DRESULT disk_ioctl ( /*-----------------------------------------------------------------------*/ /* Device Timer Interrupt Procedure (Platform dependent) */ /*-----------------------------------------------------------------------*/ + /* This function must be called in period of 10ms */ void disk_timerproc( void )