To get started with Seeed Tiny BLE, include detecting motion, button and battery level.
Dependencies: BLE_API eMPL_MPU6050 mbed nRF51822
nRF51822/nordic-sdk/components/drivers_nrf/ble_flash/ble_flash.c@1:fc2f9d636751, 2015-04-22 (annotated)
- Committer:
- yihui
- Date:
- Wed Apr 22 07:47:17 2015 +0000
- Revision:
- 1:fc2f9d636751
update libraries; ; delete nRF51822/nordic-sdk/components/gpiote/app_gpiote.c to solve GPIOTE_IRQHandler multiply defined issue. temperarily change nRF51822 library to folder
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yihui | 1:fc2f9d636751 | 1 | /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. |
yihui | 1:fc2f9d636751 | 2 | * |
yihui | 1:fc2f9d636751 | 3 | * The information contained herein is property of Nordic Semiconductor ASA. |
yihui | 1:fc2f9d636751 | 4 | * Terms and conditions of usage are described in detail in NORDIC |
yihui | 1:fc2f9d636751 | 5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. |
yihui | 1:fc2f9d636751 | 6 | * |
yihui | 1:fc2f9d636751 | 7 | * Licensees are granted free, non-transferable use of the information. NO |
yihui | 1:fc2f9d636751 | 8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from |
yihui | 1:fc2f9d636751 | 9 | * the file. |
yihui | 1:fc2f9d636751 | 10 | * |
yihui | 1:fc2f9d636751 | 11 | */ |
yihui | 1:fc2f9d636751 | 12 | |
yihui | 1:fc2f9d636751 | 13 | #include "ble_flash.h" |
yihui | 1:fc2f9d636751 | 14 | #include <stdlib.h> |
yihui | 1:fc2f9d636751 | 15 | #include <stdint.h> |
yihui | 1:fc2f9d636751 | 16 | #include <string.h> |
yihui | 1:fc2f9d636751 | 17 | #include "nrf_soc.h" |
yihui | 1:fc2f9d636751 | 18 | #include "nordic_common.h" |
yihui | 1:fc2f9d636751 | 19 | #include "nrf_error.h" |
yihui | 1:fc2f9d636751 | 20 | #include "nrf.h" |
yihui | 1:fc2f9d636751 | 21 | #include "nrf51_bitfields.h" |
yihui | 1:fc2f9d636751 | 22 | #include "app_util.h" |
yihui | 1:fc2f9d636751 | 23 | |
yihui | 1:fc2f9d636751 | 24 | |
yihui | 1:fc2f9d636751 | 25 | static volatile bool m_radio_active = false; /**< TRUE if radio is active (or about to become active), FALSE otherwise. */ |
yihui | 1:fc2f9d636751 | 26 | |
yihui | 1:fc2f9d636751 | 27 | |
yihui | 1:fc2f9d636751 | 28 | uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc) |
yihui | 1:fc2f9d636751 | 29 | { |
yihui | 1:fc2f9d636751 | 30 | uint16_t i; |
yihui | 1:fc2f9d636751 | 31 | uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc; |
yihui | 1:fc2f9d636751 | 32 | |
yihui | 1:fc2f9d636751 | 33 | for (i = 0; i < size; i++) |
yihui | 1:fc2f9d636751 | 34 | { |
yihui | 1:fc2f9d636751 | 35 | crc = (unsigned char)(crc >> 8) | (crc << 8); |
yihui | 1:fc2f9d636751 | 36 | crc ^= p_data[i]; |
yihui | 1:fc2f9d636751 | 37 | crc ^= (unsigned char)(crc & 0xff) >> 4; |
yihui | 1:fc2f9d636751 | 38 | crc ^= (crc << 8) << 4; |
yihui | 1:fc2f9d636751 | 39 | crc ^= ((crc & 0xff) << 4) << 1; |
yihui | 1:fc2f9d636751 | 40 | } |
yihui | 1:fc2f9d636751 | 41 | return crc; |
yihui | 1:fc2f9d636751 | 42 | } |
yihui | 1:fc2f9d636751 | 43 | |
yihui | 1:fc2f9d636751 | 44 | |
yihui | 1:fc2f9d636751 | 45 | /**@brief Function for erasing a page in flash. |
yihui | 1:fc2f9d636751 | 46 | * |
yihui | 1:fc2f9d636751 | 47 | * @param[in] p_page Pointer to first word in page to be erased. |
yihui | 1:fc2f9d636751 | 48 | */ |
yihui | 1:fc2f9d636751 | 49 | static void flash_page_erase(uint32_t * p_page) |
yihui | 1:fc2f9d636751 | 50 | { |
yihui | 1:fc2f9d636751 | 51 | // Turn on flash erase enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 52 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 53 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 54 | { |
yihui | 1:fc2f9d636751 | 55 | // Do nothing. |
yihui | 1:fc2f9d636751 | 56 | } |
yihui | 1:fc2f9d636751 | 57 | |
yihui | 1:fc2f9d636751 | 58 | // Erase page. |
yihui | 1:fc2f9d636751 | 59 | NRF_NVMC->ERASEPAGE = (uint32_t)p_page; |
yihui | 1:fc2f9d636751 | 60 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 61 | { |
yihui | 1:fc2f9d636751 | 62 | // Do nothing. |
yihui | 1:fc2f9d636751 | 63 | } |
yihui | 1:fc2f9d636751 | 64 | |
yihui | 1:fc2f9d636751 | 65 | // Turn off flash erase enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 66 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 67 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 68 | { |
yihui | 1:fc2f9d636751 | 69 | // Do nothing |
yihui | 1:fc2f9d636751 | 70 | } |
yihui | 1:fc2f9d636751 | 71 | } |
yihui | 1:fc2f9d636751 | 72 | |
yihui | 1:fc2f9d636751 | 73 | |
yihui | 1:fc2f9d636751 | 74 | /**@brief Function for writing one word to flash. Unprotected write, which can interfere with radio communication. |
yihui | 1:fc2f9d636751 | 75 | * |
yihui | 1:fc2f9d636751 | 76 | * @details This function DOES NOT use the m_radio_active variable, but will force the write even |
yihui | 1:fc2f9d636751 | 77 | * when the radio is active. To be used only from @ref ble_flash_page_write. |
yihui | 1:fc2f9d636751 | 78 | * |
yihui | 1:fc2f9d636751 | 79 | * @note Flash location to be written must have been erased previously. |
yihui | 1:fc2f9d636751 | 80 | * |
yihui | 1:fc2f9d636751 | 81 | * @param[in] p_address Pointer to flash location to be written. |
yihui | 1:fc2f9d636751 | 82 | * @param[in] value Value to write to flash. |
yihui | 1:fc2f9d636751 | 83 | */ |
yihui | 1:fc2f9d636751 | 84 | static void flash_word_unprotected_write(uint32_t * p_address, uint32_t value) |
yihui | 1:fc2f9d636751 | 85 | { |
yihui | 1:fc2f9d636751 | 86 | // Turn on flash write enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 87 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 88 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 89 | { |
yihui | 1:fc2f9d636751 | 90 | // Do nothing. |
yihui | 1:fc2f9d636751 | 91 | } |
yihui | 1:fc2f9d636751 | 92 | *p_address = value; |
yihui | 1:fc2f9d636751 | 93 | |
yihui | 1:fc2f9d636751 | 94 | // Wait flash write to finish |
yihui | 1:fc2f9d636751 | 95 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 96 | { |
yihui | 1:fc2f9d636751 | 97 | // Do nothing. |
yihui | 1:fc2f9d636751 | 98 | } |
yihui | 1:fc2f9d636751 | 99 | |
yihui | 1:fc2f9d636751 | 100 | // Turn off flash write enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 101 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 102 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 103 | { |
yihui | 1:fc2f9d636751 | 104 | // Do nothing. |
yihui | 1:fc2f9d636751 | 105 | } |
yihui | 1:fc2f9d636751 | 106 | } |
yihui | 1:fc2f9d636751 | 107 | |
yihui | 1:fc2f9d636751 | 108 | |
yihui | 1:fc2f9d636751 | 109 | /**@brief Function for writing one word to flash. |
yihui | 1:fc2f9d636751 | 110 | * |
yihui | 1:fc2f9d636751 | 111 | * @note Flash location to be written must have been erased previously. |
yihui | 1:fc2f9d636751 | 112 | * |
yihui | 1:fc2f9d636751 | 113 | * @param[in] p_address Pointer to flash location to be written. |
yihui | 1:fc2f9d636751 | 114 | * @param[in] value Value to write to flash. |
yihui | 1:fc2f9d636751 | 115 | */ |
yihui | 1:fc2f9d636751 | 116 | static void flash_word_write(uint32_t * p_address, uint32_t value) |
yihui | 1:fc2f9d636751 | 117 | { |
yihui | 1:fc2f9d636751 | 118 | // If radio is active, wait for it to become inactive. |
yihui | 1:fc2f9d636751 | 119 | while (m_radio_active) |
yihui | 1:fc2f9d636751 | 120 | { |
yihui | 1:fc2f9d636751 | 121 | // Do nothing (just wait for radio to become inactive). |
yihui | 1:fc2f9d636751 | 122 | (void) sd_app_evt_wait(); |
yihui | 1:fc2f9d636751 | 123 | } |
yihui | 1:fc2f9d636751 | 124 | |
yihui | 1:fc2f9d636751 | 125 | // Turn on flash write enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 126 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 127 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 128 | { |
yihui | 1:fc2f9d636751 | 129 | // Do nothing. |
yihui | 1:fc2f9d636751 | 130 | } |
yihui | 1:fc2f9d636751 | 131 | |
yihui | 1:fc2f9d636751 | 132 | *p_address = value; |
yihui | 1:fc2f9d636751 | 133 | // Wait flash write to finish |
yihui | 1:fc2f9d636751 | 134 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 135 | { |
yihui | 1:fc2f9d636751 | 136 | // Do nothing. |
yihui | 1:fc2f9d636751 | 137 | } |
yihui | 1:fc2f9d636751 | 138 | // Turn off flash write enable and wait until the NVMC is ready. |
yihui | 1:fc2f9d636751 | 139 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
yihui | 1:fc2f9d636751 | 140 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) |
yihui | 1:fc2f9d636751 | 141 | { |
yihui | 1:fc2f9d636751 | 142 | // Do nothing |
yihui | 1:fc2f9d636751 | 143 | } |
yihui | 1:fc2f9d636751 | 144 | } |
yihui | 1:fc2f9d636751 | 145 | |
yihui | 1:fc2f9d636751 | 146 | |
yihui | 1:fc2f9d636751 | 147 | uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value) |
yihui | 1:fc2f9d636751 | 148 | { |
yihui | 1:fc2f9d636751 | 149 | flash_word_write(p_address, value); |
yihui | 1:fc2f9d636751 | 150 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 151 | } |
yihui | 1:fc2f9d636751 | 152 | |
yihui | 1:fc2f9d636751 | 153 | |
yihui | 1:fc2f9d636751 | 154 | uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count) |
yihui | 1:fc2f9d636751 | 155 | { |
yihui | 1:fc2f9d636751 | 156 | uint16_t i; |
yihui | 1:fc2f9d636751 | 157 | |
yihui | 1:fc2f9d636751 | 158 | for (i = 0; i < word_count; i++) |
yihui | 1:fc2f9d636751 | 159 | { |
yihui | 1:fc2f9d636751 | 160 | flash_word_write(p_address, p_in_array[i]); |
yihui | 1:fc2f9d636751 | 161 | p_address++; |
yihui | 1:fc2f9d636751 | 162 | } |
yihui | 1:fc2f9d636751 | 163 | |
yihui | 1:fc2f9d636751 | 164 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 165 | } |
yihui | 1:fc2f9d636751 | 166 | |
yihui | 1:fc2f9d636751 | 167 | |
yihui | 1:fc2f9d636751 | 168 | uint32_t ble_flash_page_erase(uint8_t page_num) |
yihui | 1:fc2f9d636751 | 169 | { |
yihui | 1:fc2f9d636751 | 170 | uint32_t * p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); |
yihui | 1:fc2f9d636751 | 171 | flash_page_erase(p_page); |
yihui | 1:fc2f9d636751 | 172 | |
yihui | 1:fc2f9d636751 | 173 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 174 | } |
yihui | 1:fc2f9d636751 | 175 | |
yihui | 1:fc2f9d636751 | 176 | |
yihui | 1:fc2f9d636751 | 177 | uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count) |
yihui | 1:fc2f9d636751 | 178 | { |
yihui | 1:fc2f9d636751 | 179 | int i; |
yihui | 1:fc2f9d636751 | 180 | uint32_t * p_page; |
yihui | 1:fc2f9d636751 | 181 | uint32_t * p_curr_addr; |
yihui | 1:fc2f9d636751 | 182 | uint16_t in_data_crc; |
yihui | 1:fc2f9d636751 | 183 | uint16_t flash_crc; |
yihui | 1:fc2f9d636751 | 184 | uint32_t flash_header; |
yihui | 1:fc2f9d636751 | 185 | |
yihui | 1:fc2f9d636751 | 186 | p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); |
yihui | 1:fc2f9d636751 | 187 | p_curr_addr = p_page; |
yihui | 1:fc2f9d636751 | 188 | |
yihui | 1:fc2f9d636751 | 189 | // Calculate CRC of the data to write. |
yihui | 1:fc2f9d636751 | 190 | in_data_crc = ble_flash_crc16_compute((uint8_t *)p_in_array, |
yihui | 1:fc2f9d636751 | 191 | word_count * sizeof(uint32_t), |
yihui | 1:fc2f9d636751 | 192 | NULL); |
yihui | 1:fc2f9d636751 | 193 | |
yihui | 1:fc2f9d636751 | 194 | // Compare the calculated to the one in flash. |
yihui | 1:fc2f9d636751 | 195 | flash_header = *p_curr_addr; |
yihui | 1:fc2f9d636751 | 196 | flash_crc = (uint16_t)flash_header; |
yihui | 1:fc2f9d636751 | 197 | |
yihui | 1:fc2f9d636751 | 198 | if (flash_crc == in_data_crc) |
yihui | 1:fc2f9d636751 | 199 | { |
yihui | 1:fc2f9d636751 | 200 | // Data is the same as the data already stored in flash, return without modifying flash. |
yihui | 1:fc2f9d636751 | 201 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 202 | } |
yihui | 1:fc2f9d636751 | 203 | |
yihui | 1:fc2f9d636751 | 204 | // Erase flash page |
yihui | 1:fc2f9d636751 | 205 | flash_page_erase(p_page); |
yihui | 1:fc2f9d636751 | 206 | |
yihui | 1:fc2f9d636751 | 207 | // Reserve space for magic number (for detecting if flash content is valid). |
yihui | 1:fc2f9d636751 | 208 | p_curr_addr++; |
yihui | 1:fc2f9d636751 | 209 | |
yihui | 1:fc2f9d636751 | 210 | // Reserve space for saving word_count. |
yihui | 1:fc2f9d636751 | 211 | p_curr_addr++; |
yihui | 1:fc2f9d636751 | 212 | |
yihui | 1:fc2f9d636751 | 213 | // Write data |
yihui | 1:fc2f9d636751 | 214 | for (i = 0; i < word_count; i++) |
yihui | 1:fc2f9d636751 | 215 | { |
yihui | 1:fc2f9d636751 | 216 | flash_word_unprotected_write(p_curr_addr, p_in_array[i]); |
yihui | 1:fc2f9d636751 | 217 | p_curr_addr++; |
yihui | 1:fc2f9d636751 | 218 | } |
yihui | 1:fc2f9d636751 | 219 | |
yihui | 1:fc2f9d636751 | 220 | // Write number of elements. |
yihui | 1:fc2f9d636751 | 221 | flash_word_write(p_page + 1, (uint32_t)(word_count)); |
yihui | 1:fc2f9d636751 | 222 | |
yihui | 1:fc2f9d636751 | 223 | // Write magic number and CRC to indicate that flash content is valid. |
yihui | 1:fc2f9d636751 | 224 | flash_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)in_data_crc; |
yihui | 1:fc2f9d636751 | 225 | flash_word_write(p_page, flash_header); |
yihui | 1:fc2f9d636751 | 226 | |
yihui | 1:fc2f9d636751 | 227 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 228 | } |
yihui | 1:fc2f9d636751 | 229 | |
yihui | 1:fc2f9d636751 | 230 | |
yihui | 1:fc2f9d636751 | 231 | uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count) |
yihui | 1:fc2f9d636751 | 232 | { |
yihui | 1:fc2f9d636751 | 233 | int byte_count; |
yihui | 1:fc2f9d636751 | 234 | uint32_t * p_page; |
yihui | 1:fc2f9d636751 | 235 | uint32_t * p_curr_addr; |
yihui | 1:fc2f9d636751 | 236 | uint32_t flash_header; |
yihui | 1:fc2f9d636751 | 237 | uint32_t calc_header; |
yihui | 1:fc2f9d636751 | 238 | uint16_t calc_crc; |
yihui | 1:fc2f9d636751 | 239 | uint32_t tmp; |
yihui | 1:fc2f9d636751 | 240 | |
yihui | 1:fc2f9d636751 | 241 | p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); |
yihui | 1:fc2f9d636751 | 242 | p_curr_addr = p_page; |
yihui | 1:fc2f9d636751 | 243 | |
yihui | 1:fc2f9d636751 | 244 | // Check if block is valid |
yihui | 1:fc2f9d636751 | 245 | flash_header = *p_curr_addr; |
yihui | 1:fc2f9d636751 | 246 | tmp = flash_header & 0xFFFF0000; |
yihui | 1:fc2f9d636751 | 247 | if (tmp != BLE_FLASH_MAGIC_NUMBER) |
yihui | 1:fc2f9d636751 | 248 | { |
yihui | 1:fc2f9d636751 | 249 | *p_word_count = 0; |
yihui | 1:fc2f9d636751 | 250 | return NRF_ERROR_NOT_FOUND; |
yihui | 1:fc2f9d636751 | 251 | } |
yihui | 1:fc2f9d636751 | 252 | p_curr_addr++; |
yihui | 1:fc2f9d636751 | 253 | |
yihui | 1:fc2f9d636751 | 254 | // Read number of elements |
yihui | 1:fc2f9d636751 | 255 | *p_word_count = (uint8_t)(*(p_curr_addr)); |
yihui | 1:fc2f9d636751 | 256 | p_curr_addr++; |
yihui | 1:fc2f9d636751 | 257 | |
yihui | 1:fc2f9d636751 | 258 | // Read data |
yihui | 1:fc2f9d636751 | 259 | byte_count = (*p_word_count) * sizeof(uint32_t); |
yihui | 1:fc2f9d636751 | 260 | memcpy(p_out_array, p_curr_addr, byte_count); |
yihui | 1:fc2f9d636751 | 261 | |
yihui | 1:fc2f9d636751 | 262 | // Check CRC |
yihui | 1:fc2f9d636751 | 263 | calc_crc = ble_flash_crc16_compute((uint8_t *)p_out_array, |
yihui | 1:fc2f9d636751 | 264 | (*p_word_count) * sizeof(uint32_t), |
yihui | 1:fc2f9d636751 | 265 | NULL); |
yihui | 1:fc2f9d636751 | 266 | calc_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)calc_crc; |
yihui | 1:fc2f9d636751 | 267 | |
yihui | 1:fc2f9d636751 | 268 | if (calc_header != flash_header) |
yihui | 1:fc2f9d636751 | 269 | { |
yihui | 1:fc2f9d636751 | 270 | return NRF_ERROR_NOT_FOUND; |
yihui | 1:fc2f9d636751 | 271 | } |
yihui | 1:fc2f9d636751 | 272 | |
yihui | 1:fc2f9d636751 | 273 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 274 | } |
yihui | 1:fc2f9d636751 | 275 | |
yihui | 1:fc2f9d636751 | 276 | |
yihui | 1:fc2f9d636751 | 277 | uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr) |
yihui | 1:fc2f9d636751 | 278 | { |
yihui | 1:fc2f9d636751 | 279 | *pp_page_addr = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); |
yihui | 1:fc2f9d636751 | 280 | return NRF_SUCCESS; |
yihui | 1:fc2f9d636751 | 281 | } |
yihui | 1:fc2f9d636751 | 282 | |
yihui | 1:fc2f9d636751 | 283 | |
yihui | 1:fc2f9d636751 | 284 | void ble_flash_on_radio_active_evt(bool radio_active) |
yihui | 1:fc2f9d636751 | 285 | { |
yihui | 1:fc2f9d636751 | 286 | m_radio_active = radio_active; |
yihui | 1:fc2f9d636751 | 287 | } |