This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

pstorage handler callback without scheduler?

This should be simple, but I just can't get it working.

Many examples show setting a flag before calling the pstorage clear/store/load functions and then looping, waiting for the pstorage handler to change this flag to signify that it finished.

pstorage_sys_event_handler(sys_evt) is in sys_evt_dispatch(uint32_t sys_evt){} and my pstorage handler gets called (I have RTT printf statements that show successful).

volatile uint8_t pstorageState;

static void device_cb_handler(pstorage_handle_t * p_handle, uint8_t op_code, uint32_t result, uint8_t * p_data, uint32_t data_len) {
	switch(op_code) {
		case PSTORAGE_STORE_OP_CODE:
			if(result == NRF_SUCCESS) {
				SEGGER_RTT_WriteString(0, "pstorage_store success\n");
			}
			else {
				SEGGER_RTT_WriteString(0, "pstorage_store fail\n");
			}
			pstorageState = 0;
			break;
		case PSTORAGE_CLEAR_OP_CODE:
			if(result == NRF_SUCCESS) {
				SEGGER_RTT_WriteString(0, "pstorage_clear success\n");
			}
			else {
				SEGGER_RTT_WriteString(0, "pstorage_clear fail\n");
			}
			pstorageState = 0;
			break;
		case PSTORAGE_LOAD_OP_CODE:
			...
	}
}

I do the storing like this:

void store() {
	uint32_t err_code;
	pstorage_handle_t p_block_id;
	
	//clear before store
	pstorageState = 1;
	err_code = pstorage_clear(&m_device_handle, sizeof(device_state_t));
	if(err_code != NRF_SUCCESS) {
		APP_ERROR_CHECK(err_code);
		SEGGER_RTT_WriteString(0, "store() pstorage_clear fail\n");
		return;
	}

	//wait for clear to return
	while(pstorageState) {
		power_manage(); //stuck in this loop forever
	}

	...pstorage_store()...
}

If I remove the while() loops everything works just fine and I have not seen the pstorage handler print out a fail message yet, but I assume I should actually be waiting for the clear to finish before starting the store...

Even though pstorageState is volatile, I tried disabling optimizations (-O0), but that made no difference.

Am I getting stuck in the while loop because I am not using a scheduler?

  • Is device_cb_handler() being called by the pstorage module? If so is it setting the pStorageState variable? If you run, wait a second and then hit break in the debugger, what's the value of pStorageState? If it's '1' then the issue is you're not getting out of power_manage().

    If that's the case - change it to __wfe()

  • If I remove the while() loop, then I will get the printf from the device_cd_handler(), "pstorage_clear success".

    With the while() loop in place, it gets stuck in there. Changing power_manage() to __wfe() made no difference. I changed it to this and it prints outs out '1' forever.

    while(pstorageState) {
    	//power_manage();
    	//__wfe();
    	SEGGER_RTT_printf(0, "pstorageState = %d\n", pstorageState);
    }
    

    I am asking again, just to make sure, is a scheduler required for this to work?

    Thanks.

  • store(), I'm guessing that's called from an interrupt handler, one running with APP_HIGH interrupt priority. If that's the case you never leave the interrupt handler which means the lower-priority SWI which does all the event handling can never run, you've deadlocked yourself.

    Don't put power_manage() in the interrupt handlers, put it in your main context, or run it at a lower interrupt priority (not a fan of that myself, interrupt handlers should be fast if possible). If you put it in your main thread then you'll have to keep some kind of state machine variables to tell you you have started a store() operation and are waiting for the pstorage_clear() to finish in order to do the store.

    So no you don't need a scheduler, there's a ton of ways to do what you want, you may however find a scheduler, which runs in main thread context, it the easiest.

  • The only place I am calling power_manage() is from the main loop:

    // Enter main loop.
    for(;;) {
    	power_manage();
    }
    

    I am assuming that a timer timeoutHandler() is an 'interrupt handler'? Then any function that gets called from inside the timeoutHandler() would be running with APP_HIGH interrupt priority? And any following functions that are called from within the initially-called function would also be APP_HIGH interrupt priority - creating a giant chain of APP_HIGH interrupt priority 'functions'? Then I see the problem...

  • but there's a call to power_manage() in the code you posted for 'store()' which is not your main loop. Or is that not your real code?

    yes a timer timeout handler is called in interrupt context.

Related