This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432E401Y: Detect SD Card is Mounted using Custom Board

Part Number: MSP432E401Y
Other Parts Discussed in Thread: SYSCONFIG, , TM4C1294NCPDT, SEGGER

Hello Ti Community,

I am not using the boosterpack and have three pins selected from SSI2 in sysconfig for SD SPI interface. I have a CS pin that is not part of the SSI2 interface. Non of the simplelink examples for MSP432E401Y launchpad work for me with the custom pinconfig. It cannot perform R/W operations to sd card as well.

I applied the modification in the linked post but had no luck getting a handle that is not null.


Any tips on how to overcome this?

Thanks,


Utsav

  • 1. Are you want to use SPI to communicate with SD card?

    2. Can you catch the wave on SSI pins to see if there is any output.

  • I have an old Tiva C SDK project (tm4c1294ncpdt) that I managed to upload on the board with the help of a segger debugger. It worked as the msp432 and tm4c1294ncpdt are the same processor.

    I do not have any equipment at the moment to capture the waves. The ti.mw.fatfs.FatFS from Tiva C sdk works perfectly and hence I can confirm the SPI bus is working. I am able to R/W to SD card. The difference is that the pinconfigs need to be specified via code in Tiva C whereas in MSP432 it has to be done via sysconfig.

  • /*
     *  ======== SDSPITiva_open ========
     *  Function to mount the FatFs filesystem and register the SDSPITiva disk
     *  I/O functions with SYS/BIOS' FatFS module.
     *
     *  This function also configures some basic GPIO settings needed for the
     *  software chip select with the SDCard.
     *
     *  @param  handle      SDSPI handle
     *  @param  drv         Drive Number
     *  @param  params      SDSPI parameters
     */
    SDSPI_Handle SDSPITiva_open(SDSPI_Handle handle,
                                unsigned char drv,
                                SDSPI_Params *params)
    {
        DRESULT                   dresult;
        FRESULT                   fresult;
        unsigned int              key;
        Types_FreqHz              freq;
        SDSPITiva_Object         *object = handle->object;
        SDSPITiva_HWAttrs const  *hwAttrs = handle->hwAttrs;;
        TCHAR                     path[3];
    
        /* Determine if the device was already opened */
        key = Hwi_disable();
        if (object->driveNumber != DRIVE_NOT_MOUNTED) {
            Hwi_restore(key);
            return (NULL);
        }
        /* Mark as being used */
        object->driveNumber = drv;
        Hwi_restore(key);
    
        /* Determine time scaling for ms timeouts */
        Timestamp_getFreq(&freq);
        mSScalingFactor = freq.lo / 1000;
        Assert_isTrue(mSScalingFactor != 0, NULL);
    
        /* Store desired bitRate */
        object->bitRate = params->bitRate;
    
        GPIODirModeSet(hwAttrs->portSCK,  hwAttrs->pinSCK,  GPIO_DIR_MODE_HW);
        GPIODirModeSet(hwAttrs->portMISO, hwAttrs->pinMISO, GPIO_DIR_MODE_HW);
        GPIODirModeSet(hwAttrs->portMOSI, hwAttrs->pinMOSI, GPIO_DIR_MODE_HW);
    
        /* Pin used for Chip Select */
        GPIOPinTypeGPIOOutput(hwAttrs->portCS, hwAttrs->pinCS);
    
        /* Raise the chip select pin */
        GPIOPinWrite(hwAttrs->portCS, hwAttrs->pinCS, hwAttrs->pinCS);
    
        /*
         * Configure the SPI bus to 400 kHz as required per SD specs. This frequency
         * will be adjusted later once the SD card has been successfully initialized
         */
        BIOS_getCpuFreq(&freq);
        SSIConfigSetExpClk(hwAttrs->baseAddr, freq.lo, SSI_FRF_MOTO_MODE_0,
                           SSI_MODE_MASTER, 400000, 8);
    
        Log_print2(Diags_USER1, "SDSPI:(%p) CPU freq: %d; SDSPI freq to 400000 kHz",
                   hwAttrs->baseAddr, freq.lo);
    
        SSIEnable(hwAttrs->baseAddr);
    
        /* Register the new disk_*() functions */
        dresult = disk_register(object->driveNumber,
                                SDSPITiva_diskInitialize,
                                SDSPITiva_diskStatus,
                                SDSPITiva_diskRead,
                                SDSPITiva_diskWrite,
                                SDSPITiva_diskIOctrl);
    
        /* Check for drive errors */
        if (dresult != RES_OK) {
            Log_error1("SDSPI:(%p) disk functions not registered",
                        hwAttrs->baseAddr);
    
            SDSPITiva_close(handle);
            return (NULL);
        }
    
        /*
         * Register the filesystem with FatFs. This operation does not access the
         * SDCard yet.
         */
        path[0] = '0' + object->driveNumber;
        path[1] = ':';
        path[2] = '\0';
    
        fresult = f_mount(&(object->filesystem), path, 0);
        if (fresult != FR_OK) {
            Log_error2("SDSPI:(%p) drive %d not mounted",
                        hwAttrs->baseAddr, object->driveNumber);
    
            SDSPITiva_close(handle);
            return (NULL);
        }
    
        /* Store the new SDSPI handle for this FatFs drive number */
        sdspiHandles[drv] = handle;
    
        Log_print1(Diags_USER1, "SDSPI:(%p) opened", hwAttrs->baseAddr);
    
        return (handle);
    }


    This is the Tiva C handle implementation. It actually accesses the pins. I didnt see it in the Simplelink SDK FatFS handle

  • MSP432 belong to simplelink platform, that means it use different code style with TIVA.

    If you don't have oscilloscope to test the wave, can you connect the MISO and MOSI together. Then you can check it on your application.

  • I'm afraid Ill have to wait for a while to do that as we are in lockdown and I do not have a spare board if something gets shorted.

    I formatted my SD card and ran the Tiva C project where I made it generate a file called input.txt with some text inside it. It has that file in it after the code is run so can confirm the SPI bus is working perfectly.

    After I applied the modification in the linked post in the simplelink example, it tries to mount the SD card immediately instead of later and does not succeed. I suspect its something to do with how the driver uses the SPI interface.


  • From you explain, you SD card works good. The problem should lies on the MSP432 part, mostly is the software.

    As you can't monitor the SPI data, it is really a bad news. You can't prove the MCU operate like what you want. Sorry, I can't give you more help on this question until you can compare what you send and what you want to send.

  • Hello Eason,

    I'm sorry and thank you so much for taking the time out to look at this. I will definitely update once I have done so.

    I did not find any posts regarding custom boards. Are you aware of anyone achieving this with a custom board or could you direct me to someone from TI team (TI software makers)?

    As a last resort I'm trying to port over Tiva C sd card modules into simplelink and trying.

    Thanks,

    Utsav

  • Didn't have any luck with that. The problem is in 'fresult = f_mount(&(obj->filesystem), path, 1); '

     /*
                         * @orig: Register the filesystem with FatFs. This operation does
                         * not access the SDCard yet.
                         * @new: Mounts and accesses SD card immediately
                         */
                        sdFatFSHandles[obj->driveNum] = handle;
    
                        fresult = f_mount(&(obj->filesystem), path, 1);
    
                        if (fresult != FR_OK) {
                            DebugP_log1("SDFatFS: Drive %d not mounted",
                                        obj->driveNum);
                            sdFatFSHandles[obj->driveNum] = NULL;
                            SDFatFS_close(handle);
                            handle = NULL;
                        }else {
    
                            /*
                             * Store the new sdfatfs handle for the input drive
                             * number
                             */
                            DebugP_log0("SDFatFS: opened");
                        }

  • What about in the f_mount?

    Sorry, for MSP432E series, we only give the limited support. We are the last guy will support it.

  • I did a comparison between Tiva C and MSP432. I thought f_mount might not be a problem when I started investigating. The SDSPI.c implementation is where it fails in MSP432 SDK when SDSPI_Initialise is called. It fails to put the card in idle mode.

    UPDATE 1: It fails to get a correct response with any command. Even if Idle state code is commented out, it fails to get a correct response with CMD8 to determine card type. CMD0 and CMD8 both pass in Tiva C SDK returning number 0x01 as response.

    UPDATE 2:  The status variable is always SD_STATUS_SUCCESS indicating the Commands are sent successfully. The rxBuf (response is always 0x07 for all the commands there apart from CMD8 (0x04) for MSP432 SDK

    UPDATE 3: I managed to port Tiva C SPI API into MSP432 SDK and use it instead of MSP432 SPI API. It fails to mount the SD Card with the Tiva C API running in MSP432 SDK. It crashes if f_mount() is set to mount immediately and fails to mount the SD Card with delayed mounting. I tried using only the send and receive SPI functions from Tiva C which include SSIGet. It hangs in MSP432. SSIDataGetNonBlocking also does not return a correct response.

    UPDATE 4: The Fatfs version in Tiva C is R0.11a and R0.13A for MSP432. Porting over those files did not help. Replacing static library fatfs.a in MSP432 with the Tiva C equivalent cannot be done as there is no .a file in the Tiva C SDK for fatfs. The call stack below shows that f_mount leads to the MSP432 SPI drivers and tries to send CMD0.
    I will upload the waveforms in a separate post linking this one once I am able to.



    TODO: Send waveforms of SPI interface as soon as I am able to for @Eason to review.
     
    MSP432 using Tiva C API, fails to detect SD Card is mounted:

    SDSPI_Handle SDSPITiva_open(SDSPI_Handle handle,
                                unsigned char drv,
                                SDSPI_Params *params)
    {
    
    
        DRESULT                   dresult;
        FRESULT                   fresult;
        unsigned int              key;
        Types_FreqHz              freq;
        SDSPITiva_Object         *object = handle->object;
        SDSPITiva_HWAttrs* const hwAttrs = handle->hwAttrs;
        TCHAR                     path[3];
    
        /* Determine if the device was already opened */
        key = Hwi_disable();
        if (object->driveNumber != DRIVE_NOT_MOUNTED) {
            Hwi_restore(key);
            return (NULL); // Returns here when using Tiva C in MSP432 SDK
        }


    MSP432 SPI  for sending Commands to SDCard. Response rxBuf is never correct:

    static uint8_t sendCmd(SPI_Handle handle, uint8_t cmd, uint32_t arg)
    {
        uint8_t      i;
        uint8_t      rxBuf;
        uint8_t      txBuf[6];
        int_fast16_t status;
    
        if ((cmd != CMD0) && !waitUntilReady(handle)) {
            return (0xFF);
        }
    
        /* Setup SPI transaction */
        txBuf[0] = cmd;                  /* Command */
        txBuf[1] = (uint8_t)(arg >> 24); /* Argument[31..24] */
        txBuf[2] = (uint8_t)(arg >> 16); /* Argument[23..16] */
        txBuf[3] = (uint8_t)(arg >> 8);  /* Argument[15..8] */
        txBuf[4] = (uint8_t) arg;        /* Argument[7..0] */
    
        if (cmd == CMD0) {
            /* CRC for CMD0(0) */
            txBuf[5] = 0x95;
        }
        else if (cmd == CMD8) {
            /* CRC for CMD8(0x1AA) */
            txBuf[5] = 0x87;
        }
        else {
            /* Default CRC should be at least 0x01 */
            txBuf[5] = 0x01;
        }
    
        if (spiTransfer(handle, NULL, &txBuf, 6) != SD_STATUS_SUCCESS) {
            return (0xFF);
        }
    
        /* Prepare to receive SD card response (send 0xFF) */
        txBuf[0] = 0xFF;
    
        /*
         * CMD 12 has R1b response which transfers an additional
         * "busy" byte
         */
        if ((cmd == CMD12) &&
            (spiTransfer(handle, &rxBuf, &txBuf, 1) != SD_STATUS_SUCCESS)) {
                return (0xFF);
        }
    
        /* Wait for a valid response; 10 attempts */
        i = 10;
        do {
            status = spiTransfer(handle, &rxBuf, &txBuf, 1);
        } while ((status == SD_STATUS_SUCCESS) && (rxBuf & 0x80) && (--i));
    
        /* Return with the response value */
        return (rxBuf);
    }


    MSP432 SPI API SD Card fails to transition to Idle Mode
    int_fast16_t SDSPI_initialize(SD_Handle handle)
    {
        SD_CardType          cardType = SD_NOCARD;
        uint8_t              i;
        uint8_t              ocr[4];
        uint8_t              txDummy[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                                           0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        int_fast16_t         status;
        uint32_t             currentTime;
        uint32_t             startTime;
        uint32_t             timeout;
        SPI_Params           spiParams;
        SDSPI_Object        *object = handle->object;
        SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
    
        SemaphoreP_pend(object->lockSem, SemaphoreP_WAIT_FOREVER);
    
        /*
         * The CS line should not be asserted when attempting to put the
         * SD card into SPI mode.
         */
        deassertCS(hwAttrs);
    
        /*
         * To put the SD card in SPI mode we must keep the TX line high while
         * toggling the clock line several times. To do this we transmit 0xFF
         * 10 times. Do not assert CS during this time
         */
        status = spiTransfer(object->spiHandle, NULL, &txDummy, 10);
        if (status != SD_STATUS_SUCCESS) {
            SemaphoreP_post(object->lockSem);
            return (status);
        }
    
        /* Now select the SD Card's chip select to send CMD0 command */
        assertCS(hwAttrs);
    
        /*
         * Send CMD0 to put the SD card in idle mode. Depending on the previous
         * state of the SD card, this may take up to a couple hundred milliseconds.
         * Rather than delay between attempts, we try up to 255 attempts.
         * Failure is returned if the card does not respond will a valid byte
         * within 255 attempts. When the card will respond with 0x1 when its
         * in idle mode.
         */
        for (i = 255, status = 0xFF; i > 0 && status != 0x1; i--) {
            status = sendCmd(object->spiHandle, CMD0, 0); // Fails to send
        }
    
        /* If the card never transitioned into idle mode */
        if (status != 0x1) {
            deassertCS(hwAttrs);
            SemaphoreP_post(object->lockSem);
            return (SD_STATUS_ERROR); // Returns here
        }
        
        // More Code below but taken out for this TI Forum Post
        ....
    }

    The first f_open is where it tries to open a file for writing or create it if it does not exist.

    Call Stack


    Tiva C Project runs successfully:

    DSTATUS SDSPITiva_diskInitialize(BYTE drv)
    {
        uint8_t                    n;
        uint8_t                    ocr[4];
        SDSPITiva_CardType         cardType;
        Types_FreqHz               freq;
        uint32_t                   timestampTimeout;
        uint32_t                   timestampStart;
        uint32_t                   timestampCurrent;
        SDSPITiva_Object          *object = sdspiHandles[drv]->object;
        SDSPITiva_HWAttrs const   *hwAttrs = sdspiHandles[drv]->hwAttrs;
    
        /* No card in the socket */
        if (object->diskState & STA_NODISK) {
            Log_error1("SDSPI:(%p) disk initialization failed: No disk",
                        hwAttrs->baseAddr);
    
            return (object->diskState);
        }
    
        /* Initialize the SD Card for SPI mode */
        send_initial_clock_train(hwAttrs);
    
        /* Select the SD Card's chip select */
        takeSPIBus(hwAttrs);
        cardType = SDSPITiva_NOCARD;
    
        /* Send the CMD0 to put the SD Card in "Idle" state */
        if (send_cmd(hwAttrs, CMD0, 0) == 1) {// Succeeds here
    
            /*
             * Determine what SD Card version we are dealing with
             * Depending on which SD Card version, we need to send different SD
             * commands to the SD Card, which will have different response fields.
             */
            
            // Succeeds here but fails in MSP432 SDSPI SDK
            if (send_cmd(hwAttrs, CMD8, 0x1AA) == 1) { 
                /* SDC Ver2+ */
                for (n = 0; n < 4; n++) {
                    ocr[n] = rxSPI(hwAttrs);
                }
    

  • Hi Utsav Trivedi,

    Do you have any progress? Have you find a way to read the SPI data?

    Eason

  • The lockdown has been extended where I am so sending waveforms will be a while. I managed to get a Launchpad instead. I will use this breadboard setup. The SPI bus is free so should not matter.

    Update: The breadboard setup from the YouTube link works with Launchpad. One key difference between the custom board and launchpad is there is a 32KHz crystal. Not sure if this is being used in the driver. The rtc (crystal) is called in launchpad but for custom board I am using software clock from seconds module.

    Commenting this line in fatsd example had no effect.

    /* Initialize real-time clock */
    clock_settime(CLOCK_REALTIME, &ts);

  • Hello Eason, I managed to get an oscilloscope and here are my findings. I sent CMD0 in this. The MSP432 launchpad matches an image from this guide here: http://www.rjhcoding.com/avrc-sd-interface-1.php.

    Another key difference I notices was that the Tiva C SDK sends each byte one at a time while Simplelink SDK sends it all at once. I tried doing that with Simplelink driver but no luck. It is obvious that CMD0 is not being sent properly in Simplelink SDK but I can't understand why.

    In terms on the hardware, the Custom board has external Pull-ups at 3.3V for SPI interface whereas the launchpad is internal. Pin 1 (NC1 ) is at 3.3V and Pin 8 (RSV) is at Gnd. I feel this could be the problem as there is no way to set Pull-ups to none or external in syscfg for SPI.

    Update: I used driverlib API GPIOPadConfigSet() to set it to open drain but had no luck. I can't tell if this is meant for external or internal pullups.

    Hopefully I can get some insight from you from this. Should I try with removing the external pullup resistors?

    Custom Board:

    # MOSI
    MOSI

    #MISO

    MISO

    # CS



    MSP432 Launchpad:

    # MOSI
    MOSI

    # MISO

    MISO

    # CS

  • Hi Trivedi,

    1. As you said the wave of MSP432 is same as the image from this guide. Although it is different with the wave of TIVA. I think it should be OK.

    2. See you customized board, the wave of SPI is not good. The setup time takes too long. Can you double check if this is a problem? Maybe it is caused from external resistor. It is quite wired that some setup time is good. Some is not.

    3. Normally, SPI is not like I2C and don't need to add a pull-up resistor.

    Eason

  • Hello Eason,

    The external pullups were not a problem for the Tiva C project where bytes were sent one at at time. That makes it harder for me to capture a waveform as well.

    I'll try this on a Tiva C launchpad as I can replicate this without external pullups. Ill update you when I get the launchpad for it.

    Thanks,

    Utsav


  • Hi Utsav,

    You can see that at these time point, both the CLK and MOSI is streched. Is the same behaviour on TIVA?

    Eason

  • Hello Eason,

    I can't see the whole waveform at once for Tiva driver as the bytes are sent one at a time. But for each byte I didnt observe this.

    I got a Tiva C launchpad and observed that it works with Simplelink SDK if I dont use external pullups. With Tiva C SDK it works with and without external pullups.

    Is there a way to make Simplelink SDK work with external pull up resistors for SPI SD card? I observed the same for MSP432 launchpad. It cannot write to sd card with external pullups.

    So to summarise the simplelink SD card driver cannot work if external pullups are present. Tiva C SD card driver has no problems with that.

    Thanks,

    Utsav

  • Hi Utsav,

    I think it is related to hardware (MSP432 itself), it has no relationship with software. It is really hard to tell you why it happens.

    I am not sure if you can make it work without external resistor? 

    Eason

  • Hello Eason,

    MSP432 launchpad itself only works without external pullups as well. You can try it with some resistors if you have a setup.

    Regards,

    Utsav.

  • Hi Utsav,

    Sorry, I just come back from a long holiday. The problem that MSP432 can't communicate with SD card is related to the external pullup resistor . But for TIVA MCU, it is not a problem. I think you have found a way to slove it. 

    If you want to check why MSP432 can't work with pullup resistor. I think you need to double check:

    1. Why you put the pullup resistor? From the SD card document or any other reference design?

    2.  What the resistor value you added and On which signal? The resistor value is too small?

    Eason

  • Hello Eason,

    1. It was a design decision made by my company long time ago. Personally I would not put it unless there is a high current problem. The custom board I have shares the same SPI bus for two different peripherals. There is an extra CS pin for that.

    2. On my custom board 10k resistor is used and 8.2k on launchpad as thats the highest I have at home.

    Thank you so much for putting the time in though. Ill mark this as resolved and perhaps you can keep a note of this to look at later. Ive requested the company to apply a hardware modification instead.

    Thanks,

    Utsav