MMC_SPI problems on STM32

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

MMC_SPI problems on STM32

Post by CheBuzz »

I am trying to talk to a SD card using the MMC_SPI in-built into ChibiOS but am seeing some odd behavior. If I use SPI by itself, I am seeing what I expect. That is, SCK and MOSI signals as seen here:
Image

Here is the code for that:

Code: Select all

static void t_sdcard(void *arg)
{
   (void)arg;
   chRegSetThreadName("sdcard");

   // For now just listen for events
   while (TRUE)
   {
      spiSelect(&SPID1);
      spiSend(&SPID1, 11, "Hello World");
      chThdSleepSeconds(1);
   }

   // Should never get here
   chThdExit(1);
}

void createSdCardThread(void)
{
   /*
    * Initializes the MMC driver to work with SPI1.
    */
    palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); /* NSS.     */
    palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
    palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));              /* MISO.    */
    palSetPadMode(GPIOB, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* MOSI.    */
    palSetPad(GPIOA, 4);  // Set NSS high
    spiObjectInit(&SPID1);
    spiStart(&SPID1, &ls_spicfg);

   chThdCreateStatic(waSdCard, sizeof(waSdCard), LOWPRIO, (tfunc_t)t_sdcard, NULL);
}


But when I use that same SPI port with the same config under MMC, I get SCK, but MOSI is always logic high, as seen below:
Image

And here is the code for that:

Code: Select all

static void t_sdcard(void *arg)
{
   (void)arg;
   chRegSetThreadName("sdcard");

   static const evhandler_t evhndl[] = {
         InsertHandler,
         RemoveHandler
   };
   struct EventListener el0, el1;

   chEvtRegister(&MMCD1.inserted_event, &el0, 0);
   chEvtRegister(&MMCD1.removed_event, &el1, 1);
   mmcStart(&MMCD1, NULL);
   // For now just listen for events
   while (TRUE)
   {
         if(fs_ready)
       {
          f_open(sdfp, "/sd/tap_bfr.txt", FA_READ);
          if (sdfp == NULL)
          {
             chprintf((BaseChannel *)&SD1, "Could not open tap_bfr.txt\n");
          }
          else
          {
             f_close(sdfp);
          }
       }
         chEvtDispatch(evhndl, chEvtWaitOne(ALL_EVENTS));
   }

   // Should never get here
   chThdExit(1);
}

void createSdCardThread(void)
{
   /*
    * Initializes the MMC driver to work with SPI1.
    */
    palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); /* NSS.     */
    palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
    palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));              /* MISO.    */
    palSetPadMode(GPIOB, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* MOSI.    */
    palSetPad(GPIOA, 4);  // Set NSS high
    mmcObjectInit(&MMCD1, &SPID1, &ls_spicfg, &hs_spicfg, mmc_is_protected, mmc_is_inserted);
    mmcStart(&MMCD1, NULL);

   chThdCreateStatic(waSdCard, sizeof(waSdCard), LOWPRIO, (tfunc_t)t_sdcard, NULL);
}


So anybody have any idea why this is happening?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: MMC_SPI problems on STM32

Post by Giovanni »

Hi,

Part of the MMC-SPI initialization sequence is the generation of 80 clock pulses without any data going out, probably you are seeing that.

I recommend that you single step through mmcConnect() in order to understand what is happening.

BTW it is better to post all the code, many things are not visible there.

Giovanni
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

Re: MMC_SPI problems on STM32

Post by CheBuzz »

Right, I am seeing the 80 clock pulses on initialization:
Image

But if you look at the line below it (attached to MOSI), it is logic high the entire time. If I understood mmc_spi.c correctly, this should be logic 0 for those 80 clock pulses. In fact MOSI stays high always when using MMC_SPI. It works as expected when using only SPI, as seen in the screen shot from the first post.

I don't know what other code would be helpful. Everything else is pretty much the same as the demos. Here is the entirety of that file:

Code: Select all

#include "sdcard.h"

/**
 * @brief FS object.
 */
FATFS MMC_FS;
FIL *sdfp;
MMCDriver MMCD1;

/* FS mounted and ready.*/
bool_t fs_ready = FALSE;

/* Maximum speed SPI configuration (18MHz, CPHA=0, CPOL=0, MSb first).*/
static const SPIConfig hs_spicfg = {NULL, GPIOA, GPIOA_SPI1NSS, 0};

/* Low speed SPI configuration (281.250KHz, CPHA=0, CPOL=0, MSb first).*/
static const SPIConfig ls_spicfg = {NULL, GPIOA, GPIOA_SPI1NSS,
                              SPI_CR1_BR_2 | SPI_CR1_BR_1};

/* Card insertion verification.*/
bool_t mmc_is_inserted(void)
{
//   return palReadPad(IOPORT3, GPIOC_MMCCP);
   return 1;
}

/* Card protection verification.*/
bool_t mmc_is_protected(void)
{
//   return !palReadPad(IOPORT3, GPIOC_MMCWP);
   return 0;
}

FRESULT scan_files(BaseChannel *chp, char *path) {
  FRESULT res;
  FILINFO fno;
  DIR dir;
  int i;
  char *fn;

  res = f_opendir(&dir, path);
  if (res == FR_OK) {
    i = strlen(path);
    for (;;) {
      res = f_readdir(&dir, &fno);
      if (res != FR_OK || fno.fname[0] == 0)
        break;
      if (fno.fname[0] == '.')
        continue;
      fn = fno.fname;
      if (fno.fattrib & AM_DIR) {
        path[i++] = '/';
        strcpy(&path[i], fn);
        res = scan_files(chp, path);
        if (res != FR_OK)
          break;
        path[i] = 0;
      }
      else {
        chprintf(chp, "%s/%s\r\n", path, fn);
      }
    }
  }
  return res;
}

/*
 * MMC card insertion event.
 */
static void InsertHandler(eventid_t id) {
  FRESULT err;

  (void)id;
  /*
   * On insertion MMC initialization and FS mount.
   */
  if (mmcConnect(&MMCD1)) {
    return;
  }
  err = f_mount(0, &MMC_FS);
  if (err != FR_OK) {
    mmcDisconnect(&MMCD1);
    return;
  }
  fs_ready = TRUE;
}

/*
 * MMC card removal event.
 */
static void RemoveHandler(eventid_t id) {

  (void)id;
  fs_ready = FALSE;
}



static WORKING_AREA(waSdCard, 512);
#if 1
/**
 * @brief Task to store and retrieve flow and temperature readings on
 *          the on-board SD card
 */
static void t_sdcard(void *arg)
{
   (void)arg;
   chRegSetThreadName("sdcard");

   static const evhandler_t evhndl[] = {
         InsertHandler,
         RemoveHandler
   };
   struct EventListener el0, el1;

   chEvtRegister(&MMCD1.inserted_event, &el0, 0);
   chEvtRegister(&MMCD1.removed_event, &el1, 1);
   mmcStart(&MMCD1, NULL);
   // For now just listen for events
   while (TRUE)
   {
      if(fs_ready)
       {
          f_open(sdfp, "/sd/tap_bfr.txt", FA_READ);
          if (sdfp == NULL)
          {
             chprintf((BaseChannel *)&SD1, "Could not open tap_bfr.txt\n");
          }
          else
          {
             f_close(sdfp);
          }
       }
      else
         InsertHandler(NULL);
      chEvtDispatch(evhndl, chEvtWaitOne(ALL_EVENTS));
   }

   // Should never get here
   chThdExit(1);
}

void createSdCardThread(void)
{
   /*
    * Initializes the MMC driver to work with SPI1.
    */
    palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); /* NSS.     */
    palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
    palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));              /* MISO.    */
    palSetPadMode(GPIOB, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* MOSI.    */
    palSetPad(GPIOA, 4);  // Set NSS high
    spiObjectInit(&SPID1);
    mmcObjectInit(&MMCD1, &SPID1, &ls_spicfg, &hs_spicfg, mmc_is_protected, mmc_is_inserted);

   chThdCreateStatic(waSdCard, sizeof(waSdCard), LOWPRIO, (tfunc_t)t_sdcard, NULL);
}
#else
/**
 * @brief Task to store and retrieve flow and temperature readings on
 *          the on-board SD card
 */
static void t_sdcard(void *arg)
{
   (void)arg;
   chRegSetThreadName("sdcard");

   // For now just listen for events
   while (TRUE)
   {
      spiSelect(&SPID1);
      spiSend(&SPID1, 11, "Hello World");
      chThdSleepSeconds(1);
   }

   // Should never get here
   chThdExit(1);
}

void createSdCardThread(void)
{
   /*
    * Initializes the MMC driver to work with SPI1.
    */
    palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); /* NSS.     */
    palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
    palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));              /* MISO.    */
    palSetPadMode(GPIOB, 5, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);           /* MOSI.    */
    palSetPad(GPIOA, 4);  // Set NSS high
    spiObjectInit(&SPID1);
    spiStart(&SPID1, &ls_spicfg);

   chThdCreateStatic(waSdCard, sizeof(waSdCard), LOWPRIO, (tfunc_t)t_sdcard, NULL);
}
#endif
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: MMC_SPI problems on STM32

Post by Giovanni »

MOSI is supposed to be high during the clock pulses, spiIgnore() does that. I don't understand why it is still high after that, it should be sending the initialization commands.

Anyway, MMC_SPI is used on a lot of demos on various MCUs and hasn't been touched for a while, the problem must lie elsewhere. Do you have another card to try?

Edit: MMC_SPI does not support cards above 2GB, is that your case?

Giovanni
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

Re: MMC_SPI problems on STM32

Post by CheBuzz »

No, I am using a 2GB SD card.

I have seen this on both my custom F2 board and the F4-Discovery board. I will see if I can dig up an old F1 board to try it out on.
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

Re: MMC_SPI problems on STM32

Post by CheBuzz »

Well, it looks like I am having the same problem with the F1 board. I can't be exactly sure as it is difficult to hook up the LA to it so I haven't done that yet. But fs_ready never toggle true.

Also, it seems like there is bug with the latest trunk, as line 165 of shell.c (code - lp = strtok_r(line, " \009", &tokp); ) is causing an unhandled exception. Anybody else seeing that?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: MMC_SPI problems on STM32

Post by Giovanni »

Hi,

I retested the demo ARMCM3-STM32F103-FATFS using YAGARTO 4.6.2 and it appears to work correctly:

Code: Select all

ChibiOS/RT Shell
ch> help
Commands: help exit info systime mem threads test tree
ch> info
Kernel:       2.3.5unstable
Compiler:     GCC 4.6.2
Architecture: ARMv7-M
Core Variant: Cortex-M3
Port Info:    Advanced kernel mode
Platform:     STM32F1 Performance Line Medium Density
Board:        Olimex STM32-P103
Build time:   Dec 18 2011 - 09:13:21
ch> tree
FS: 60213 free clusters, 1 sectors per cluster, 30829056 bytes free
/MMC.H
/MBR.H
/MMC.C
ch>


I begin to think there is something strange with your build environment or compiler.

Giovanni
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: MMC_SPI problems on STM32

Post by Giovanni »

I committed a change in shell.c to not use the strtok_r function in library, now it always uses the internal implementation. Does this work for you? (if it works then probably you have problems with the C library in your compiler)

Giovanni
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

Re: MMC_SPI problems on STM32

Post by CheBuzz »

It looks like it was a problem with my toolchain. I was using summon-arm-toolchain which was causing the hangup. I switched the toolchain to CodeSourcery 2011.03 release and I'm not getting it anymore. Now to see if that solves the MMC_SPI problem as well.
CheBuzz
Posts: 17
Joined: Mon Dec 12, 2011 4:17 am

Re: MMC_SPI problems on STM32

Post by CheBuzz »

*edit nm-was probing the wrong line. nSS goes low just as expected. So I am still seeing the same thing. Clock going, with MOSI always high and MISO always low.
Post Reply