您的位置:首页 > 运维架构

nRF51/52 : Pstorage (Flash , Non-volatile Memory) Operation

2017-01-04 14:29 423 查看
    It is very requisite for internet of thing (IoT) application to have a non-volatile memory, it could keep the status when the battery runs out.

   In nRF51/52 series, the flash is called as "Persistent storage", the
APIs of this kind are begin from pstorage.

   There are
examples and
guild for how to exploit the pstorag, but I found those are not concise enough. So in here, I would demonstrate how to call the pstorage api in practice case.

  Continue from my
previous post, I want to add code of pstorage in that.

  Add Below code about line 603 :

static void power_manage(void)
{
uint32_t err_code = sd_app_evt_wait();
APP_ERROR_CHECK(err_code);
}

#ifndef FALSE
#define FALSE       (0)
#define TRUE       (1)
#endif

#define UART_TX_BUF_SIZE      (256)
#define UART_RX_BUF_SIZE      (256)
#define APP_BLOCK_SIZE      (32)

pstorage_handle_t m_app_storage_base_handle;
static uint8_t m_is_need_to_wait_pstorage_operation = FALSE;
static pstorage_block_t m_pstorage_operation_block_id = 0;

unsigned char m_pstorage_buffer[APP_BLOCK_SIZE];

void app_storage_save_data(void);
void app_storage_print_stored_data(void);

/**
* @brief UART events handler.
*/
void uart_events_handler(app_uart_evt_t * p_event)
{

switch (p_event->evt_type)
{
case APP_UART_DATA_READY:
{
unsigned char received_char;
UNUSED_VARIABLE(app_uart_get(&received_char));

if('~' == received_char)
{
app_storage_print_stored_data();
NVIC_SystemReset();
}

{
sprintf((char*)&m_pstorage_buffer[0],
" received char = %c\r\n", received_char);

pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);

/*
m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;
*/

uint32_t  err_code;
err_code = pstorage_update(&block_handle, &m_pstorage_buffer[0],
APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);
printf("storing str :\"%s\" into flash\r\n",
(char*)&m_pstorage_buffer[0]);
}/*store data to flash block*/
}
break;

case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(p_event->data.error_communication);
break;

case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;

case APP_UART_TX_EMPTY:
break;

case APP_UART_DATA:
break;

default:
break;
}
}

/**
* @brief UART initialization.
*/
void uart_config(void)
{
uint32_t                     err_code;
const app_uart_comm_params_t comm_params =
{
RX_PIN_NUMBER,
TX_PIN_NUMBER,
RTS_PIN_NUMBER,
CTS_PIN_NUMBER,
APP_UART_FLOW_CONTROL_DISABLED,
false,
UART_BAUDRATE_BAUDRATE_Baud38400
};

APP_UART_FIFO_INIT(&comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_events_handler,
APP_IRQ_PRIORITY_LOW,
err_code);

APP_ERROR_CHECK(err_code);
}/*uart_config*/

// Event Notification Handler.
static void app_storage_callback_handler(pstorage_handle_t  * handle,
uint8_t              op_code,
uint32_t             result,
uint8_t            * p_data,
uint32_t             data_len)
{
if(handle->block_id == m_pstorage_operation_block_id)
m_is_need_to_wait_pstorage_operation = FALSE;

switch(op_code)
{

case PSTORAGE_STORE_OP_CODE:
if(NRF_SUCCESS != result)
printf("pstorage STORE ERROR callback received \r\n");
break;

case PSTORAGE_LOAD_OP_CODE:
if(NRF_SUCCESS != result)
printf("pstorage LOAD ERROR callback received \r\n");
break;

case PSTORAGE_CLEAR_OP_CODE:
if(NRF_SUCCESS != result)
printf("pstorage CLEAR ERROR callback received \r\n");
break;

case PSTORAGE_UPDATE_OP_CODE:
if(NRF_SUCCESS != result)
printf("pstorage UPDATE ERROR callback received \r\n");
break;

default:
printf("pstorage ERROR callback received \r\n");
break;
}
}/*app_storage_callback_handler*/

/**
* @brief pstorage initializing and block register
*/
void app_storage_init()
{
uint32_t err_code;

err_code = pstorage_init();
APP_ERROR_CHECK(err_code);

pstorage_module_param_t pstorage_param;

pstorage_param.block_size = APP_BLOCK_SIZE;
pstorage_param.block_count = 1;
pstorage_param.cb = app_storage_callback_handler;

err_code = pstorage_register(&pstorage_param, &m_app_storage_base_handle);
APP_ERROR_CHECK(err_code);
#if(0)
{
pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);

m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;

err_code = pstorage_clear(&block_handle, APP_BLOCK_SIZE);
APP_ERROR_CHECK(err_code);

while(FALSE != m_is_need_to_wait_pstorage_operation)
power_manage();
}/*clear data block*/
#endif

}/*pstorage_init_store_and_update*/

void app_storage_save_data(void)
{
uint32_t err_code;

#if(0)
{
pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);

m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;

err_code = pstorage_clear(&block_handle, APP_BLOCK_SIZE);
APP_ERROR_CHECK(err_code);

while(FALSE != m_is_need_to_wait_pstorage_operation)
power_manage();
}/*clear data block*/
#endif
{
pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle, 0, &block_handle);

m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;

//err_code = pstorage_store(&block_handle, &m_pstorage_buffer[0],
// APP_BLOCK_SIZE, 0);
err_code = pstorage_update(&block_handle, &m_pstorage_buffer[0],
APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);

while(FALSE != m_is_need_to_wait_pstorage_operation)
power_manage();
}/*store code block*/

}/*app_storage_save_data*/

void app_storage_print_stored_data(void)
{
uint32_t err_code;
unsigned char storedData[APP_BLOCK_SIZE];

pstorage_handle_t block_handle;

err_code = pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);
APP_ERROR_CHECK(err_code);

err_code = pstorage_load(&storedData[0],
&block_handle, APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);

{
printf("%s\r\n", &storedData[0]);
}
}/*app_storage_print_stored_data*/

/**@brief Function for application main entry.
*/
int main(void)
{
uint32_t err_code;
bool erase_bonds;

uart_config();
printf("Start...\r\n");

// Initialize.
timers_init();

buttons_leds_init(&erase_bonds);
ble_stack_init();

app_storage_init();
app_storage_print_stored_data();
sprintf((char*)&m_pstorage_buffer[0], "new boot string\n\r");

{
pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);

m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;

//err_code = pstorage_store(&block_handle, &m_pstorage_buffer[0],
// APP_BLOCK_SIZE, 0);
err_code = pstorage_update(&block_handle,
&m_pstorage_buffer[0], APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);

while(FALSE != m_is_need_to_wait_pstorage_operation)
power_manage();
}/*store code block*/
app_storage_print_stored_data();

device_manager_init(erase_bonds);
gap_params_init(); 


You could use serial tool (like sscom..etc) to write data (a character) to pstorage.

 for example, when I send 'a' via uart, the flash would be written the string" received char = a".

When you send '~' the nRF51/52 would reboot,  you could find that the string in pstorage would be kept.



 
 

Here is the knacks for using pstorage:

零. The block size should be align of 4, of course.

一. The initialization function pstorage_init (in my case, within the function pstorage_init), should be called after function ble_stack_init. If you call it before  ble_stack_init, the function pstorage_init might lead the system reboot ceaselessly. It is not
necessary to call pstorage_init after  ble_stack_init Immediately, you could call it after the advertise has been started.

二. Before calling the function pstorage_store, it is necessary to call function pstorage_clear, Or the storing action should not be done : the flash contain would not be update. The alternative way is to call function pstorage_update, which is the combination
of pstorage_clear and pstorage_store.

三. When the functions pstorage_store/pstorage_update/pstorage_clear, it costs time to complete the actionafter the functions have returned. In the main "thread", I adopt a global flag (m_is_need_to_wait_pstorage_operation) , while
loop and function power_manage to wait the pstorage has been updatedindeed, that is like:

{
pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle, 0, &block_handle);

m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;

//err_code = pstorage_store(&block_handle, &m_pstorage_buffer[0],
// APP_BLOCK_SIZE, 0);
err_code = pstorage_update(&block_handle, &m_pstorage_buffer[0],
APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);

while(FALSE != m_is_need_to_wait_pstorage_operation)
power_manage();
}/*store code block*/


In the pstorage handler callback function :

// Event Notification Handler.
static void app_storage_callback_handler(pstorage_handle_t  * handle,
uint8_t              op_code,
uint32_t             result,
uint8_t            * p_data,
uint32_t             data_len)
{
if(handle->block_id == m_pstorage_operation_block_id)
m_is_need_to_wait_pstorage_operation = FALSE;

switch(op_code)
{

case PSTORAGE_STORE_OP_CODE:


that could ensure the data be stored into pstorage.

But inside the interrupt callback, calling power_manage would lead system hanging. Therefore, in the uart event handler callback, i do not call the power_manage function:

/**
* @brief UART events handler.
*/
void uart_events_handler(app_uart_evt_t * p_event)
{

switch (p_event->evt_type)
{
case APP_UART_DATA_READY:
{
unsigned char received_char;
UNUSED_VARIABLE(app_uart_get(&received_char));

if('~' == received_char)
{
app_storage_print_stored_data();
NVIC_SystemReset();
}

{
sprintf((char*)&m_pstorage_buffer[0],
" received char = %c\r\n", received_char);

pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_app_storage_base_handle,
0, &block_handle);

/*
m_pstorage_operation_block_id = block_handle.block_id;
m_is_need_to_wait_pstorage_operation = TRUE;
*/

uint32_t  err_code;
err_code = pstorage_update(&block_handle, &m_pstorage_buffer[0],
APP_BLOCK_SIZE, 0);
APP_ERROR_CHECK(err_code);
printf("storing str :\"%s\" into flash\r\n",
(char*)&m_pstorage_buffer[0]);
}/*store data to flash block*/
}
break;


四. Do not update your pstorage too frequently, It would cost much electric power, and the written times is limited : it be written 10000 times before broken typically.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息