cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F412 HardFault_Handler while trying to create new file system

RSheetz
Associate

Dear ST Community, Dear ST Team.

To implement a small USB Device i working with STM32F412 MCU and a Flash Chip mt25ql512.

The Good Part is, that the QSPI Communication works absolutly fine and i can read, write the flash and erase the Chip.

Next Step is to Implement a small Filesystem with FATFS.

After the Standard settings and configure the user_diskio.c, i stuck in the HardFault_Handler after the call f_mkfs() function. So im sitting on a dead end and im glad to hear some ideas or information about that topic.

Thanks for your help.

Thx RSheetz

/********************************************************************************************/

void FatFS_USB_init(void)
{
// FATFS_LinkDriver(&Flash_Driver, USERPath);
FRESULT res = f_mount(&USERFatFS, USERPath, 1);
// If FatFS fails mounting process, create new file system
if (res != FR_OK)
{
f_mkfs(USERPath, FM_FAT32, 0, workBuffer, sizeof(workBuffer));
res = f_mount(&USERFatFS, USERPath, 1);
}
}

/********************************************************************************************/

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file user_diskio.c
* @brief This file includes a diskio driver skeleton to be completed by the user.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */

#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
/*
* Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
* To be suppressed in the future.
* Kept to ensure backward compatibility with previous CubeMx versions when
* migrating projects.
* User code previously added there should be copied in the new user sections before
* the section contents can be deleted.
*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#endif

/* USER CODE BEGIN DECL */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"
#include "qspiFlashHandler.h"
#include "mt25ql512.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;

/* USER CODE END DECL */

/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
#if _USE_WRITE == 1
DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
#endif /* _USE_IOCTL == 1 */

Diskio_drvTypeDef USER_Driver =
{
USER_initialize,
USER_status,
USER_read,
#if _USE_WRITE
USER_write,
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};

/* Private functions ---------------------------------------------------------*/

/**
* @brief Initializes a Drive
* @PAram pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS USER_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
/* USER CODE BEGIN INIT */
Stat = STA_NOINIT;
if (pdrv != 0)
{
return STA_NOINIT;
}
Stat = QSPIFL_init(); // QSPIFL_init(); needs to run before
return RES_OK;
/* USER CODE END INIT */
}

/**
* @brief Gets Disk Status
* @PAram pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS USER_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
/* USER CODE BEGIN STATUS */
Stat = STA_NOINIT;
return Stat;
/* USER CODE END STATUS */
}

/**
* @brief Reads Sector(s)
* @PAram pdrv: Physical drive number (0..)
* @PAram *buff: Data buffer to store read data
* @PAram sector: Sector address (LBA)
* @PAram count: Number of sectors to read (1..128)
* @retval DRESULT: Operation result
*/
DRESULT USER_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
/* USER CODE BEGIN READ */
if (pdrv != 0 || Stat & STA_NOINIT)
{
return RES_NOTRDY;
}
uint32_t addr = sector * MT25QL512_MEMORY_SECTOR_SIZE;
uint32_t size = count * MT25QL512_MEMORY_SECTOR_SIZE;
if (QSPIFL_readMemory(buff, addr, size) != QSPIFL_OK)
{
return RES_ERROR;
}
return RES_OK;
/* USER CODE END READ */
}

/**
* @brief Writes Sector(s)
* @PAram pdrv: Physical drive number (0..)
* @PAram *buff: Data to be written
* @PAram sector: Sector address (LBA)
* @PAram count: Number of sectors to write (1..128)
* @retval DRESULT: Operation result
*/
#if _USE_WRITE == 1
DRESULT USER_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
/* USER CODE BEGIN WRITE */
/* USER CODE HERE */
if (pdrv != 0 || Stat & STA_NOINIT)
{
return RES_NOTRDY;
}
uint32_t addr = sector * MT25QL512_MEMORY_SECTOR_SIZE;
uint32_t size = count * MT25QL512_MEMORY_SECTOR_SIZE;
if (QSPIFL_eraseSector(addr, addr + size) != QSPIFL_OK)
{
return RES_ERROR;
}

if (QSPIFL_writeMemory((uint8_t *)buff, addr, size) != QSPIFL_OK)
{
return RES_ERROR;
}
return RES_OK;

/* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */

/**
* @brief I/O control operation
* @PAram pdrv: Physical drive number (0..)
* @PAram cmd: Control code
* @PAram *buff: Buffer to send/receive control data
* @retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT USER_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
/* USER CODE BEGIN IOCTL */
DRESULT res = RES_ERROR;
return res;
/* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */

 

1 ACCEPTED SOLUTION

Accepted Solutions
KDJEM.1
ST Employee

Hello @RSheetz;

 

I recommend you to look at the How to create a file system on a SD card using STM32CubeIDE may help you.

Also, I think this article How to debug a HardFault on an Arm® Cortex®-M STM32 can help you to debug the HardFault. 

 

I hope this help you.

Thank you.

Kaouthar

 

 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

2 REPLIES 2
Andrew Neil
Super User

Welcome to the forum.

Please seeHow to write your question to maximize your chances to find a solution; for best results; in particularHow to insert source code.

 

On debugging hard faults:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/tac-p/708193/highlight/true#M51

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
KDJEM.1
ST Employee

Hello @RSheetz;

 

I recommend you to look at the How to create a file system on a SD card using STM32CubeIDE may help you.

Also, I think this article How to debug a HardFault on an Arm® Cortex®-M STM32 can help you to debug the HardFault. 

 

I hope this help you.

Thank you.

Kaouthar

 

 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.