Question
How to work with SD Card FileX and USBX MSC on stm32h573i-dk
I'd like to use both FileX and USBX MSC as SD cards on stm32h573i-dk. FileX and USBX MSC worked respectively with reference to the example. USBX MSC cannot be used when using filex_media_open().
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file ux_device_msc.c
* @author MCD Application Team
* @brief USBX Device applicative file
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Includes ------------------------------------------------------------------*/
#include "ux_device_msc.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "main.h"
#include "fx_stm32_sd_driver.h"
/* USER CODE END Includes */
#include "fx_api.h"
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
enum {
SD_WRITE_FLAG = 0x01,
SD_READ_FLAG = 0x02,
};
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
extern SD_HandleTypeDef hsd1;
extern HAL_SD_CardInfoTypeDef sd_info;
extern TX_EVENT_FLAGS_GROUP sdmmc_event;
extern FX_MEDIA sdio_disk;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static INT check_sd_status(uint32_t instance)
{
uint32_t start = tx_time_get();
while (tx_time_get() - start < 100) {
if (fx_stm32_sd_get_status(instance) == 0) {
return 0;
}
}
return 1;
}
/* USER CODE END 0 */
/**
* @brief USBD_STORAGE_Activate
* This function is called when insertion of a storage device.
* @PAram storage_instance: Pointer to the storage class instance.
* @retval none
*/
VOID USBD_STORAGE_Activate(VOID *storage_instance)
{
/* USER CODE BEGIN USBD_STORAGE_Activate */
UX_PARAMETER_NOT_USED(storage_instance);
printf("USBD_STORAGE_Activate\n");
/* USER CODE END USBD_STORAGE_Activate */
return;
}
/**
* @brief USBD_STORAGE_Deactivate
* This function is called when extraction of a storage device.
* @PAram storage_instance: Pointer to the storage class instance.
* @retval none
*/
VOID USBD_STORAGE_Deactivate(VOID *storage_instance)
{
/* USER CODE BEGIN USBD_STORAGE_Activate */
UX_PARAMETER_NOT_USED(storage_instance);
printf("USBD_STORAGE_Activate\n");
/* USER CODE END USBD_STORAGE_Activate */
return;
}
/**
* @brief USBD_STORAGE_Read
* This function is invoked to read from media.
* @PAram storage_instance : Pointer to the storage class instance.
* @PAram lun: Logical unit number is the command is directed to.
* @PAram data_pointer: Address of the buffer to be used for reading or writing.
* @PAram number_blocks: number of sectors to read/write.
* @PAram lba: Logical block address is the sector address to read.
* @PAram media_status: should be filled out exactly like the media status
* callback return value.
* @retval status
*/
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
ULONG number_blocks, ULONG lba, ULONG *media_status)
{
UINT status = UX_SUCCESS;
/* USER CODE BEGIN USBD_STORAGE_Read */
UX_PARAMETER_NOT_USED(storage_instance);
UX_PARAMETER_NOT_USED(lun);
// UX_PARAMETER_NOT_USED(data_pointer);
// UX_PARAMETER_NOT_USED(number_blocks);
// UX_PARAMETER_NOT_USED(lba);
UX_PARAMETER_NOT_USED(media_status);
ULONG WriteFlags = 0;
status = UX_ERROR;
status = check_sd_status(0);
if (status) {
printf("SD card not ready\n");
return status;
}
/* Start the Dma write */
status = fx_stm32_sd_read_blocks(0, (UINT *)data_pointer, lba, number_blocks);
if(status != HAL_OK) {
printf("HAL_SD_ReadBlocks_DMA failed\n");
}
/* Wait on readflag until SD card is ready to use for new operation */
tx_event_flags_get(&sdmmc_event,
SD_READ_FLAG,
TX_OR_CLEAR,
&WriteFlags,
TX_WAIT_FOREVER);
/* USER CODE END USBD_STORAGE_Read */
return status;
}
/**
* @brief USBD_STORAGE_Write
* This function is invoked to write in media.
* @PAram storage_instance : Pointer to the storage class instance.
* @PAram lun: Logical unit number is the command is directed to.
* @PAram data_pointer: Address of the buffer to be used for reading or writing.
* @PAram number_blocks: number of sectors to read/write.
* @PAram lba: Logical block address is the sector address to read.
* @PAram media_status: should be filled out exactly like the media status
* callback return value.
* @retval status
*/
UINT USBD_STORAGE_Write(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
ULONG number_blocks, ULONG lba, ULONG *media_status)
{
UINT status = UX_SUCCESS;
/* USER CODE BEGIN USBD_STORAGE_Write */
UX_PARAMETER_NOT_USED(storage_instance);
// UX_PARAMETER_NOT_USED(lun);
// UX_PARAMETER_NOT_USED(data_pointer);
// UX_PARAMETER_NOT_USED(number_blocks);
// UX_PARAMETER_NOT_USED(lba);
UX_PARAMETER_NOT_USED(media_status);
ULONG ReadFlags = 0U;
status = UX_ERROR;
status = check_sd_status(0);
if (status) {
printf("SD card not ready\n");
return status;
}
/* Start the Dma write */
status = fx_stm32_sd_write_blocks(0, (UINT *)data_pointer, lba, number_blocks);
if(status != HAL_OK) {
printf("HAL_SD_WriteBlocks_DMA failed\n");
}
/* Wait on writeflag until SD card is ready to use for new operation */
tx_event_flags_get(&sdmmc_event,
SD_WRITE_FLAG,
TX_OR_CLEAR,
&ReadFlags,
TX_WAIT_FOREVER);
/* USER CODE END USBD_STORAGE_Write */
return status;
}
/**
* @brief USBD_STORAGE_Flush
* This function is invoked to flush media.
* @PAram storage_instance : Pointer to the storage class instance.
* @PAram lun: Logical unit number is the command is directed to.
* @PAram number_blocks: number of sectors to read/write.
* @PAram lba: Logical block address is the sector address to read.
* @PAram media_status: should be filled out exactly like the media status
* callback return value.
* @retval status
*/
UINT USBD_STORAGE_Flush(VOID *storage_instance, ULONG lun, ULONG number_blocks,
ULONG lba, ULONG *media_status)
{
UINT status = UX_SUCCESS;
/* USER CODE BEGIN USBD_STORAGE_Flush */
UX_PARAMETER_NOT_USED(storage_instance);
UX_PARAMETER_NOT_USED(lun);
UX_PARAMETER_NOT_USED(number_blocks);
UX_PARAMETER_NOT_USED(lba);
UX_PARAMETER_NOT_USED(media_status);
// status = UX_ERROR;
/* USER CODE END USBD_STORAGE_Flush */
return status;
}
/**
* @brief USBD_STORAGE_Status
* This function is invoked to obtain the status of the device.
* @PAram storage_instance : Pointer to the storage class instance.
* @PAram lun: Logical unit number is the command is directed to.
* @PAram media_id: is not currently used.
* @PAram media_status: should be filled out exactly like the media status
* callback return value.
* @retval status
*/
UINT USBD_STORAGE_Status(VOID *storage_instance, ULONG lun, ULONG media_id,
ULONG *media_status)
{
UINT status = UX_SUCCESS;
/* USER CODE BEGIN USBD_STORAGE_Status */
UX_PARAMETER_NOT_USED(storage_instance);
UX_PARAMETER_NOT_USED(lun);
UX_PARAMETER_NOT_USED(media_id);
UX_PARAMETER_NOT_USED(media_status);
// status = UX_ERROR;
/* USER CODE END USBD_STORAGE_Status */
return status;
}
/**
* @brief USBD_STORAGE_Notification
* This function is invoked to obtain the notification of the device.
* @PAram storage_instance : Pointer to the storage class instance.
* @PAram lun: Logical unit number is the command is directed to.
* @PAram media_id: is not currently used.
* @PAram notification_class: specifies the class of notification.
* @PAram media_notification: response for the notification.
* @PAram media_notification_length: length of the response buffer.
* @retval status
*/
UINT USBD_STORAGE_Notification(VOID *storage_instance, ULONG lun, ULONG media_id,
ULONG notification_class, UCHAR **media_notification,
ULONG *media_notification_length)
{
UINT status = UX_SUCCESS;
/* USER CODE BEGIN USBD_STORAGE_Notification */
UX_PARAMETER_NOT_USED(storage_instance);
UX_PARAMETER_NOT_USED(lun);
UX_PARAMETER_NOT_USED(media_id);
UX_PARAMETER_NOT_USED(notification_class);
UX_PARAMETER_NOT_USED(media_notification);
UX_PARAMETER_NOT_USED(media_notification_length);
// status = UX_ERROR;
/* USER CODE END USBD_STORAGE_Notification */
return status;
}
/**
* @brief USBD_STORAGE_GetMediaLastLba
* Get Media last LBA.
* @PAram none
* @retval last lba
*/
ULONG USBD_STORAGE_GetMediaLastLba(VOID)
{
ULONG LastLba = 0U;
/* USER CODE BEGIN USBD_STORAGE_GetMediaLastLba */
LastLba = (ULONG)(sd_info.BlockNbr - 1);
/* USER CODE END USBD_STORAGE_GetMediaLastLba */
return LastLba;
}
/**
* @brief USBD_STORAGE_GetMediaBlocklength
* Get Media block length.
* @PAram none.
* @retval block length.
*/
ULONG USBD_STORAGE_GetMediaBlocklength(VOID)
{
ULONG MediaBlockLen = 0U;
/* USER CODE BEGIN USBD_STORAGE_GetMediaBlocklength */
MediaBlockLen = (ULONG) sd_info.BlockSize;
/* USER CODE END USBD_STORAGE_GetMediaBlocklength */
return MediaBlockLen;
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
