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 :
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:
In the pstorage handler callback function :
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:
四. 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.
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.
相关文章推荐
- Spark SQL 源码分析之 In-Memory Columnar Storage 之 cache table
- Operation not permitted on IsolatedStorageFileStream解决方法(转)
- Byte Buffers and Non-Heap Memory
- ORA-30009: Not enough memory for CONNECT BY operation
- ORA-30009: Not enough memory for CONNECT BY operation
- 内存屏障(__asm__ __volatile__("": : :"memory"))
- mydqldump 备份数单库 然后还原数据的时候报:ERROR 1881 (HY000) at line 52: Operation not allowed when innodb_forced_recovery > 0.
- Non-Binary Error Control Coding for Wireless Communication and Data Storage
- STM8S——Flash program memory and data EEPROM
- linux/android memory/flash layout
- __asm__ __volatile__("": : :"memory")
- Memory Size Class for viewing available storage
- Getting Flash to work on non-hero builds 中文名字 如何让Flash在非Hero手机上运行
- 一种新型内存SCM(Storage Class Memory)的简单介绍
- __asm__ __volatile__("": : :"memory")含义
- __asm__ __volatile__("": : :"memory")
- Load flash from memory stream
- PatentTips - Reducing Write Amplification in a Flash Memory
- __asm__ __volatile__("": : :"memory")含义
- Operation not permitted on IsolatedStorageFileStream 解决方法