Page 1 of 2

MMC_SPI problems on STM32

Posted: Sat Dec 17, 2011 9:10 am
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?

Re: MMC_SPI problems on STM32

Posted: Sat Dec 17, 2011 10:24 am
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

Re: MMC_SPI problems on STM32

Posted: Sat Dec 17, 2011 7:06 pm
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

Re: MMC_SPI problems on STM32

Posted: Sat Dec 17, 2011 7:49 pm
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

Re: MMC_SPI problems on STM32

Posted: Sat Dec 17, 2011 8:33 pm
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.

Re: MMC_SPI problems on STM32

Posted: Sun Dec 18, 2011 8:28 am
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?

Re: MMC_SPI problems on STM32

Posted: Sun Dec 18, 2011 9:22 am
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

Re: MMC_SPI problems on STM32

Posted: Sun Dec 18, 2011 9:28 am
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

Re: MMC_SPI problems on STM32

Posted: Mon Dec 19, 2011 7:00 am
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.

Re: MMC_SPI problems on STM32

Posted: Tue Dec 20, 2011 3:20 am
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.