Settings subsystem init fails (NVS backend)

Hi,
Working with nRF5340 in NCS 1.9.2, I've overridden weak usb_update_sn_string_descriptor function to set iSerialNumber at runtime.
I wanted to read the actual serial number from settings subsystem, backend-ed in internal flash (NVS).
Code looks like this

/** @brief Overriding weak function to set iSerialNumber at runtime.
 *  @return either original or default serial number string.
 */
static uint8_t sn[sizeof(CONFIG_USB_DEVICE_SN) + 1];

uint8_t *usb_update_sn_string_descriptor(void)
{
	int rc;
	uint32_t val = COSMED_SN_DEFAULT;

	memset(sn, 0, sizeof(sn));

	if (IS_ENABLED(CONFIG_SETTINGS)) {
		rc = settings_subsys_init();
		if (rc) {
			LOG_ERR("error initializing settings subsys [%d]", rc);
		} else {
			rc = load_immediate_value("id/sn", &val, sizeof(val));
			if (rc == -ENOENT) {
				val = COSMED_SN_DEFAULT;
			} else if (rc == 0) { 
				LOG_DBG("<id/sn> = %u", val);
			} else {
				LOG_ERR("error loading sn from settings [%d]", rc);
			}
		}
		LOG_WRN("TODO: manage to store sn in settings from user input");
		rc = settings_save_one("id/sn", (const void *)&val, sizeof(val));
		if (rc) {
			LOG_ERR("error saving sn in settings [%d]", rc);
		}
	}

	snprintk(sn, sizeof(sn), "%u", val);
	return sn;
}

Unfortunately last call of the chain settings_subsys_init() -> settings_backend_init() -> device_get_binding("NRF_FLASH_DRV_NAME") returns NULL.
Settings subsystem initialization at the beginning of main() doesn't rise this exception.

Is there any explanation or workaround ?

Parents
  • Hi Susheel,
    this is the exemplified code

    static uint8_t sn[sizeof(CONFIG_USB_DEVICE_SN) + 1];
    static uint32_t val = 0;
    static struct k_work_delayable pending_work;
    static void mywork(struct k_work *work)
    {
        if (IS_ENABLED(CONFIG_SETTINGS)) {
            ...
            val = 123456789;
        }
    }
    
    uint8_t *usb_update_sn_string_descriptor(void)
    {
        k_work_init_delayable(&pending_work, mywork);
        k_work_schedule(&pending_work, K_MSEC(3000));
    
        snprintk(sn, sizeof(sn), "%u", val);
        return sn;
    }

    Actually mywork() execution happens 3 s after usb_update_sn_string_descriptor().
    The problem is that usb_update_sn_string_descriptor() will not return the desired (val) value set by mywork().

    How to solve this ?

  • OK, I overlooked at the problem, sorry it was my bad.

    The function you have modified (usb_update_sn_string_descriptor) is called from usb_device_init which in turn is called in the early stage of device bootup as shown in the usb_device.c

    SYS_INIT(usb_device_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY);

    This is initialized with the SYS_INIT POST_KERNEL level, and I do not think that the device tree macros are available at this level. 

    So now use the original code you posted (not using work queues) and try to change the usb_device.c last line to below to use APPLICATION level initialization.

    SYS_INIT(usb_device_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

Reply
  • OK, I overlooked at the problem, sorry it was my bad.

    The function you have modified (usb_update_sn_string_descriptor) is called from usb_device_init which in turn is called in the early stage of device bootup as shown in the usb_device.c

    SYS_INIT(usb_device_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY);

    This is initialized with the SYS_INIT POST_KERNEL level, and I do not think that the device tree macros are available at this level. 

    So now use the original code you posted (not using work queues) and try to change the usb_device.c last line to below to use APPLICATION level initialization.

    SYS_INIT(usb_device_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

Children
No Data
Related