Author Topic: Calling on your help again, need some help getting FATFS working...  (Read 15767 times)

0 Members and 1 Guest are viewing this topic.

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Well thank you for getting this far! As some of you may have noticed I'm not the most experienced when it comes to microcontrollers and c coding, but I'm getting there!

Well here goes! I used STM's CubeMX to generate a project for me with just FATFS and hardware initialization for SD cards over 4 bit SDIO. The code compiles fine and I've added some code to main to mount the volume, create and file and write in it. But it doesn't work.

I've stepped through the code and I get an error when the disk is being initialized and returns 'FR_NOT_READY' from the 'disk_initialize(fs->drv);' function.

Looking on my logic analyzer I do have activity on the bus (not sure what values I should be seeing) and I've checked all my connections which I'm happy with. I'm using a micro SD card with an adapter with a STM32F4 discovery board. I have 3 SD cards: two 2GB and one 4GB, I formatted them to FAT32 on my PC. I have tried doing a full format and quick.

I wonder if anyone could give me some pointers as to where I should look next. I am fairly good, honest! Just lacking in experience with this stuff.

Thanks again!

My main bit of code looks as follows:

/* USER CODE BEGIN 2 */
  UINT bw;
 
  f_mount(&FatFs, "", 0);      /* Give a work area to the default drive */

  if(f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {   /* Create a file */
    f_write(&Fil, "It works!\r\n", 11, &bw);   /* Write data to the file */
    f_close(&Fil);                        /* Close the file */
    if (bw == 11) {      /* Lights green LED if data written well */
        //Celebrate
    }
  }

  /* USER CODE END 2 */
 

Offline Karel

  • Super Contributor
  • ***
  • Posts: 2503
  • Country: 00
Re: Calling on your help again, need some help getting FATFS working...
« Reply #1 on: November 12, 2015, 10:08:09 am »
Despite I do realize that that most people prefer to take a short-cut and that "time is money" and all that other blahblah, I want to give you my opinion.

In a microcontroller environment, do not bother with libraries, not for FAT and not for SD-cards.
Download the specifications of FAT and SD-cards and start to write your own lib for SD-cards and a lib for FAT.
This way you will get a very good understanding about how this stuff works and you will gain a lot of experience.
It's not too difficult, it just takes some time.

 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #2 on: November 12, 2015, 12:21:07 pm »
Thanks for the reply and I think I may end up doing that. It's just how far do you go? I'm one person trying to complete this project I have (there's much more to it) and there's only so much time and resource I have. I have started reading the FAT specification.

I would like to try and debug this code a little further though, until I give it a try myself.

This is where I get errors.

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS disk_initialize (
   BYTE pdrv            /* Physical drive nmuber to identify the drive */
)
{
  DSTATUS stat = RES_OK;
 
  if(disk.is_initialized[pdrv] == 0)
  {
    disk.is_initialized[pdrv] = 1;
    stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
  }
  return stat;
}

I'm a little confused with this line.

stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);

So stat is equal to the variable drv[pdrv] in the struct disk which is getting it's value from the function 'disk_initialize' which is calling the function we are currently in!?

I'm not saying it's wrong - just don't understand it's operation and so struggling to go any deeper in the code.
 

Offline FreddyVictor

  • Regular Contributor
  • *
  • Posts: 164
  • Country: gb
Re: Calling on your help again, need some help getting FATFS working...
« Reply #3 on: November 12, 2015, 12:55:00 pm »
So stat is equal to the variable drv[pdrv] in the struct disk which is getting it's value from the function 'disk_initialize' which is calling the function we are currently in!?

I'm guessing the disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]) one is a (member) function pointer so can point to any 'disk_initialize' function.

confusingly it'is the same name as the function it's being called within!

c at its best  ;D
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 29808
  • Country: nl
    • NCT Developments
Re: Calling on your help again, need some help getting FATFS working...
« Reply #4 on: November 12, 2015, 01:08:08 pm »
Despite I do realize that that most people prefer to take a short-cut and that "time is money" and all that other blahblah, I want to give you my opinion.

In a microcontroller environment, do not bother with libraries, not for FAT and not for SD-cards.
It's not too difficult, it just takes some time.
Actually it is difficult and will take a lot of time. The biggest trick is to find & identify libraries which work. In many cases it takes less work to make a library work than start from scratch. Using readily made libraries is the key to getting a project going quickly nowadays and in many cases you have to. It just takes too much time to write a USB, TCP/IP, bluetooth, etc library from scratch.

More on topic: The FATfs library works well (I have tested it thouroughly) so the OPs problem is most likely something simple like wrong initialisation of the SPI peripheral or wiring. I'm also not sure whether FATfs supports FAT32 out of the box; I'd look into the documentation first and/or try a FAT16 formatted SD card.
« Last Edit: November 12, 2015, 01:12:27 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #5 on: November 12, 2015, 03:03:17 pm »
Despite I do realize that that most people prefer to take a short-cut and that "time is money" and all that other blahblah, I want to give you my opinion.

In a microcontroller environment, do not bother with libraries, not for FAT and not for SD-cards.
It's not too difficult, it just takes some time.
Actually it is difficult and will take a lot of time. The biggest trick is to find & identify libraries which work. In many cases it takes less work to make a library work than start from scratch. Using readily made libraries is the key to getting a project going quickly nowadays and in many cases you have to. It just takes too much time to write a USB, TCP/IP, bluetooth, etc library from scratch.

More on topic: The FATfs library works well (I have tested it thouroughly) so the OPs problem is most likely something simple like wrong initialisation of the SPI peripheral or wiring. I'm also not sure whether FATfs supports FAT32 out of the box; I'd look into the documentation first and/or try a FAT16 formatted SD card.

Well i think this may be the problem so I want to get lower in the code and see what should be on the bus and what is on the bus. I'm not sure how to get any lower than the above function though. Any pointers? (not a pun!)
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 628
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: Calling on your help again, need some help getting FATFS working...
« Reply #6 on: November 13, 2015, 05:47:51 am »
Quote
I've stepped through the code and I get an error when the disk is being initialized and returns 'FR_NOT_READY' from the 'disk_initialize(fs->drv);' function.
This is a generic error. You need to find what specific problem is causing it.

Searching for the error code  FR_NOT_READY, we find (in "ff.c"):-
Code: [Select]
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;

Searching for STA_NOINIT we find in  "diskio.h"
Code: [Select]
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
and in "sd_diskio.c"
Code: [Select]
DSTATUS SD_initialize(BYTE lun)
{
  Stat = STA_NOINIT;
 
  /* Configure the uSD device */
  if(BSP_SD_Init() == MSD_OK)
  {
    Stat &= ~STA_NOINIT;
  }

  return Stat;
}
So if BSP_SD_Init() doesn't return  MSD_OK then you will get the error FR_NOT_READY.

Now let's see what might cause BSP_SD_Init() to fail. In "bsp_driver_sd.c":-
Code: [Select]
uint8_t BSP_SD_Init(void)
{
  uint8_t SD_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR;
  }
  SD_state = HAL_SD_Init(&hsd, &SDCardInfo);
#ifdef BUS_4BITS
  if (SD_state == MSD_OK)
  {
    if (HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B) != SD_OK)
    {
      SD_state = MSD_ERROR;
    }
    else
    {
      SD_state = MSD_OK;
    }
  }
#endif
  return SD_state;
}
But checking if the SD card is plugged in cannot fail, because...
Code: [Select]
uint8_t BSP_SD_IsDetected(void)
{
  __IO uint8_t status = SD_PRESENT;

  /* USER CODE BEGIN 1 */
  /* user code can be inserted here */
  /* USER CODE END 1 */   
 
  return status;
}
which leaves HAL_SD_Init() and HAL_SD_WideBusOperation_Config() as the only possible culprits.

The first function called by HAL_SD_Init() is  HAL_SD_MspInit(hsd)  (in "stm32f4xx_hal_msp.c"):-
Code: [Select]
void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hsd->Instance==SDIO)
  {
  /* USER CODE BEGIN SDIO_MspInit 0 */

  /* USER CODE END SDIO_MspInit 0 */
    /* Peripheral clock enable */
    __SDIO_CLK_ENABLE();
 
    /**SDIO GPIO Configuration   
    PC12     ------> SDIO_CK
    PC11     ------> SDIO_D3
    PC10     ------> SDIO_D2
    PD2     ------> SDIO_CMD
    PC9     ------> SDIO_D1
    PC8     ------> SDIO_D0
    */
    GPIO_InitStruct.Pin = uSD_CLK_Pin|uSD_D3_Pin|uSD_D2_Pin|uSD_D1_Pin
                          |uSD_D0_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = uSD_CMD_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(uSD_CMD_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN SDIO_MspInit 1 */

  /* USER CODE END SDIO_MspInit 1 */
  }

}
Finally we begin to find out what it is actually doing!

The code looks complicated, but I'm betting it's fine and you have a wiring error or incorrect hardware configuration. First thing to do is make sure the sd card is wired to the correct pins and has good power. Then verify that the SPI clock rate is correct (should run at <=400kHz during card initialization).

 

Offline HackedFridgeMagnet

  • Super Contributor
  • ***
  • Posts: 2039
  • Country: au
Re: Calling on your help again, need some help getting FATFS working...
« Reply #7 on: November 13, 2015, 06:17:49 am »
I wonder if anyone could give me some pointers as to where I should look next.
Nice Double entendre.  :clap:
 

Offline HackedFridgeMagnet

  • Super Contributor
  • ***
  • Posts: 2039
  • Country: au
Re: Calling on your help again, need some help getting FATFS working...
« Reply #8 on: November 13, 2015, 06:28:21 am »
I agree with what Bruce said.

You probably will have to fight through the Macros and Disassembly with the debugger to find out what is returning the Not Ready code.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 29808
  • Country: nl
    • NCT Developments
Re: Calling on your help again, need some help getting FATFS working...
« Reply #9 on: November 13, 2015, 11:00:39 am »
Perhaps try and out if the IDE has some support for figuring out where functions are declared or produce a call stack. It helps a lot if you use an IDE which isn't a glorified version of notepad.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #10 on: November 13, 2015, 12:14:52 pm »
Quote
I've stepped through the code and I get an error when the disk is being initialized and returns 'FR_NOT_READY' from the 'disk_initialize(fs->drv);' function.
This is a generic error. You need to find what specific problem is causing it.

Searching for the error code  FR_NOT_READY, we find (in "ff.c"):-
Code: [Select]
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;

Searching for STA_NOINIT we find in  "diskio.h"
Code: [Select]
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
and in "sd_diskio.c"
Code: [Select]
DSTATUS SD_initialize(BYTE lun)
{
  Stat = STA_NOINIT;
 
  /* Configure the uSD device */
  if(BSP_SD_Init() == MSD_OK)
  {
    Stat &= ~STA_NOINIT;
  }

  return Stat;
}
So if BSP_SD_Init() doesn't return  MSD_OK then you will get the error FR_NOT_READY.

Now let's see what might cause BSP_SD_Init() to fail. In "bsp_driver_sd.c":-
Code: [Select]
uint8_t BSP_SD_Init(void)
{
  uint8_t SD_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR;
  }
  SD_state = HAL_SD_Init(&hsd, &SDCardInfo);
#ifdef BUS_4BITS
  if (SD_state == MSD_OK)
  {
    if (HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B) != SD_OK)
    {
      SD_state = MSD_ERROR;
    }
    else
    {
      SD_state = MSD_OK;
    }
  }
#endif
  return SD_state;
}
But checking if the SD card is plugged in cannot fail, because...
Code: [Select]
uint8_t BSP_SD_IsDetected(void)
{
  __IO uint8_t status = SD_PRESENT;

  /* USER CODE BEGIN 1 */
  /* user code can be inserted here */
  /* USER CODE END 1 */   
 
  return status;
}
which leaves HAL_SD_Init() and HAL_SD_WideBusOperation_Config() as the only possible culprits.

The first function called by HAL_SD_Init() is  HAL_SD_MspInit(hsd)  (in "stm32f4xx_hal_msp.c"):-
Code: [Select]
void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hsd->Instance==SDIO)
  {
  /* USER CODE BEGIN SDIO_MspInit 0 */

  /* USER CODE END SDIO_MspInit 0 */
    /* Peripheral clock enable */
    __SDIO_CLK_ENABLE();
 
    /**SDIO GPIO Configuration   
    PC12     ------> SDIO_CK
    PC11     ------> SDIO_D3
    PC10     ------> SDIO_D2
    PD2     ------> SDIO_CMD
    PC9     ------> SDIO_D1
    PC8     ------> SDIO_D0
    */
    GPIO_InitStruct.Pin = uSD_CLK_Pin|uSD_D3_Pin|uSD_D2_Pin|uSD_D1_Pin
                          |uSD_D0_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = uSD_CMD_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(uSD_CMD_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN SDIO_MspInit 1 */

  /* USER CODE END SDIO_MspInit 1 */
  }

}
Finally we begin to find out what it is actually doing!

The code looks complicated, but I'm betting it's fine and you have a wiring error or incorrect hardware configuration. First thing to do is make sure the sd card is wired to the correct pins and has good power. Then verify that the SPI clock rate is correct (should run at <=400kHz during card initialization).

Thank you for the comprehensive reply.

Out of interest, how is this function:

Code: [Select]
DSTATUS SD_initialize(BYTE lun)
{
  Stat = STA_NOINIT;
 
  /* Configure the uSD device */
  if(BSP_SD_Init() == MSD_OK)
  {
    Stat &= ~STA_NOINIT;
  }

  return Stat;
}

called by
Code: [Select]
disk_initialize();?

I have checked on the scope I have comms from the micro controller with the SD card in 1 bit mode. I see data on MOSI but nothing ever appears on MISO! The SCLK is at 350kHz.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 29808
  • Country: nl
    • NCT Developments
Re: Calling on your help again, need some help getting FATFS working...
« Reply #11 on: November 13, 2015, 03:47:07 pm »
IIRC you also need some pull-ups on the lines. Are those there?
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #12 on: November 14, 2015, 11:38:59 am »
IIRC you also need some pull-ups on the lines. Are those there?

Yes it is, on the MISO.

The SPI out for initialization doesn't look good. This is my next port of call.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #13 on: November 14, 2015, 11:54:11 am »
When i create break points in code that 'should be run' I never hit them? I guess this is normal depending on the structure of the code.
 

Offline HackedFridgeMagnet

  • Super Contributor
  • ***
  • Posts: 2039
  • Country: au
Re: Calling on your help again, need some help getting FATFS working...
« Reply #14 on: November 14, 2015, 01:33:50 pm »
You might have to break earlier in the call hierarchy and then step into the disassembly.
I recall doing this whilst doing FATFS on stm32. And I remember having trouble with init or Not_Ready or the clocks or DMA or something.
 I was using eclipse and the open source debug tools.

Sorry I cant be specific, it was about 18 months ago. 
But I do remember stepping into the disassembly to find the problem, and it wasn't the library.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #15 on: November 14, 2015, 07:36:05 pm »
You might have to break earlier in the call hierarchy and then step into the disassembly.
I recall doing this whilst doing FATFS on stm32. And I remember having trouble with init or Not_Ready or the clocks or DMA or something.
 I was using eclipse and the open source debug tools.

Sorry I cant be specific, it was about 18 months ago. 
But I do remember stepping into the disassembly to find the problem, and it wasn't the library.

Thanks, for the break points, I had to turn off compiler optimizations.

I'll check that out thanks!

Now I'm not sure what's going on. I've created code from the CubeMX program in 1bit and 4bit SDIO mode, I've used this guys implementation:

http://stm32f4-discovery.com/2014/07/library-21-read-sd-card-fatfs-stm32f4xx-devices/

in 4 and 1 bit SDIO as well as SPI interface. I only got FR_DISK_ERROR. So it's something to do with the uSD adapter because I've tested with 3 cards with a variety of formatting.

I think it maybe the card adapter because even with the pull up resistor removed for MISO it's still stuck high with what looks like the small signal on the top of the DC. I'll order a proper SD card with connector I think.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 296
Re: Calling on your help again, need some help getting FATFS working...
« Reply #16 on: November 14, 2015, 07:42:50 pm »
Okay it was the card adapter, I'm going to die now!
 

Offline HackedFridgeMagnet

  • Super Contributor
  • ***
  • Posts: 2039
  • Country: au
Re: Calling on your help again, need some help getting FATFS working...
« Reply #17 on: November 16, 2015, 10:41:24 pm »
I had to turn off compiler optimizations.

^^Oh yes the easy way, forgot to mention that.
In mine space was too tight to turn off the optimisations.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf