Enable USB mass storage (SD card) only when USB connected

Hi,

I am working on a battery powered device that collects data, save it to files and go to sleep, when it is not connected to a laptop via USB. When connected, the device just become a "usb sd card reader" that shows the files, the sensors are disabled and the device never goes to sleep. I have based my application on the MSC sample, I can read the SD when I connect to a PC with no issue. My problem is when not connected to USB, on a "fresh" boot I can save data files fine but after waking up from sleep I get an initialisation error from usb_msc and a system reset, the next boot works fine (data can be written on sd) until the mcu is sent to sleep again and the loop repeats. It seems that I need to disable/uninit the mass storage before going to sleep somehow. However wouldn't CONFIG_USB_MASS_STORAGE=y keep the mass storage enabled, is there a way to only have Mass storage activated when connected with USB?

I found this post but it is using a older ncs sdk and this post that suggest to change the USB descriptors at runtime but I couldn't figure out how to edit the descriptors at runtime.

I am using nrf-sdk 2.6.1 on VS code, a nrf5340 custom PCB.

Any help would be greatly appreciated.

main.c

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/printk.h>

#define SLEEP_TIME_MS 1000

#define MODULE main
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_DBG);


#include <inttypes.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/pm/pm.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#include <zephyr/sys/poweroff.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/gpio.h>
#include <hal/nrf_gpio.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/init.h>
#include <zephyr/sys/reboot.h>

#define SD_THREAD_STACK_SIZE 4096
K_THREAD_STACK_DEFINE(sd_thread_stack, SD_THREAD_STACK_SIZE);
struct k_thread sd_thread_data;


void sd_init_thread(void)
{
    LOG_DBG("Starting SD card initialization thread...");

    turn_off_sd(0);  // Ensure SD card power is on
    int ret = sd_card_init();
    if (ret != 0) {
        LOG_ERR("Failed to initialize SD card");
    } else {
        sd_card_initialized = 1; 
        save_sd_init_config(1);
        LOG_DBG("SD card initialized successfully.");
    }
}

void status_cb(enum usb_dc_status_code status, const uint8_t *param)
{
    switch (status) {
        case USB_DC_CONNECTED:
            LOG_DBG("Device connected");
            if (!sd_card_initialized) {
                LOG_DBG("Starting SD initialization thread...");
                k_thread_create(&sd_thread_data, sd_thread_stack,
                                K_THREAD_STACK_SIZEOF(sd_thread_stack),
                                sd_init_thread, NULL, NULL, NULL,
                                K_LOWEST_APPLICATION_THREAD_PRIO, 0, K_NO_WAIT);
            }
            save_usb_connected_config(1);
            usb_connected = 1;
            break;

        case USB_DC_DISCONNECTED:
            LOG_INF("Device disconnected");
            if (sd_card_initialized) {
                LOG_INF("Unmounting SD card...");
                unmount_sd_card();
                turn_off_sd(0);  // Turn off SD card power
                sd_card_initialized = 0;
                save_sd_init_config(0);
                LOG_INF("SD card unmounted and powered off.");
            }
            save_usb_connected_config(0);
            usb_connected = 0;
			save_usb_callback_config(1);
			usb_call_back_set = 1;
			usb_disable();
            break;

        default:
            LOG_DBG("status %u unhandled", status);
            break;
    }
}

int main(void)
{
	if(usb_call_back_set == 0){
		int ret = usb_enable(status_cb);
		LOG_INF("Enable USB...");
		if (ret != 0) {
			LOG_ERR("Failed to enable USB");
			//return 0;
		}
		save_usb_callback_config(1);
		usb_call_back_set = 1;
	}
	
	accelerometer_init(usb_connected, sd_card_initialized);
	accelerometer_run();

	LOG_DBG("Done.");
	return 0;
}

logs

SEGGER J-Link V7.94e - Real time terminal output
SEGGER J-Link (unknown) V1.0, SN=801046272
Process: JLink.exe
[00:00:00.003,875] <inf> lis2dh: LIS2DH: int2 on [email protected]
[00:00:00.006,103] <inf> lis2dh: fs=2, odr=0x3 lp_en=0x8 scale=9576
[00:00:00.007,568] <inf> pcf85063a: pcf85063a@51 is initialized!
*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
[00:00:00.149,169] <inf> main: Hi! DFU Starting nrf5340dk_nrf5340_cpuapp
[00:00:00.165,069] <inf> nvs_storage: set SD_INIT config 0 at id 7
[00:00:00.165,924] <inf> nvs_storage: set acc sensitivity config 1.200 at id 4
[00:00:00.166,687] <inf> nvs_storage: config: 4, acc_sensitivity: 1.200
[00:00:00.174,774] <inf> nvs_storage: set acc sampling config 1 at id 3
[00:00:00.175,476] <inf> nvs_storage: config: 3, acc_sampling: 1
[00:00:00.175,933] <inf> nvs_storage: The integer value is: 1
[00:00:00.176,452] <inf> nvs_storage: config: 7, SD_INIT: 0
[00:00:00.176,879] <inf> nvs_storage: The integer value is: 0
[00:00:00.177,947] <inf> main: Enable USB...
[00:[00:00:08.308,868] <inf> accelerometer: Motion detected, starting data collection
[00:00:08.309,387] <inf> accelerometer: Motion detected, starting data collection, usb_connected:0 sd_card_initialized:0
[00:00:08.428,436] <inf> accelerometer: Motion detected, starting data collection
[00:00:08.428,955] <inf> accelerometer: Motion detected, starting data collection, usb_connected:0 sd_card_initialized:0
[00:00:13.430,206] <inf> accelerometer: Motion timer expired, stopping data collection
[00:00:13.430,725] <inf> accelerometer: Submit to queue...
[00:00:13.431,152] <inf> accelerometer: sd_card_write_work_handler called
[00:00:13.609,130] <inf> nvs_storage: set SD_INIT config 1 at id 7
[00:00:13.610,900] <inf> accelerometer: filename:2BFE6027164802EE_2020_04_12.csv
[00:00:13.688,476] <inf> accelerometer: Unmount disk...
[00:00:13.688,720] <inf> accelerometer: Disk unmounted.
[00:00:13.694,702] <inf> nvs_storage: set SD_INIT config 0 at id 7
[00:00:13.695,159] <inf> accelerometer: Unmount done.
[00:00:13.695,526] <inf> accelerometer: CONFIG acc_sensitivity:1.200000 acc_sampling:1 usb_connected:0 usb_call_back_set:1 sd_card_initialized:0
[00:00:13.696,105] <inf> accelerometer: Going to sleep...
[00:00:13.702,117] <inf> nvs_storage: set USB_CALLBACK config 0 at id 6
[00:00:00.003,875] <inf> lis2dh: LIS2DH: int2 on [email protected]
[00:00:00.006,042] <inf> lis2dh: fs=2, odr=0x3 lp_en=0x8 scale=9576
[00:00:00.007,446] <inf> pcf85063a: pcf85063a@51 is initialized!
*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
[00:00:00.014,831] <err> usb_msc: Storage init ERROR !!!! - Aborting USB init
[00:00:00.015,716] <inf> main: Hi! DFU Starting nrf5340dk_nrf5340_cpuapp
[00:00:00.031,341] <inf> nvs_storage: set SD_INIT config 0 at id 7
[00:00:00.031,860] <inf> nvs_storage: config: 4, acc_sensitivity: 1.200
[00:00:00.032,409] <inf> nvs_storage: config: 3, acc_sampling: 0
[00:00:00.032,867] <inf> nvs_storage: The integer value is: 0
[00:00:00.033,416] <inf> nvs_storage: config: 7, SD_INIT: 0
[00:00:00.033,813] <inf> nvs_storage: The integer value is: 0
[00:00:00.034,851] <inf> main: Enable USB...
[00:00:00.042,694] <inf> nvs_storage: set USB_CALLBACK config 1 at id 6
[00:00:00.043,365] <inf> main: CONFIG acc_sensitivity:1.200000 acc_sampling:0 usb_connected:0 usb_call_back_set:1 sd_card_initialized:0
[00:00:00.044,525] <inf> accelerometer: Setting triggers for motion detection...
[00:00:00.048,553] <inf> lis2dh: int2_ths=0x4c range_g=2 ums2=11767979
[00:00:00.050,903] <inf> lis2dh: int2_dur=0x0
[00:00:00.052,246] <dbg> main: main: Done.
[00:00:10.573,455] <inf> accelerometer: Motion detected, starting data collection
[00:00:10.573,974] <inf> accelerometer: Motion detected, starting data collection, usb_connected:0 sd_card_initialized:0
[00:00:10.578,552] <err> os: ***** USAGE FAULT *****
[00:00:10.578,918] <err> os:   Division by zero
[00:00:10.579,315] <err> os: r0/a1:  0x000003e7  r1/a2:  0x200437ec  r2/a3:  0x00000000
[00:00:10.579,895] <err> os: r3/a4:  0x00000000 r12/ip:  0x00000000 r14/lr:  0x000093bb
[00:00:10.580,444] <err> os:  xpsr:  0x21000000
[00:00:10.580,841] <err> os: Faulting instruction address (r15/pc): 0x000091ea
[00:00:10.581,359] <err> os: >>> ZEPHYR FATAL ERROR 30: Unknown error on CPU 0
[00:00:10.581,878] <err> os: Current thread: 0x200092d8 (sysworkq)
[00:00:10.587,341] <err> fatal_error: Resetting system

[00:00:10.580,841] <err> os: Faulting instruction address (r15/pc): 0x000091ea
[00:00:10.581,359] <err> os: >>> ZEPHYR FATAL ERROR 30: Unknown error on CPU 0
[00:00:10.581,878] <err> os: Current thread: 0x200092d8 (sysworkq)
[00:00:10.587,341] <err> fatal_error: Resetting system
[00:00:00.003,875] <inf> lis2dh: LIS2DH: int2 on [email protected]
[00:00:00.006,042] <inf> lis2dh: fs=2, odr=0x3 lp_en=0x8 scale=9576
[00:00:00.007,446] <inf> pcf85063a: pcf85063a@51 is initialized!
*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
[00:00:00.148,498] <inf> main: Hi! DFU Starting nrf5340dk_nrf5340_cpuapp
[00:00:00.164,123] <inf> nvs_storage: set SD_INIT config 0 at id 7
[00:00:00.164,672] <inf> nvs_storage: config: 4, acc_sensitivity: 1.200
[00:00:00.165,222] <inf> nvs_storage: config: 3, acc_sampling: 1
[00:00:00.165,679] <inf> nvs_storage: The integer value is: 1
[00:00:00.166,229] <inf> nvs_storage: config: 7, SD_INIT: 0
[00:00:00.166,656] <inf> nvs_storage: The integer value is: 0
[00:00:00.167,694] <inf> main: Enable USB...
[00:00:00.175,506] <inf> nvs_storage: set USB_CALLBACK config 1 at id 6
[00:00:00.176,055] <inf> main: CONFIG acc_sensitivity:1.200000 acc_sampling:1 usb_connected:0 usb_call_back_set:1 sd_card_initialized:0
[00:00:00.177,185] <inf> accelerometer: Setting triggers for motion detection...
[00:00:00.181,213] <inf> lis2dh: int2_ths=0x4c range_g=2 ums2=11767979
[00:00:00.183,563] <inf> lis2dh: int2_dur=0x0
[00:00:00.184,997] <dbg> main: main: Done.
[00:00:00.185,485] <inf> accelerometer: Motion detected, starting data collection
[00:00:00.186,004] <inf> accelerometer: Motion detected, starting data collection, usb_connected:0 sd_card_initialized:0
[00:00:05.187,225] <inf> accelerometer: Motion timer expired, stopping data collection
[00:00:05.187,744] <inf> accelerometer: Submit to queue...
[00:00:05.188,171] <inf> accelerometer: sd_card_write_work_handler called
[00:00:05.366,058] <inf> nvs_storage: set SD_INIT config 1 at id 7
[00:00:05.367,828] <inf> accelerometer: filename:2BFE6027164802EE_2020_04_12.csv
[00:00:05.445,343] <inf> accelerometer: Unmount disk...
[00:00:05.445,587] <inf> accelerometer: Disk unmounted.
[00:00:05.451,538] <inf> nvs_storage: set SD_INIT config 0 at id 7
[00:00:05.451,995] <inf> accelerometer: Unmount done.
[00:00:05.452,362] <inf> accelerometer: CONFIG acc_sensitivity:1.200000 acc_sampling:1 usb_connected:0 usb_call_back_set:1 sd_card_initialized:0
[00:00:05.452,941] <inf> accelerometer: Going to sleep...
[00:00:05.458,923] <inf> nvs_storage: set USB_CALLBACK config 0 at id 6

pjr.conf

#Storage related
CONFIG_SPI=y
CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=128

#Filesystem
CONFIG_DISK_ACCESS=y
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_FS_FATFS_EXFAT=y

#Add external flash
CONFIG_DISK_DRIVER_SDMMC=y
CONFIG_SDMMC_SUBSYS=y

CONFIG_SD_LOG_LEVEL_DBG=n
CONFIG_SDHC_LOG_LEVEL_DBG=n

#USB related configs
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PID=0x0008
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y
CONFIG_USB_MASS_STORAGE=y
CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y
CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_MASS_STORAGE_STACK_SIZE=8192
CONFIG_LOG=y
CONFIG_USB_WORKQUEUE_STACK_SIZE=4096

Kconfig

config APP_WIPE_STORAGE
	bool "Option to clear the flash area before mounting"
	help
	  Use this to force an existing file system to be created.

choice
	prompt "Storage and file system type used by the application"
	default APP_MSC_STORAGE_NONE
	help
	  Specify the type of storage and file system.

config APP_MSC_STORAGE_NONE
	bool "Use RAM disk as block device"

config APP_MSC_STORAGE_RAM
	bool "Use RAM disk and FAT file system"
	imply FILE_SYSTEM
	imply FAT_FILESYSTEM_ELM

config APP_MSC_STORAGE_FLASH_FATFS
	bool "Use FLASH disk and FAT file system"
	imply DISK_DRIVER_FLASH
	imply FILE_SYSTEM
	imply FAT_FILESYSTEM_ELM

config APP_MSC_STORAGE_FLASH_LITTLEFS
	bool "Use FLASH disk and LittleFS"
	imply DISK_DRIVER_FLASH
	imply FILE_SYSTEM
	imply FILE_SYSTEM_LITTLEFS

config APP_MSC_STORAGE_SDCARD
	bool "Use SDHC and FAT file system"
	imply DISK_DRIVER_SDMMC
	imply FILE_SYSTEM
	imply FAT_FILESYSTEM_ELM

endchoice

config MASS_STORAGE_DISK_NAME
	default "NAND" if DISK_DRIVER_FLASH
	default "RAM" if DISK_DRIVER_RAM
	default "SD" if DISK_DRIVER_SDMMC

if DISK_DRIVER_FLASH

config FLASH_MAP
	default y

config FLASH_PAGE_LAYOUT
	default y

config FLASH_LOG_LEVEL
	default 3

if NORDIC_QSPI_NOR

config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE
	default 4096

config FF_FS_NORTC
	int "Timestamp"
	default 0

endif # NORDIC_QSPI_NOR

endif # DISK_DRIVER_FLASH

source "Kconfig.zephyr"

Parents Reply Children
Related