![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Sample application that shows the use of persistent storage (pstorage) in Nordic nRF51822 tigether with a BLE service
Simple example that shows the use of pstorage (persistent storage) in nRF51822
The code is based on an example proposed at Nordic Developer Zone:
main.cpp
- Committer:
- tumaku
- Date:
- 2015-03-05
- Revision:
- 1:b8cefa34f89d
- Parent:
- 0:49d5cce77458
File content as of revision 1:b8cefa34f89d:
// Sample app that shows the use of persistent staprage in nRF51822 (pstorage) together with BLE // Based on the sample code proposed at Nordic developers forum: // https://devzone.nordicsemi.com/question/15271/how-can-i-write-10kb-of-data-to-internal-flash/?answer=17300#post-id-17300 // https://devzone.nordicsemi.com/attachment/9b7ebaa65cd8f4f0eeb9d8fd99937c54 #include "mbed.h" #include "BLEDevice.h" #include "UARTService.h" #include "pstorage.h" #include "nrf_error.h" DigitalOut magnet(p15); #define MAGNET_ON 1 #define MAGNET_OFF 0 Ticker ticker; int tickerState=MAGNET_OFF; #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; * it will have an impact on code-size and power consumption. */ #if NEED_CONSOLE_OUTPUT #define DEBUG(...) { printf(__VA_ARGS__); } //Defaults to stdio without having to wirte pcUart explicitly #else #define DEBUG(...) /* nothing */ #endif /* #if NEED_CONSOLE_OUTPUT */ Serial pcUart(USBTX, USBRX); // tx, rx Still required to read data coming from the PC BLEDevice ble; // Create Bluetooth object UARTService *uartServicePtr; #define PS_NOT_INIT 0 #define PS_WAITING_FOR_NEXT_COMMAND 1 //#define PS_STATE_INIT_AND_REGISTER 2 #define PS_CLEAR_3_BLOCKS 3 #define PS_STORE_ALL 4 #define PS_CLEAR_2_BLOCKS 5 #define PS_UPDATE_1_BLCK 6 uint8_t psState= PS_NOT_INIT; uint8_t psNextState= PS_WAITING_FOR_NEXT_COMMAND; pstorage_handle_t handle; pstorage_handle_t block_0_handle; pstorage_handle_t block_1_handle; pstorage_handle_t block_2_handle; pstorage_module_param_t param; uint8_t source_data_0[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F}; uint8_t source_data_1[16] = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F}; uint8_t source_data_2[16] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F}; uint8_t source_data_9[16] = {0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34}; uint8_t dest_data_0[16]; uint8_t dest_data_1[16]; uint8_t dest_data_2[16]; static void psLoadAllBlocks(void); #define PS_NOT_INIT 0 #define PS_WAITING_FOR_NEXT_COMMAND 1 //#define PS_STATE_INIT_AND_REGISTER 2 #define PS_CLEAR_3_BLOCKS 3 #define PS_STORE_ALL 4 #define PS_CLEAR_2_BLOCKS 5 #define PS_UPDATE_1_BLCK 6 void magnetControl(void) { DEBUG("Timer\r\n"); DEBUG("Timer State %d \r\n",tickerState); if (tickerState==MAGNET_ON) { magnet=1; tickerState=MAGNET_OFF; } else { // (tickerState==MAGNET_OFF) magnet=0; tickerState=MAGNET_OFF; ticker.detach(); } } /* BLE disconnected callback */ void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { DEBUG("Disconnected!\n\r"); DEBUG("Restarting the advertising process\n\r"); ble.startAdvertising(); } /* BLE UART data received callback */ void onDataWritten(const GattCharacteristicWriteCBParams *params) { if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) { //If characters received over BLE uint16_t bytesRead = params->len; DEBUG("received %u bytes\n\r", bytesRead); DEBUG("Received string: '"); //Note the size of data expands to the largest string received. Need to use bytesRead to resize. for (int i=0;i<bytesRead; i++) { DEBUG("%c",params->data[i]); } DEBUG("'\n\r"); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data,bytesRead); // Echo received characters back over BLE } ticker.detach(); tickerState=MAGNET_ON; ticker.attach(magnetControl,0.7); } /* pcUART read callback */ void rxInterrupt(void) { while (pcUart.readable()) { if (pcUart.readable()) { char s[2]; s[1]=0; s[0]=pcUart.getc(); if (s[0]=='0') psLoadAllBlocks(); if (psState==PS_WAITING_FOR_NEXT_COMMAND){ switch(s[0]) { case '1': psNextState=PS_CLEAR_3_BLOCKS; break; case '2': psNextState=PS_STORE_ALL; break; case '3': psNextState=PS_CLEAR_2_BLOCKS; break; case '4': psNextState=PS_UPDATE_1_BLCK; break; default: break; } } // DEBUG("-%c_",s[0]); uartServicePtr->write(s,1); } } } static void checkPsState(pstorage_block_t blockId) { if (psState==PS_CLEAR_3_BLOCKS ) { psState=PS_WAITING_FOR_NEXT_COMMAND; return; } if ((psState==PS_STORE_ALL )&&(blockId==block_2_handle.block_id)) { psState=PS_WAITING_FOR_NEXT_COMMAND; return; } if (psState==PS_CLEAR_2_BLOCKS ) { psState=PS_WAITING_FOR_NEXT_COMMAND; return; } if (psState==PS_UPDATE_1_BLCK ) { psState=PS_WAITING_FOR_NEXT_COMMAND; return; } } static void example_cb_handler(pstorage_handle_t * handle, uint8_t op_code, uint32_t result, uint8_t * p_data, uint32_t data_len) { checkPsState(handle->block_id); DEBUG("ps handler\r\n"); switch(op_code) { case PSTORAGE_LOAD_OP_CODE: if (result == NRF_SUCCESS) { DEBUG("ps LOAD ok %d \r\n",handle->block_id); } else { DEBUG("ps LOAD Failed %d %d \r\n",handle->block_id, result); } break; case PSTORAGE_STORE_OP_CODE: if (result == NRF_SUCCESS) { DEBUG("ps STORE ok %d \r\n",handle->block_id); } else { DEBUG("ps STORE Failed %d %d \r\n",handle->block_id, result); } break; case PSTORAGE_UPDATE_OP_CODE: if (result == NRF_SUCCESS) { DEBUG("ps UPDATE ok %d \r\n",handle->block_id); } else { DEBUG("ps UPDATE Failed %d %d \r\n",handle->block_id, result); } break; case PSTORAGE_CLEAR_OP_CODE: if (result == NRF_SUCCESS) { DEBUG("ps CLEAR ok %d \r\n",handle->block_id); } else { DEBUG("ps CLEAR Failed %d %d \r\n",handle->block_id, result); } break; case PSTORAGE_ERROR_OP_CODE: DEBUG("ps ERROR %d \r\n",handle->block_id); break; } } static void psInit(void) { uint32_t retval; retval = pstorage_init(); if(retval != NRF_SUCCESS) { DEBUG("ps init error\r\n"); return; } else { DEBUG("ps init ok\r\n"); } param.block_size = 16; //Select block size of 16 bytes param.block_count = 10; //Select 10 blocks, total of 160 bytes param.cb = example_cb_handler; //Set the pstorage callback handler retval = pstorage_register(¶m, &handle); if (retval != NRF_SUCCESS) { DEBUG("ps register error\r\n"); return; } else { DEBUG("ps register ok\r\n"); } //Get block identifiers pstorage_block_identifier_get(&handle, 0, &block_0_handle); pstorage_block_identifier_get(&handle, 1, &block_1_handle); pstorage_block_identifier_get(&handle, 2, &block_2_handle); DEBUG("ps identifier get OK\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; psNextState= PS_WAITING_FOR_NEXT_COMMAND; } static void psClear3Blocks(void) { uint32_t retval; psState= PS_CLEAR_3_BLOCKS; retval= pstorage_clear(&block_0_handle, 48); //Clear 48 bytes if (retval != NRF_SUCCESS) { DEBUG("ps clear error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps clear ok\r\n"); } } static void psStoreAll(void) { uint32_t retval; psState= PS_STORE_ALL; retval= pstorage_store(&block_0_handle, source_data_0, 16, 0); if (retval != NRF_SUCCESS) { DEBUG("ps store block 0 error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps store block 0 ok\r\n"); } retval= pstorage_store(&block_1_handle, source_data_1, 16, 0); if (retval != NRF_SUCCESS) { DEBUG("ps store block 1 error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps store block 1 ok\r\n"); } retval= pstorage_store(&block_2_handle, source_data_2, 16, 0); if (retval != NRF_SUCCESS) { DEBUG("ps store block 2 error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps store block 2 ok\r\n"); } uint32_t count; retval = pstorage_access_status_get(&count); DEBUG("ps pending %d returncode %d\r\n", count,retval); } static void psClear2Blocks(void) { uint32_t retval; psState= PS_CLEAR_2_BLOCKS; retval= pstorage_clear(&block_0_handle, 32); //Clear 32 bytes if (retval != NRF_SUCCESS) { DEBUG("ps clear error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps clear ok\r\n"); } } static void psUpdate1Block(void) { uint32_t retval; psState= PS_UPDATE_1_BLCK; retval=pstorage_update(&block_0_handle, source_data_9, 16, 0); if (retval != NRF_SUCCESS) { DEBUG("ps clear error\r\n"); psState=PS_WAITING_FOR_NEXT_COMMAND; return; } else { DEBUG("ps clear ok\r\n"); } } static void psLoadAllBlocks(void) { pstorage_load(dest_data_0, &block_0_handle, 16, 0); pstorage_load(dest_data_1, &block_1_handle, 16, 0); pstorage_load(dest_data_2, &block_2_handle, 16, 0); dest_data_0[15]=0; dest_data_1[15]=0; dest_data_2[15]=0; DEBUG ("Zero: %s\r\n", dest_data_0); DEBUG ("One: %s\r\n", dest_data_1); DEBUG ("Two: %s\r\n", dest_data_2); } int main(void) { magnet=0; tickerState=MAGNET_OFF; // Not used so not enabled pcUart.attach(&rxInterrupt,Serial::RxIrq); //interrupt for incoming data available from PC connection //ticker.attach(periodicCallback, 0.1); DEBUG("Initialising the nRF51822\n\r"); ble.init(); psInit(); ble.onDisconnection(disconnectionCallback); // Define callback function for BLE disconnection event ble.onDataWritten(onDataWritten); // Define callback function for BLE Data received event /* setup advertising */ ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); // Indicate that Legacy Bluetooth in not supported ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)"B_MAGNET", sizeof("B_MAGNET") - 1); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(500)); // Set advertising interval to 1 second ble.startAdvertising(); // Start advertising UARTService uartService(ble); // Create BLE UART service uartServicePtr = &uartService; // Initalise pointer to point to UART Service while (true) { if ((psState==PS_WAITING_FOR_NEXT_COMMAND)&&(psNextState!=PS_WAITING_FOR_NEXT_COMMAND)){ switch(psNextState) { case PS_CLEAR_3_BLOCKS: psClear3Blocks(); break; case PS_STORE_ALL: psStoreAll(); break; case PS_CLEAR_2_BLOCKS: psClear2Blocks(); break; case PS_UPDATE_1_BLCK: psUpdate1Block(); break; default: DEBUG ("Unexpected next pstorage state"); } psNextState= PS_WAITING_FOR_NEXT_COMMAND; } ble.waitForEvent(); // Wait for BLE events } }