Calling on your help again, need some help getting FATFS working... - Page 1
Forum section: electronics / general

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 11, 2015, 07:02:16 pm
content: 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 */

author: Karel
author_rank: Super Contributor
timestamp: November 12, 2015, 10:08:09 am
content: 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.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 12, 2015, 12:21:07 pm
content: 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 == 0){disk.is_initialized = 1;stat = disk.drv->disk_initialize(disk.lun);}return stat;}I'm a little confused with this line.stat = disk.drv->disk_initialize(disk.lun);So stat is equal to the variable drv 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.

author: FreddyVictor
author_rank: Regular Contributor
timestamp: November 12, 2015, 12:55:00 pm
content: Quote from: Boscoe on November 12, 2015, 12:21:07 pmI'm guessing the disk.drv->disk_initialize(disk.lun) one is a (member) function pointer so can point toany'disk_initialize' function.confusingly it'is the same name as the function it's being called within!c at its best

author: nctnico
author_rank: Super Contributor
timestamp: November 12, 2015, 01:08:08 pm
content: Quote from: Karel on November 12, 2015, 10:08:09 amActually 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.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 12, 2015, 03:03:17 pm
content: Quote from: nctnico on November 12, 2015, 01:08:08 pmWell 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!)

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: November 13, 2015, 05:47:51 am
content: QuoteThis 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:stat = disk_initialize(pdrv);if (stat & STA_NOINIT) return FR_NOT_READY;Searching for STA_NOINIT we find in "diskio.h"Code:/* Disk Status Bits (DSTATUS) */#define STA_NOINIT0x01/* Drive not initialized */and in "sd_diskio.c"Code: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: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_4BITSif (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;}}#endifreturn SD_state;}But checking if the SD card is plugged in cannot fail, because...Code: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: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 ConfigurationPC12 ------> SDIO_CKPC11 ------> SDIO_D3PC10 ------> SDIO_D2PD2 ------> SDIO_CMDPC9 ------> SDIO_D1PC8 ------> 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).

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: November 13, 2015, 06:17:49 am
content: Quote from: Boscoe on November 11, 2015, 07:02:16 pmNice Double entendre.

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: November 13, 2015, 06:28:21 am
content: 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.

author: nctnico
author_rank: Super Contributor
timestamp: November 13, 2015, 11:00:39 am
content: 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.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 13, 2015, 12:14:52 pm
content: Quote from: Bruce Abbott on November 13, 2015, 05:47:51 amThank you for the comprehensive reply.Out of interest, how is this function:Code:DSTATUS SD_initialize(BYTE lun){Stat = STA_NOINIT;/* Configure the uSD device */if(BSP_SD_Init() == MSD_OK){Stat &= ~STA_NOINIT;}return Stat;}called byCode: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.

author: nctnico
author_rank: Super Contributor
timestamp: November 13, 2015, 03:47:07 pm
content: IIRC you also need some pull-ups on the lines. Are those there?

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 14, 2015, 11:38:59 am
content: Quote from: nctnico on November 13, 2015, 03:47:07 pmYes it is, on the MISO.The SPI out for initialization doesn't look good. This is my next port of call.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 14, 2015, 11:54:11 am
content: 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.

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: November 14, 2015, 01:33:50 pm
content: 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.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 14, 2015, 07:36:05 pm
content: Quote from: HackedFridgeMagnet on November 14, 2015, 01:33:50 pmThanks, 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.

author: Boscoe
author_rank: Frequent Contributor
timestamp: November 14, 2015, 07:42:50 pm
content: Okay it was the card adapter, I'm going to die now!

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: November 16, 2015, 10:41:24 pm
content: Quote from: Boscoe on November 14, 2015, 07:42:50 pm^^Oh yes the easy way, forgot to mention that.In mine space was too tight to turn off the optimisations.