helpfor studient
Dependents: STM32_F103-C8T6basecanblink_led
Fork of mbed-dev by
targets/TARGET_NORDIC/TARGET_NRF5/flash_api.c@186:9c2029bfadbe, 2018-04-20 (annotated)
- Committer:
- Anna Bridge
- Date:
- Fri Apr 20 11:31:35 2018 +0100
- Revision:
- 186:9c2029bfadbe
- Parent:
- 183:a56a73fd2a6f
Update to latest version of mbed lib
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 166:c97ed07ec1a8 | 1 | /* |
AnnaBridge | 166:c97ed07ec1a8 | 2 | * Copyright (c) 2017 Nordic Semiconductor ASA |
AnnaBridge | 166:c97ed07ec1a8 | 3 | * All rights reserved. |
AnnaBridge | 166:c97ed07ec1a8 | 4 | * |
AnnaBridge | 166:c97ed07ec1a8 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
AnnaBridge | 166:c97ed07ec1a8 | 6 | * are permitted provided that the following conditions are met: |
AnnaBridge | 166:c97ed07ec1a8 | 7 | * |
AnnaBridge | 166:c97ed07ec1a8 | 8 | * 1. Redistributions of source code must retain the above copyright notice, this list |
AnnaBridge | 166:c97ed07ec1a8 | 9 | * of conditions and the following disclaimer. |
AnnaBridge | 166:c97ed07ec1a8 | 10 | * |
AnnaBridge | 166:c97ed07ec1a8 | 11 | * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA |
AnnaBridge | 166:c97ed07ec1a8 | 12 | * integrated circuit in a product or a software update for such product, must reproduce |
AnnaBridge | 166:c97ed07ec1a8 | 13 | * the above copyright notice, this list of conditions and the following disclaimer in |
AnnaBridge | 166:c97ed07ec1a8 | 14 | * the documentation and/or other materials provided with the distribution. |
AnnaBridge | 166:c97ed07ec1a8 | 15 | * |
AnnaBridge | 166:c97ed07ec1a8 | 16 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be |
AnnaBridge | 166:c97ed07ec1a8 | 17 | * used to endorse or promote products derived from this software without specific prior |
AnnaBridge | 166:c97ed07ec1a8 | 18 | * written permission. |
AnnaBridge | 166:c97ed07ec1a8 | 19 | * |
AnnaBridge | 166:c97ed07ec1a8 | 20 | * 4. This software, with or without modification, must only be used with a |
AnnaBridge | 166:c97ed07ec1a8 | 21 | * Nordic Semiconductor ASA integrated circuit. |
AnnaBridge | 166:c97ed07ec1a8 | 22 | * |
AnnaBridge | 166:c97ed07ec1a8 | 23 | * 5. Any software provided in binary or object form under this license must not be reverse |
AnnaBridge | 166:c97ed07ec1a8 | 24 | * engineered, decompiled, modified and/or disassembled. |
AnnaBridge | 166:c97ed07ec1a8 | 25 | * |
AnnaBridge | 166:c97ed07ec1a8 | 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
AnnaBridge | 166:c97ed07ec1a8 | 27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
AnnaBridge | 166:c97ed07ec1a8 | 28 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
AnnaBridge | 166:c97ed07ec1a8 | 29 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
AnnaBridge | 166:c97ed07ec1a8 | 30 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
AnnaBridge | 166:c97ed07ec1a8 | 31 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
AnnaBridge | 166:c97ed07ec1a8 | 32 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
AnnaBridge | 166:c97ed07ec1a8 | 33 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
AnnaBridge | 166:c97ed07ec1a8 | 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
AnnaBridge | 166:c97ed07ec1a8 | 35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
AnnaBridge | 166:c97ed07ec1a8 | 36 | * |
AnnaBridge | 166:c97ed07ec1a8 | 37 | */ |
AnnaBridge | 166:c97ed07ec1a8 | 38 | |
AnnaBridge | 183:a56a73fd2a6f | 39 | #if DEVICE_FLASH |
AnnaBridge | 183:a56a73fd2a6f | 40 | |
AnnaBridge | 183:a56a73fd2a6f | 41 | #include "hal/flash_api.h" |
AnnaBridge | 183:a56a73fd2a6f | 42 | #include "hal/lp_ticker_api.h" |
AnnaBridge | 183:a56a73fd2a6f | 43 | |
AnnaBridge | 183:a56a73fd2a6f | 44 | #include "nrf_drv_common.h" |
AnnaBridge | 166:c97ed07ec1a8 | 45 | #include "nrf_nvmc.h" |
AnnaBridge | 166:c97ed07ec1a8 | 46 | #include "nrf_soc.h" |
AnnaBridge | 183:a56a73fd2a6f | 47 | |
AnnaBridge | 183:a56a73fd2a6f | 48 | #define WORD_WRITE_TIMEOUT_US (1 * 1000) // Max. value from datasheet: 338 us |
AnnaBridge | 183:a56a73fd2a6f | 49 | #define PAGE_ERASE_TIMEOUT_US (200 * 1000) // Max. value from datasheet: 89.7 ms |
AnnaBridge | 166:c97ed07ec1a8 | 50 | |
AnnaBridge | 183:a56a73fd2a6f | 51 | /* Macro for testing if the SoftDevice is active, regardless of whether the |
AnnaBridge | 183:a56a73fd2a6f | 52 | * application is build with the SoftDevice or not. |
AnnaBridge | 183:a56a73fd2a6f | 53 | */ |
AnnaBridge | 183:a56a73fd2a6f | 54 | #if defined(SOFTDEVICE_PRESENT) |
AnnaBridge | 183:a56a73fd2a6f | 55 | #include "nrf_sdm.h" |
AnnaBridge | 183:a56a73fd2a6f | 56 | static uint8_t wrapper(void) { |
AnnaBridge | 183:a56a73fd2a6f | 57 | uint8_t softdevice_is_enabled; |
AnnaBridge | 183:a56a73fd2a6f | 58 | ret_code_t result = sd_softdevice_is_enabled(&softdevice_is_enabled); |
AnnaBridge | 183:a56a73fd2a6f | 59 | return ((result == NRF_SUCCESS) && (softdevice_is_enabled == 1)); |
AnnaBridge | 183:a56a73fd2a6f | 60 | } |
AnnaBridge | 183:a56a73fd2a6f | 61 | #define NRF_HAL_SD_IS_ENABLED() wrapper() |
AnnaBridge | 183:a56a73fd2a6f | 62 | #else |
AnnaBridge | 183:a56a73fd2a6f | 63 | #define NRF_HAL_SD_IS_ENABLED() 0 |
AnnaBridge | 183:a56a73fd2a6f | 64 | #endif |
AnnaBridge | 166:c97ed07ec1a8 | 65 | |
AnnaBridge | 166:c97ed07ec1a8 | 66 | int32_t flash_init(flash_t *obj) |
AnnaBridge | 166:c97ed07ec1a8 | 67 | { |
AnnaBridge | 166:c97ed07ec1a8 | 68 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 69 | |
AnnaBridge | 183:a56a73fd2a6f | 70 | /* Initialize low power ticker. Used for timeouts. */ |
AnnaBridge | 183:a56a73fd2a6f | 71 | static bool first_init = true; |
AnnaBridge | 183:a56a73fd2a6f | 72 | |
AnnaBridge | 183:a56a73fd2a6f | 73 | if (first_init) { |
AnnaBridge | 183:a56a73fd2a6f | 74 | first_init = false; |
AnnaBridge | 183:a56a73fd2a6f | 75 | lp_ticker_init(); |
AnnaBridge | 166:c97ed07ec1a8 | 76 | } |
AnnaBridge | 183:a56a73fd2a6f | 77 | |
AnnaBridge | 166:c97ed07ec1a8 | 78 | return 0; |
AnnaBridge | 166:c97ed07ec1a8 | 79 | } |
AnnaBridge | 166:c97ed07ec1a8 | 80 | |
AnnaBridge | 166:c97ed07ec1a8 | 81 | int32_t flash_free(flash_t *obj) |
AnnaBridge | 166:c97ed07ec1a8 | 82 | { |
AnnaBridge | 166:c97ed07ec1a8 | 83 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 84 | |
AnnaBridge | 166:c97ed07ec1a8 | 85 | return 0; |
AnnaBridge | 166:c97ed07ec1a8 | 86 | } |
AnnaBridge | 166:c97ed07ec1a8 | 87 | |
AnnaBridge | 166:c97ed07ec1a8 | 88 | int32_t flash_erase_sector(flash_t *obj, uint32_t address) |
AnnaBridge | 166:c97ed07ec1a8 | 89 | { |
AnnaBridge | 166:c97ed07ec1a8 | 90 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 91 | |
AnnaBridge | 183:a56a73fd2a6f | 92 | /* Return value defaults to error. */ |
AnnaBridge | 183:a56a73fd2a6f | 93 | uint32_t result = NRF_ERROR_BUSY; |
AnnaBridge | 183:a56a73fd2a6f | 94 | |
AnnaBridge | 183:a56a73fd2a6f | 95 | if (NRF_HAL_SD_IS_ENABLED()) { |
AnnaBridge | 183:a56a73fd2a6f | 96 | |
AnnaBridge | 183:a56a73fd2a6f | 97 | /* Convert address to page number. */ |
AnnaBridge | 183:a56a73fd2a6f | 98 | uint32_t page_number = address / NRF_FICR->CODEPAGESIZE; |
AnnaBridge | 183:a56a73fd2a6f | 99 | |
AnnaBridge | 183:a56a73fd2a6f | 100 | /* Setup stop watch for timeout. */ |
AnnaBridge | 183:a56a73fd2a6f | 101 | uint32_t start_us = lp_ticker_read(); |
AnnaBridge | 183:a56a73fd2a6f | 102 | uint32_t now_us = start_us; |
AnnaBridge | 183:a56a73fd2a6f | 103 | |
AnnaBridge | 183:a56a73fd2a6f | 104 | /* Retry if flash is busy until timeout is reached. */ |
AnnaBridge | 183:a56a73fd2a6f | 105 | while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && |
AnnaBridge | 183:a56a73fd2a6f | 106 | (result == NRF_ERROR_BUSY)) { |
AnnaBridge | 183:a56a73fd2a6f | 107 | |
AnnaBridge | 183:a56a73fd2a6f | 108 | result = sd_flash_page_erase(page_number); |
AnnaBridge | 183:a56a73fd2a6f | 109 | |
AnnaBridge | 183:a56a73fd2a6f | 110 | /* Read timeout timer. */ |
AnnaBridge | 183:a56a73fd2a6f | 111 | now_us = lp_ticker_read(); |
AnnaBridge | 183:a56a73fd2a6f | 112 | } |
AnnaBridge | 183:a56a73fd2a6f | 113 | |
AnnaBridge | 183:a56a73fd2a6f | 114 | } else { |
AnnaBridge | 183:a56a73fd2a6f | 115 | |
AnnaBridge | 183:a56a73fd2a6f | 116 | /* Raw API doesn't return error code, assume success. */ |
AnnaBridge | 183:a56a73fd2a6f | 117 | nrf_nvmc_page_erase(address); |
AnnaBridge | 183:a56a73fd2a6f | 118 | result = NRF_SUCCESS; |
AnnaBridge | 166:c97ed07ec1a8 | 119 | } |
AnnaBridge | 183:a56a73fd2a6f | 120 | |
AnnaBridge | 183:a56a73fd2a6f | 121 | /* Convert Nordic error code to mbed HAL error code. */ |
AnnaBridge | 183:a56a73fd2a6f | 122 | return (result == NRF_SUCCESS) ? 0 : -1; |
AnnaBridge | 166:c97ed07ec1a8 | 123 | } |
AnnaBridge | 166:c97ed07ec1a8 | 124 | |
AnnaBridge | 166:c97ed07ec1a8 | 125 | int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) |
AnnaBridge | 166:c97ed07ec1a8 | 126 | { |
AnnaBridge | 183:a56a73fd2a6f | 127 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 128 | |
AnnaBridge | 183:a56a73fd2a6f | 129 | /* Return value defaults to error. */ |
AnnaBridge | 183:a56a73fd2a6f | 130 | uint32_t result = NRF_ERROR_BUSY; |
AnnaBridge | 183:a56a73fd2a6f | 131 | |
AnnaBridge | 183:a56a73fd2a6f | 132 | /* Convert size to words. */ |
AnnaBridge | 183:a56a73fd2a6f | 133 | uint32_t words = size / sizeof(uint32_t); |
AnnaBridge | 183:a56a73fd2a6f | 134 | |
AnnaBridge | 183:a56a73fd2a6f | 135 | if (NRF_HAL_SD_IS_ENABLED()) { |
AnnaBridge | 183:a56a73fd2a6f | 136 | |
AnnaBridge | 183:a56a73fd2a6f | 137 | /* Setup stop watch for timeout. */ |
AnnaBridge | 183:a56a73fd2a6f | 138 | uint32_t start_us = lp_ticker_read(); |
AnnaBridge | 183:a56a73fd2a6f | 139 | uint32_t now_us = start_us; |
AnnaBridge | 183:a56a73fd2a6f | 140 | |
AnnaBridge | 183:a56a73fd2a6f | 141 | /* Retry if flash is busy until timeout is reached. */ |
AnnaBridge | 183:a56a73fd2a6f | 142 | while (((now_us - start_us) < (words * WORD_WRITE_TIMEOUT_US)) && |
AnnaBridge | 183:a56a73fd2a6f | 143 | (result == NRF_ERROR_BUSY)) { |
AnnaBridge | 183:a56a73fd2a6f | 144 | |
AnnaBridge | 183:a56a73fd2a6f | 145 | result = sd_flash_write((uint32_t *) address, (const uint32_t *) data, words); |
AnnaBridge | 183:a56a73fd2a6f | 146 | |
AnnaBridge | 183:a56a73fd2a6f | 147 | /* Read timeout timer. */ |
AnnaBridge | 183:a56a73fd2a6f | 148 | now_us = lp_ticker_read(); |
AnnaBridge | 183:a56a73fd2a6f | 149 | } |
AnnaBridge | 183:a56a73fd2a6f | 150 | |
AnnaBridge | 183:a56a73fd2a6f | 151 | } else { |
AnnaBridge | 183:a56a73fd2a6f | 152 | /* We will use *_words function to speed up flashing code. Word means 32bit -> 4B |
AnnaBridge | 183:a56a73fd2a6f | 153 | * or sizeof(uint32_t). |
AnnaBridge | 183:a56a73fd2a6f | 154 | */ |
AnnaBridge | 183:a56a73fd2a6f | 155 | nrf_nvmc_write_words(address, (const uint32_t *) data, words); |
AnnaBridge | 183:a56a73fd2a6f | 156 | result = NRF_SUCCESS; |
AnnaBridge | 166:c97ed07ec1a8 | 157 | } |
AnnaBridge | 183:a56a73fd2a6f | 158 | |
AnnaBridge | 183:a56a73fd2a6f | 159 | /* Convert Nordic error code to mbed HAL error code. */ |
AnnaBridge | 183:a56a73fd2a6f | 160 | return (result == NRF_SUCCESS) ? 0 : -1; |
AnnaBridge | 166:c97ed07ec1a8 | 161 | } |
AnnaBridge | 166:c97ed07ec1a8 | 162 | |
AnnaBridge | 166:c97ed07ec1a8 | 163 | uint32_t flash_get_size(const flash_t *obj) |
AnnaBridge | 166:c97ed07ec1a8 | 164 | { |
AnnaBridge | 166:c97ed07ec1a8 | 165 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 166 | |
AnnaBridge | 166:c97ed07ec1a8 | 167 | /* Just count flash size. */ |
AnnaBridge | 166:c97ed07ec1a8 | 168 | return NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE; |
AnnaBridge | 166:c97ed07ec1a8 | 169 | } |
AnnaBridge | 166:c97ed07ec1a8 | 170 | |
AnnaBridge | 166:c97ed07ec1a8 | 171 | uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) |
AnnaBridge | 166:c97ed07ec1a8 | 172 | { |
AnnaBridge | 166:c97ed07ec1a8 | 173 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 174 | |
AnnaBridge | 166:c97ed07ec1a8 | 175 | /* Test if passed address is in flash space. */ |
AnnaBridge | 166:c97ed07ec1a8 | 176 | if (address < flash_get_size(obj)) { |
AnnaBridge | 166:c97ed07ec1a8 | 177 | return NRF_FICR->CODEPAGESIZE; |
AnnaBridge | 166:c97ed07ec1a8 | 178 | } |
AnnaBridge | 183:a56a73fd2a6f | 179 | |
AnnaBridge | 166:c97ed07ec1a8 | 180 | /* Something goes wrong, return invalid size error code. */ |
AnnaBridge | 166:c97ed07ec1a8 | 181 | return MBED_FLASH_INVALID_SIZE; |
AnnaBridge | 166:c97ed07ec1a8 | 182 | } |
AnnaBridge | 166:c97ed07ec1a8 | 183 | |
AnnaBridge | 166:c97ed07ec1a8 | 184 | uint32_t flash_get_page_size(const flash_t *obj) |
AnnaBridge | 166:c97ed07ec1a8 | 185 | { |
AnnaBridge | 166:c97ed07ec1a8 | 186 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 187 | |
AnnaBridge | 183:a56a73fd2a6f | 188 | /* Return minimum writeable size. Note that this is different from the erase page size. */ |
AnnaBridge | 183:a56a73fd2a6f | 189 | return 4; |
AnnaBridge | 166:c97ed07ec1a8 | 190 | } |
AnnaBridge | 166:c97ed07ec1a8 | 191 | |
AnnaBridge | 166:c97ed07ec1a8 | 192 | uint32_t flash_get_start_address(const flash_t *obj) |
AnnaBridge | 166:c97ed07ec1a8 | 193 | { |
AnnaBridge | 183:a56a73fd2a6f | 194 | (void)(obj); |
AnnaBridge | 183:a56a73fd2a6f | 195 | |
AnnaBridge | 166:c97ed07ec1a8 | 196 | return 0; |
AnnaBridge | 166:c97ed07ec1a8 | 197 | } |
AnnaBridge | 166:c97ed07ec1a8 | 198 | |
AnnaBridge | 166:c97ed07ec1a8 | 199 | #endif |
AnnaBridge | 166:c97ed07ec1a8 | 200 | |
AnnaBridge | 166:c97ed07ec1a8 | 201 | /** @}*/ |