This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC2368 SD read problem

i'm using the example program for LPC236X for testing the SD card by writing to it and verifying i'm reading back the same value.
the writing goes fluently without any problems.
the reading is stacked.
i realized that i don't get any data from the SD in the read process and the processor is waiting in the:

while ( !(MCI_STATUS & MCI_RX_DATA_AVAIL) );

i'm using an old 16MB SD card.
even when i'm trying to read from the card the SD_Status by using ACMD13 the card doesn't send any data.

when i insert the card to my digital camera i get the message "unable to use the card", but when i connect the camera to my laptop i can read and write to the card as it is detected by the laptop as removable storage.
any idea regarding the possible problem i have?

  • Hi Meir Sudry, Don't read the data in FIFO mode, use GPDMA mode.
    In my case Iam getting Receive Overrun error in FIFO mode so i shifted to DMA mode.
    I think You are writing the data on 0th block, which is a boot sector for file system, which was corrupted.
    When the bootsector was corrupted it won't work in camera because it won't format(not sure my guess) and if you connect to PC it shows as a removable disk but it will ask to format before trying to open it.

    Can you tell me which IDE and board you are using?

  • Hi, thanks for the reply.
    i realized that writing to sector 0 will be a problem, that's why i tried to read SD_Status and find out the size of the protected area. any how i added 0x1000* block_size as base address so i bypassed this problem.
    i think that in the example program there is a bug in the RX_Active handling, the conditions for setting the blocksize are wrong. i attached here this part of the code. i turned the original code into remark and located my substitute code

            if ( MCI_STATUS & MCI_RX_ACTIVE )
            {
                    DataRxActiveCount++;
    #if MCI_DMA_ENABLED
                    while ( !(GPDMA_RAW_INT_TCSTAT & 0x02) );
                    GPDMA_INT_TCCLR |= 0x02;
    #else
                    while ( RXBlockCounter < BLOCK_LENGTH )
                    {
    //                      if ( !(MCI_STATUS & MCI_RX_FIFO_FULL) )
                            if ( MCI_STATUS & MCI_RX_FIFO_FULL)
                            {
                                    blockSize = FIFO_SIZE * 4;
                            }
                            else if ( MCI_STATUS & MCI_RX_HALF_FULL )
                            {
                                    blockSize = (FIFO_SIZE/2) * 4;
                            }
    //                      else if ( MCI_STATUS & MCI_RX_FIFO_EMPTY )
                            else if (!( MCI_STATUS & MCI_RX_FIFO_EMPTY ))
                            {
                                    blockSize = 1 * 4;
                            }
                            else
                            {
                                    blockSize = 0;
                            }
    


    i'm using the Keil uVision 3 as IDE and my board is CP-JR ARM7 LPC2368 from Futurlec.
    those are my first steps with ARM series (3 weeks since first time i use it) so i didn't cover yet the DMA part. i plan that (DMA) to be the next feature i'll try to get through.

  • Hi Meir, In your testing you got receive overrun,transmit underrun and data timeout errors during read and write from the card. When these errors occurred what you did?

    In my case i got above errors and I tried to read and write once again from the above errors,but it's not working. You have any idea how to overcome these errors?

  • Hi.did you try the code i attached or the original code? i didn't get any of the above mentioned errors. i was afraid that the SW is stuck in nested interrupt so i trap all interrupts handling with notices to my LCD display, but the program doesn't go there. so, as far as i can see this is not a problem of receive overrun.
    with the original code receive overrun is expected as it fixes the blockSize to the FIFO size even if the FIFO buffer is not full.
    anyhow in the example code there is a treatment for the various types of error and interrupts (separate handling for data and for commands), in most of the cases the "treatment" is just increasing a counter and interrupt flag reset.
    as i mentioned earlier, i tried to catch the problem with this type of code in the routine tha handles each type of interrupt:

            /* Underrun or overrun */
            if ( MCIStatus &  MCI_TX_UNDERRUN )
            {
                    DataTxUnderrunErrCount++;
                    sprintf (lcd_buf,"TX_UNDERRUN FAIL   ");
                    goto_cursor(0,0);
                    lcd_print(lcd_buf);
                    delay (1000000);
                    MCI_CLEAR = MCIStatus | MCI_TX_UNDERRUN;
            }
            if ( MCIStatus &  MCI_RX_OVERRUN )
            {
                    DataRxOverrunErrCount++;
                    sprintf (lcd_buf,"RX_OVERRUN FAIL   ");
                    goto_cursor(0,0);
                    lcd_print(lcd_buf);
                    delay (1000000);
                    MCI_CLEAR = MCIStatus | MCI_RX_OVERRUN;
            }
    

  • Hi Meir, No I haven't tried your code.I am reviewing my code, in which I got the above errors.I will try your code.
    Using DMA in MCI is more useful than fifo where we can overcome the above errors.
    If possible can you send read and write the fifo functions where you haven't get the errors?
    Iam working on KEIL IDE with LPC2468 Embedded Artists board.

  • Maybe you could consider the RL-ARM option. In RL-ARM there is a ready to go MCI_LPC24xx.c driver for MCB2400. With this driver MCB2400 works just fine with the File System.

    Franc

  • Hi again, pls find below the write fifo function where i don't get errors.
    look inside for the part of MCI_TX_Active. this part of the program goes without any problems.
    BTW, in the part of MCI_RX_Active, in the point where the program stuck in the value of blocksize in the LCD is 4, which indicates that there is available data in the fifo and yet the condition of RX_DATD_AVAIL is not set.

    /******************************************************************************
            /* Tx active, and Rx active  */
            if ( MCI_STATUS & MCI_TX_ACTIVE )
            {
                    DataTxActiveCount++;
    #if MCI_DMA_ENABLED
                    while ( !(GPDMA_RAW_INT_TCSTAT & 0x01) );
                    GPDMA_INT_TCCLR |= 0x01;
    #else
                    while ( TXBlockCounter < BLOCK_LENGTH )
                    {
                            blockSize = 0;
                            if ( MCI_STATUS & MCI_TX_FIFO_EMPTY )
                            {
                                    blockSize = FIFO_SIZE * 4;
                            }
                            else if ( MCI_STATUS & MCI_TX_HALF_EMPTY )
                            {
                                    blockSize = (FIFO_SIZE/2) * 4;
                            }
                            else if ( !(MCI_STATUS & MCI_TX_FIFO_FULL) )
                            {
                                    blockSize = 1 * 4;
                            }
    
                            for ( i = 0; i < blockSize; i += 4 )
                            {
                                    DataWord = (unsigned long)(WriteBlock[TXBlockCounter]) | (unsigned long)(WriteBlock[TXBlockCounter+1] << 8)
                                            | (unsigned long)(WriteBlock[TXBlockCounter+2] << 16) | (unsigned long)(WriteBlock[TXBlockCounter+3] << 24);
                                    MCI_FIFO = DataWord;
                                    TXBlockCounter += 4;
                            }
                    }
    #endif
                    /* Data has been written, but has not been programmed into the card yet. */
                    /* Even it's a dead while loop inside the ISR, but, during the
                    flash writing, there is not much else you should do. If it's not in the
                    TRAN state, per MMC/SD state diagram, send STOP to bail out. */
                    if ( MCI_CheckStatus() != TRUE )
                    {
                            MCI_Send_Stop();
                    }
                    MCI_DATA_CTRL = 0;
            }
    
            if ( MCI_STATUS & MCI_RX_ACTIVE )
            {
                    DataRxActiveCount++;
    #if MCI_DMA_ENABLED
                    while ( !(GPDMA_RAW_INT_TCSTAT & 0x02) );
                    GPDMA_INT_TCCLR |= 0x02;
    #else
                    while ( RXBlockCounter < BLOCK_LENGTH )
                    {
    //                      if ( !(MCI_STATUS & MCI_RX_FIFO_FULL) )
                            if ( MCI_STATUS & MCI_RX_FIFO_FULL)
                            {
                                    blockSize = FIFO_SIZE * 4;
                            }
                            else if ( MCI_STATUS & MCI_RX_HALF_FULL )
                            {
                                    blockSize = (FIFO_SIZE/2) * 4;
                            }
    //                      else if ( MCI_STATUS & MCI_RX_FIFO_EMPTY )
                            else if (!( MCI_STATUS & MCI_RX_FIFO_EMPTY ))
                            {
                                    blockSize = 1 * 4;
                            }
                            else
                            {
                                    blockSize = 0;
                            }
    
                            for ( i = 0; i < blockSize; i += 4 )
                            {
                            sprintf (lcd_buf,"blockSize = %3u ",blockSize);
                            goto_cursor(1,0);
                            lcd_print(lcd_buf);
                                    while ( !(MCI_STATUS & MCI_RX_DATA_AVAIL) );
    //                              while ( !(MCI_STATUS & MCI_RX_HALF_FULL) );
                            sprintf (lcd_buf,"Got here2 RX_Active");
                            goto_cursor(1,0);
                            lcd_print(lcd_buf);
                                    DataWord = MCI_FIFO;
                                    ReadBlock[RXBlockCounter] = DataWord & 0xFF;
                                    ReadBlock[RXBlockCounter+1] = (DataWord >> 8) & 0xFF;
                                    ReadBlock[RXBlockCounter+2] = (DataWord >> 16) & 0xFF;
                                    ReadBlock[RXBlockCounter+3] = (DataWord >> 24) & 0xFF;
                                    RXBlockCounter += 4;
                            }
                    }
    #endif
                    if ( MCI_CheckStatus() != TRUE )
                    {
                            MCI_Send_Stop();
                            sprintf (lcd_buf,"CMD13,status check");
                            goto_cursor(0,0);
                            lcd_print(lcd_buf);
                            sprintf (lcd_buf,"Failed RX_Active");
                            goto_cursor(1,0);
                            lcd_print(lcd_buf);
                            delay (10000000);
                    }
                    else
                    {
                            sprintf (lcd_buf,"CMD13 OK Status Check");
                            goto_cursor(0,0);
                            lcd_print(lcd_buf);
                            sprintf (lcd_buf,"Pass RX_Active");
                            goto_cursor(1,0);
                            lcd_print(lcd_buf);
                            delay (10000000);
                    }
    
                    MCI_DATA_CTRL = 0;
            }
            VICIntEnable |= MCI_Int;                                /*enable MCI interrupts */
            return;
    }
    

  • Thank you Meir, I will test it and give the feedback!!!!

  • Hi Meir, I try your code, Iam trying to read 0th block from 1GB SD card.
    It was hanging in below line:

    while ( !(MCI_STATUS & MCI_RX_DATA_AVAIL) ); .
    If I comment this line I got Receive OverRun error.

    Iam using IAR 5.2 with LPC2468 EA OEM Board.

    Any help....

  • Hi and thank you once more.
    i managed to solve the problem.
    i realized that after identification stage of the SD card the clock frequency wasn't changed to the normal frequency (during identification it should be below 400KHz). once i changed the frequency the program started functioning properly.
    so thank you for supporting me along this issue.