ver:init
source/bluenrg-hci/hci/controller/bluenrg_utils.c@0:88b85febcb45, 2017-06-18 (annotated)
- Committer:
- iv123
- Date:
- Sun Jun 18 16:10:28 2017 +0000
- Revision:
- 0:88b85febcb45
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
iv123 | 0:88b85febcb45 | 1 | |
iv123 | 0:88b85febcb45 | 2 | #include "ble_hal.h" |
iv123 | 0:88b85febcb45 | 3 | #include "ble_hal_types.h" |
iv123 | 0:88b85febcb45 | 4 | #include "ble_status.h" |
iv123 | 0:88b85febcb45 | 5 | #include "bluenrg_aci.h" |
iv123 | 0:88b85febcb45 | 6 | #include "bluenrg_utils.h" |
iv123 | 0:88b85febcb45 | 7 | #include "ble_hci.h" |
iv123 | 0:88b85febcb45 | 8 | #include "ble_osal.h" |
iv123 | 0:88b85febcb45 | 9 | #include "string.h" |
iv123 | 0:88b85febcb45 | 10 | #include "stm32_bluenrg_ble.h" |
iv123 | 0:88b85febcb45 | 11 | |
iv123 | 0:88b85febcb45 | 12 | #define SUPPORTED_BOOTLOADER_VERSION_MIN 3 |
iv123 | 0:88b85febcb45 | 13 | #define SUPPORTED_BOOTLOADER_VERSION_MAX 5 |
iv123 | 0:88b85febcb45 | 14 | |
iv123 | 0:88b85febcb45 | 15 | #define BASE_ADDRESS 0x10010000 |
iv123 | 0:88b85febcb45 | 16 | |
iv123 | 0:88b85febcb45 | 17 | #define FW_OFFSET (2*1024) // 2 KB |
iv123 | 0:88b85febcb45 | 18 | #define FW_OFFSET_MS 0 |
iv123 | 0:88b85febcb45 | 19 | #define FULL_STACK_SIZE (66*1024) // 66 KB |
iv123 | 0:88b85febcb45 | 20 | #define BOOTLOADER_SIZE (2*1024) // 2 kB |
iv123 | 0:88b85febcb45 | 21 | #define SECTOR_SIZE (2*1024) // 2 KB |
iv123 | 0:88b85febcb45 | 22 | #define DATA_SIZE 64 // 64 bytes |
iv123 | 0:88b85febcb45 | 23 | |
iv123 | 0:88b85febcb45 | 24 | // x**32 + x**26 + x**23 + x ** 22 + x**16 + x**12 + x**11 + |
iv123 | 0:88b85febcb45 | 25 | // x**10 + x**8 + x**7 + x**5 + x**4 + x**2 + x**1 + x**0 |
iv123 | 0:88b85febcb45 | 26 | #define CRC_POLY 0x04C11DB7 // the poly without the x**32 |
iv123 | 0:88b85febcb45 | 27 | |
iv123 | 0:88b85febcb45 | 28 | #define BOOTLOADER_CRC_NOT_PATCHED 0x878FB3FC |
iv123 | 0:88b85febcb45 | 29 | |
iv123 | 0:88b85febcb45 | 30 | #define IFR_SIZE 192 |
iv123 | 0:88b85febcb45 | 31 | #define IFR_BASE_ADDRESS 0x10020000 |
iv123 | 0:88b85febcb45 | 32 | #define IFR_CONFIG_DATA_OFFSET (SECTOR_SIZE-IFR_SIZE) // Offset in IFR sector containing configuration data |
iv123 | 0:88b85febcb45 | 33 | |
iv123 | 0:88b85febcb45 | 34 | #if BLUENRG_MS |
iv123 | 0:88b85febcb45 | 35 | #define IFR_WRITE_OFFSET_BEGIN IFR_CONFIG_DATA_OFFSET |
iv123 | 0:88b85febcb45 | 36 | #else |
iv123 | 0:88b85febcb45 | 37 | #define IFR_WRITE_OFFSET_BEGIN 0 |
iv123 | 0:88b85febcb45 | 38 | #endif |
iv123 | 0:88b85febcb45 | 39 | |
iv123 | 0:88b85febcb45 | 40 | |
iv123 | 0:88b85febcb45 | 41 | #define BLUE_FLAG_OFFSET 0x8C0 |
iv123 | 0:88b85febcb45 | 42 | #define MAX_ERASE_RETRIES 2 |
iv123 | 0:88b85febcb45 | 43 | #define MAX_WRITE_RETRIES 2 |
iv123 | 0:88b85febcb45 | 44 | #define MIN_WRITE_BLOCK_SIZE 4 |
iv123 | 0:88b85febcb45 | 45 | |
iv123 | 0:88b85febcb45 | 46 | #define RETRY_COMMAND(func, num_ret, error) \ |
iv123 | 0:88b85febcb45 | 47 | { \ |
iv123 | 0:88b85febcb45 | 48 | uint8_t num_retries; \ |
iv123 | 0:88b85febcb45 | 49 | num_retries = 0; \ |
iv123 | 0:88b85febcb45 | 50 | error = 0; \ |
iv123 | 0:88b85febcb45 | 51 | while (num_retries++ < num_ret) { \ |
iv123 | 0:88b85febcb45 | 52 | if (func == BLE_STATUS_SUCCESS) \ |
iv123 | 0:88b85febcb45 | 53 | break; \ |
iv123 | 0:88b85febcb45 | 54 | if (num_retries == num_ret) \ |
iv123 | 0:88b85febcb45 | 55 | error = BLE_UTIL_ACI_ERROR; \ |
iv123 | 0:88b85febcb45 | 56 | } \ |
iv123 | 0:88b85febcb45 | 57 | } |
iv123 | 0:88b85febcb45 | 58 | |
iv123 | 0:88b85febcb45 | 59 | typedef struct{ |
iv123 | 0:88b85febcb45 | 60 | uint8_t cold_ana_act_config_table[64]; |
iv123 | 0:88b85febcb45 | 61 | }cold_table_TypeDef; |
iv123 | 0:88b85febcb45 | 62 | |
iv123 | 0:88b85febcb45 | 63 | /* This function calculates the CRC of a sector of flash, if bytes passed are less than sector size, |
iv123 | 0:88b85febcb45 | 64 | they are extended with 0xFF until sector size is reached |
iv123 | 0:88b85febcb45 | 65 | */ |
iv123 | 0:88b85febcb45 | 66 | static uint32_t updater_calc_crc(const uint8_t* data, uint16_t nr_of_bytes) |
iv123 | 0:88b85febcb45 | 67 | { |
iv123 | 0:88b85febcb45 | 68 | uint32_t i, j, a1; |
iv123 | 0:88b85febcb45 | 69 | uint32_t crc, value; |
iv123 | 0:88b85febcb45 | 70 | |
iv123 | 0:88b85febcb45 | 71 | crc = 0; |
iv123 | 0:88b85febcb45 | 72 | for (i = 0; i < SECTOR_SIZE; i += 4) { |
iv123 | 0:88b85febcb45 | 73 | uint8_t *dataw = (uint8_t *) &value; |
iv123 | 0:88b85febcb45 | 74 | |
iv123 | 0:88b85febcb45 | 75 | dataw[0] = (i < nr_of_bytes) ? data[i] : 0xFF; |
iv123 | 0:88b85febcb45 | 76 | dataw[1] = ((i + 1) < nr_of_bytes) ? data[i+1] : 0xFF; |
iv123 | 0:88b85febcb45 | 77 | dataw[2] = ((i + 2) < nr_of_bytes) ? data[i+2] : 0xFF; |
iv123 | 0:88b85febcb45 | 78 | dataw[3] = ((i + 3) < nr_of_bytes) ? data[i+3] : 0xFF; |
iv123 | 0:88b85febcb45 | 79 | |
iv123 | 0:88b85febcb45 | 80 | crc = crc ^ value; |
iv123 | 0:88b85febcb45 | 81 | for (j = 0; j < 32; j ++) { |
iv123 | 0:88b85febcb45 | 82 | a1 = (crc >> 31) & 0x1; |
iv123 | 0:88b85febcb45 | 83 | crc = (crc << 1) ^ (a1 * CRC_POLY); |
iv123 | 0:88b85febcb45 | 84 | } |
iv123 | 0:88b85febcb45 | 85 | } |
iv123 | 0:88b85febcb45 | 86 | |
iv123 | 0:88b85febcb45 | 87 | return crc; |
iv123 | 0:88b85febcb45 | 88 | } |
iv123 | 0:88b85febcb45 | 89 | |
iv123 | 0:88b85febcb45 | 90 | int program_device(const uint8_t *fw_image, uint32_t fw_size) |
iv123 | 0:88b85febcb45 | 91 | { |
iv123 | 0:88b85febcb45 | 92 | uint8_t version, num_erase_retries=0, status, data_size; |
iv123 | 0:88b85febcb45 | 93 | uint8_t number_sectors, module; |
iv123 | 0:88b85febcb45 | 94 | uint32_t address, j; |
iv123 | 0:88b85febcb45 | 95 | uint32_t crc, crc2, crc_size; |
iv123 | 0:88b85febcb45 | 96 | uint32_t fw_offset = FW_OFFSET; |
iv123 | 0:88b85febcb45 | 97 | |
iv123 | 0:88b85febcb45 | 98 | BlueNRG_HW_Bootloader(); |
iv123 | 0:88b85febcb45 | 99 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 100 | |
iv123 | 0:88b85febcb45 | 101 | if(aci_get_updater_version(&version)) |
iv123 | 0:88b85febcb45 | 102 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 103 | |
iv123 | 0:88b85febcb45 | 104 | if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX) |
iv123 | 0:88b85febcb45 | 105 | return BLE_UTIL_UNSUPPORTED_VERSION; |
iv123 | 0:88b85febcb45 | 106 | |
iv123 | 0:88b85febcb45 | 107 | if(aci_updater_hw_version(&version)) |
iv123 | 0:88b85febcb45 | 108 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 109 | |
iv123 | 0:88b85febcb45 | 110 | if(version==0x31){ |
iv123 | 0:88b85febcb45 | 111 | // It does not contain bootloader inside first sector. It may contain code. |
iv123 | 0:88b85febcb45 | 112 | fw_offset = FW_OFFSET_MS; |
iv123 | 0:88b85febcb45 | 113 | } |
iv123 | 0:88b85febcb45 | 114 | |
iv123 | 0:88b85febcb45 | 115 | if (fw_size != FULL_STACK_SIZE) |
iv123 | 0:88b85febcb45 | 116 | return BLE_UTIL_WRONG_IMAGE_SIZE; |
iv123 | 0:88b85febcb45 | 117 | |
iv123 | 0:88b85febcb45 | 118 | if (fw_size % MIN_WRITE_BLOCK_SIZE) |
iv123 | 0:88b85febcb45 | 119 | return BLE_UTIL_WRONG_IMAGE_SIZE; |
iv123 | 0:88b85febcb45 | 120 | |
iv123 | 0:88b85febcb45 | 121 | /* Calculate the number of sectors necessary to contain the fw image.*/ |
iv123 | 0:88b85febcb45 | 122 | number_sectors = ((fw_size + SECTOR_SIZE - 1) / SECTOR_SIZE); |
iv123 | 0:88b85febcb45 | 123 | |
iv123 | 0:88b85febcb45 | 124 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 125 | * Erase BLUE flag |
iv123 | 0:88b85febcb45 | 126 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 127 | RETRY_COMMAND(aci_erase_blue_flag(), MAX_WRITE_RETRIES, status); |
iv123 | 0:88b85febcb45 | 128 | if (status != BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 129 | return status; |
iv123 | 0:88b85febcb45 | 130 | |
iv123 | 0:88b85febcb45 | 131 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 132 | * Erase and Program sectors |
iv123 | 0:88b85febcb45 | 133 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 134 | for(unsigned int i = fw_offset; i < (number_sectors * SECTOR_SIZE); i += SECTOR_SIZE) { |
iv123 | 0:88b85febcb45 | 135 | num_erase_retries = 0; |
iv123 | 0:88b85febcb45 | 136 | while (num_erase_retries++ < MAX_ERASE_RETRIES) { |
iv123 | 0:88b85febcb45 | 137 | aci_updater_erase_sector(BASE_ADDRESS + i); |
iv123 | 0:88b85febcb45 | 138 | if ((i/SECTOR_SIZE) < (unsigned int)(number_sectors-1)) |
iv123 | 0:88b85febcb45 | 139 | data_size = DATA_SIZE; |
iv123 | 0:88b85febcb45 | 140 | else |
iv123 | 0:88b85febcb45 | 141 | data_size = MIN_WRITE_BLOCK_SIZE; |
iv123 | 0:88b85febcb45 | 142 | for (j=i; ((j<SECTOR_SIZE+i)&&(j<fw_size)); j += data_size) { |
iv123 | 0:88b85febcb45 | 143 | RETRY_COMMAND(aci_updater_program_data_block(BASE_ADDRESS+j, data_size, fw_image+j), MAX_WRITE_RETRIES, status); |
iv123 | 0:88b85febcb45 | 144 | if (status != BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 145 | break; |
iv123 | 0:88b85febcb45 | 146 | } |
iv123 | 0:88b85febcb45 | 147 | if (status == BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 148 | break; |
iv123 | 0:88b85febcb45 | 149 | } |
iv123 | 0:88b85febcb45 | 150 | if (num_erase_retries == MAX_ERASE_RETRIES) |
iv123 | 0:88b85febcb45 | 151 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 152 | } |
iv123 | 0:88b85febcb45 | 153 | |
iv123 | 0:88b85febcb45 | 154 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 155 | * Verify firmware |
iv123 | 0:88b85febcb45 | 156 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 157 | module = fw_size % SECTOR_SIZE; |
iv123 | 0:88b85febcb45 | 158 | crc_size = SECTOR_SIZE; |
iv123 | 0:88b85febcb45 | 159 | for(int i = fw_offset; i < (number_sectors*SECTOR_SIZE); i += SECTOR_SIZE){ |
iv123 | 0:88b85febcb45 | 160 | address = BASE_ADDRESS + i; |
iv123 | 0:88b85febcb45 | 161 | if(aci_updater_calc_crc(address, 1, &crc)) |
iv123 | 0:88b85febcb45 | 162 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 163 | |
iv123 | 0:88b85febcb45 | 164 | if ((module != 0) && ((i/SECTOR_SIZE) == (number_sectors-1))) |
iv123 | 0:88b85febcb45 | 165 | crc_size = module; |
iv123 | 0:88b85febcb45 | 166 | |
iv123 | 0:88b85febcb45 | 167 | crc2 = updater_calc_crc(fw_image+i,crc_size); |
iv123 | 0:88b85febcb45 | 168 | if(crc!=crc2) |
iv123 | 0:88b85febcb45 | 169 | return BLE_UTIL_CRC_ERROR; |
iv123 | 0:88b85febcb45 | 170 | } |
iv123 | 0:88b85febcb45 | 171 | |
iv123 | 0:88b85febcb45 | 172 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 173 | * Write BLUE flag |
iv123 | 0:88b85febcb45 | 174 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 175 | RETRY_COMMAND(aci_reset_blue_flag(), MAX_WRITE_RETRIES, status); |
iv123 | 0:88b85febcb45 | 176 | if (status != BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 177 | return status; |
iv123 | 0:88b85febcb45 | 178 | |
iv123 | 0:88b85febcb45 | 179 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 180 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 181 | |
iv123 | 0:88b85febcb45 | 182 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 183 | } |
iv123 | 0:88b85febcb45 | 184 | |
iv123 | 0:88b85febcb45 | 185 | int read_IFR(uint8_t *data) |
iv123 | 0:88b85febcb45 | 186 | { |
iv123 | 0:88b85febcb45 | 187 | uint8_t version, offset; |
iv123 | 0:88b85febcb45 | 188 | tBleStatus ret; |
iv123 | 0:88b85febcb45 | 189 | |
iv123 | 0:88b85febcb45 | 190 | offset = 0; |
iv123 | 0:88b85febcb45 | 191 | aci_updater_start(); |
iv123 | 0:88b85febcb45 | 192 | if(aci_get_updater_version(&version)) |
iv123 | 0:88b85febcb45 | 193 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 194 | |
iv123 | 0:88b85febcb45 | 195 | if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX) |
iv123 | 0:88b85febcb45 | 196 | return BLE_UTIL_UNSUPPORTED_VERSION; |
iv123 | 0:88b85febcb45 | 197 | |
iv123 | 0:88b85febcb45 | 198 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 199 | * Reading last 3 IFR 64-byte blocks |
iv123 | 0:88b85febcb45 | 200 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 201 | for(int i = (FULL_STACK_SIZE - IFR_SIZE); i < FULL_STACK_SIZE; i += DATA_SIZE){ |
iv123 | 0:88b85febcb45 | 202 | ret = aci_updater_read_data_block(BASE_ADDRESS+i, DATA_SIZE, (data+offset)); |
iv123 | 0:88b85febcb45 | 203 | offset += DATA_SIZE; |
iv123 | 0:88b85febcb45 | 204 | if(ret) return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 205 | } |
iv123 | 0:88b85febcb45 | 206 | |
iv123 | 0:88b85febcb45 | 207 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 208 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 209 | |
iv123 | 0:88b85febcb45 | 210 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 211 | |
iv123 | 0:88b85febcb45 | 212 | } |
iv123 | 0:88b85febcb45 | 213 | |
iv123 | 0:88b85febcb45 | 214 | void parse_IFR_data_config(const uint8_t data[64], IFR_config2_TypeDef *IFR_config) |
iv123 | 0:88b85febcb45 | 215 | { |
iv123 | 0:88b85febcb45 | 216 | IFR_config->stack_mode = data[0]; |
iv123 | 0:88b85febcb45 | 217 | IFR_config->slave_sca_ppm = LE_TO_HOST_16(data+28); |
iv123 | 0:88b85febcb45 | 218 | IFR_config->master_sca = data[30]; |
iv123 | 0:88b85febcb45 | 219 | IFR_config->hs_startup_time = LE_TO_HOST_16(data+32); |
iv123 | 0:88b85febcb45 | 220 | IFR_config->year = BCD_TO_INT(data[41]); |
iv123 | 0:88b85febcb45 | 221 | IFR_config->month = BCD_TO_INT(data[42]); |
iv123 | 0:88b85febcb45 | 222 | IFR_config->day = BCD_TO_INT(data[43]); |
iv123 | 0:88b85febcb45 | 223 | } |
iv123 | 0:88b85febcb45 | 224 | |
iv123 | 0:88b85febcb45 | 225 | int IFR_validate(IFR_config2_TypeDef *IFR_config) |
iv123 | 0:88b85febcb45 | 226 | { |
iv123 | 0:88b85febcb45 | 227 | #if BLUENRG_MS |
iv123 | 0:88b85febcb45 | 228 | if(IFR_config->stack_mode < 1 || IFR_config->stack_mode > 4) |
iv123 | 0:88b85febcb45 | 229 | #else |
iv123 | 0:88b85febcb45 | 230 | if(IFR_config->stack_mode < 1 || IFR_config->stack_mode > 3) |
iv123 | 0:88b85febcb45 | 231 | #endif |
iv123 | 0:88b85febcb45 | 232 | return BLE_UTIL_PARSE_ERROR; // Unknown Stack Mode |
iv123 | 0:88b85febcb45 | 233 | if(IFR_config->master_sca > 7) |
iv123 | 0:88b85febcb45 | 234 | return BLE_UTIL_PARSE_ERROR; // Invalid Master SCA |
iv123 | 0:88b85febcb45 | 235 | if(IFR_config->month > 12 || IFR_config->month < 1) |
iv123 | 0:88b85febcb45 | 236 | return BLE_UTIL_PARSE_ERROR; // Invalid date |
iv123 | 0:88b85febcb45 | 237 | if(IFR_config->day > 31 || IFR_config->day < 1) |
iv123 | 0:88b85febcb45 | 238 | return BLE_UTIL_PARSE_ERROR; // Invalid date |
iv123 | 0:88b85febcb45 | 239 | if(IFR_config->month > 12 || IFR_config->month < 1) |
iv123 | 0:88b85febcb45 | 240 | return BLE_UTIL_PARSE_ERROR; // Invalid date |
iv123 | 0:88b85febcb45 | 241 | |
iv123 | 0:88b85febcb45 | 242 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 243 | } |
iv123 | 0:88b85febcb45 | 244 | |
iv123 | 0:88b85febcb45 | 245 | /* TODO: Function to generate data from given options. */ |
iv123 | 0:88b85febcb45 | 246 | |
iv123 | 0:88b85febcb45 | 247 | void change_IFR_data_config(IFR_config2_TypeDef *IFR_config, uint8_t data[64]) |
iv123 | 0:88b85febcb45 | 248 | { |
iv123 | 0:88b85febcb45 | 249 | data[0] = IFR_config->stack_mode; |
iv123 | 0:88b85febcb45 | 250 | HOST_TO_LE_16(data+28, IFR_config->slave_sca_ppm); |
iv123 | 0:88b85febcb45 | 251 | data[30] = IFR_config->master_sca; |
iv123 | 0:88b85febcb45 | 252 | HOST_TO_LE_16(data+32, IFR_config->hs_startup_time); |
iv123 | 0:88b85febcb45 | 253 | data[41] = INT_TO_BCD(IFR_config->year); |
iv123 | 0:88b85febcb45 | 254 | data[42] = INT_TO_BCD(IFR_config->month); |
iv123 | 0:88b85febcb45 | 255 | data[43] = INT_TO_BCD(IFR_config->day); |
iv123 | 0:88b85febcb45 | 256 | } |
iv123 | 0:88b85febcb45 | 257 | |
iv123 | 0:88b85febcb45 | 258 | |
iv123 | 0:88b85febcb45 | 259 | int program_IFR(const IFR_config_TypeDef *ifr_image) |
iv123 | 0:88b85febcb45 | 260 | { |
iv123 | 0:88b85febcb45 | 261 | uint8_t version, num_erase_retries; |
iv123 | 0:88b85febcb45 | 262 | tBleStatus ret; |
iv123 | 0:88b85febcb45 | 263 | #if BLUENRG_MS |
iv123 | 0:88b85febcb45 | 264 | const uint8_t *ifr_data = (uint8_t *)ifr_image; |
iv123 | 0:88b85febcb45 | 265 | #else |
iv123 | 0:88b85febcb45 | 266 | uint8_t ifr_data[SECTOR_SIZE]; |
iv123 | 0:88b85febcb45 | 267 | #endif |
iv123 | 0:88b85febcb45 | 268 | uint8_t hwVersion; |
iv123 | 0:88b85febcb45 | 269 | uint16_t fwVersion; |
iv123 | 0:88b85febcb45 | 270 | |
iv123 | 0:88b85febcb45 | 271 | if(getBlueNRGVersion(&hwVersion, &fwVersion)) |
iv123 | 0:88b85febcb45 | 272 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 273 | |
iv123 | 0:88b85febcb45 | 274 | BlueNRG_HW_Bootloader(); |
iv123 | 0:88b85febcb45 | 275 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 276 | |
iv123 | 0:88b85febcb45 | 277 | if(aci_get_updater_version(&version)) |
iv123 | 0:88b85febcb45 | 278 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 279 | |
iv123 | 0:88b85febcb45 | 280 | if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX) |
iv123 | 0:88b85febcb45 | 281 | return BLE_UTIL_UNSUPPORTED_VERSION; |
iv123 | 0:88b85febcb45 | 282 | |
iv123 | 0:88b85febcb45 | 283 | #ifndef BLUENRG_MS |
iv123 | 0:88b85febcb45 | 284 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 285 | * READ IFR data |
iv123 | 0:88b85febcb45 | 286 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 287 | for(int i = 0; i < SECTOR_SIZE; i += DATA_SIZE){ |
iv123 | 0:88b85febcb45 | 288 | ret = aci_updater_read_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_data+i); |
iv123 | 0:88b85febcb45 | 289 | if(ret != BLE_STATUS_SUCCESS){ |
iv123 | 0:88b85febcb45 | 290 | return ret; |
iv123 | 0:88b85febcb45 | 291 | } |
iv123 | 0:88b85febcb45 | 292 | } |
iv123 | 0:88b85febcb45 | 293 | #endif |
iv123 | 0:88b85febcb45 | 294 | |
iv123 | 0:88b85febcb45 | 295 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 296 | * Erase & Flashing IFR sectors |
iv123 | 0:88b85febcb45 | 297 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 298 | #ifndef BLUENRG_MS |
iv123 | 0:88b85febcb45 | 299 | Osal_MemCpy(&ifr_data[SECTOR_SIZE-IFR_SIZE], ifr_image, IFR_SIZE); |
iv123 | 0:88b85febcb45 | 300 | #endif |
iv123 | 0:88b85febcb45 | 301 | num_erase_retries = 0; |
iv123 | 0:88b85febcb45 | 302 | while (num_erase_retries++ < MAX_ERASE_RETRIES) { |
iv123 | 0:88b85febcb45 | 303 | aci_updater_erase_sector(IFR_BASE_ADDRESS); |
iv123 | 0:88b85febcb45 | 304 | for(int i = IFR_WRITE_OFFSET_BEGIN, j = 0; i < SECTOR_SIZE; i += DATA_SIZE, j += DATA_SIZE) { |
iv123 | 0:88b85febcb45 | 305 | RETRY_COMMAND(aci_updater_program_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_data+j), MAX_WRITE_RETRIES, ret); |
iv123 | 0:88b85febcb45 | 306 | if (ret != BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 307 | break; |
iv123 | 0:88b85febcb45 | 308 | } |
iv123 | 0:88b85febcb45 | 309 | if (ret == BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 310 | break; |
iv123 | 0:88b85febcb45 | 311 | } |
iv123 | 0:88b85febcb45 | 312 | if (num_erase_retries == MAX_ERASE_RETRIES) |
iv123 | 0:88b85febcb45 | 313 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 314 | |
iv123 | 0:88b85febcb45 | 315 | /*********************************************************************** |
iv123 | 0:88b85febcb45 | 316 | * Verify IFR |
iv123 | 0:88b85febcb45 | 317 | ************************************************************************/ |
iv123 | 0:88b85febcb45 | 318 | { |
iv123 | 0:88b85febcb45 | 319 | uint8_t ifr_updated[DATA_SIZE]; |
iv123 | 0:88b85febcb45 | 320 | for(int i = IFR_WRITE_OFFSET_BEGIN, j = 0; i < SECTOR_SIZE; i += DATA_SIZE, j += DATA_SIZE){ |
iv123 | 0:88b85febcb45 | 321 | ret = aci_updater_read_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_updated); |
iv123 | 0:88b85febcb45 | 322 | if(ret != BLE_STATUS_SUCCESS){ |
iv123 | 0:88b85febcb45 | 323 | return ret; |
iv123 | 0:88b85febcb45 | 324 | } |
iv123 | 0:88b85febcb45 | 325 | if (memcmp(ifr_updated, ifr_data+j, DATA_SIZE) != 0) |
iv123 | 0:88b85febcb45 | 326 | return BLE_UTIL_WRONG_VERIFY; |
iv123 | 0:88b85febcb45 | 327 | } |
iv123 | 0:88b85febcb45 | 328 | } |
iv123 | 0:88b85febcb45 | 329 | |
iv123 | 0:88b85febcb45 | 330 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 331 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 332 | |
iv123 | 0:88b85febcb45 | 333 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 334 | } |
iv123 | 0:88b85febcb45 | 335 | |
iv123 | 0:88b85febcb45 | 336 | uint8_t verify_IFR(const IFR_config_TypeDef *ifr_data) |
iv123 | 0:88b85febcb45 | 337 | { |
iv123 | 0:88b85febcb45 | 338 | uint8_t ifr_updated[DATA_SIZE]; |
iv123 | 0:88b85febcb45 | 339 | uint8_t version, ret = BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 340 | |
iv123 | 0:88b85febcb45 | 341 | aci_updater_start(); |
iv123 | 0:88b85febcb45 | 342 | if(aci_get_updater_version(&version)) |
iv123 | 0:88b85febcb45 | 343 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 344 | for(int i = 0; i < IFR_SIZE; i += DATA_SIZE){ |
iv123 | 0:88b85febcb45 | 345 | ret = aci_updater_read_data_block((IFR_BASE_ADDRESS+SECTOR_SIZE-IFR_SIZE)+i, DATA_SIZE, ifr_updated); |
iv123 | 0:88b85febcb45 | 346 | if(ret != BLE_STATUS_SUCCESS){ |
iv123 | 0:88b85febcb45 | 347 | return ret; |
iv123 | 0:88b85febcb45 | 348 | } |
iv123 | 0:88b85febcb45 | 349 | if (memcmp(ifr_updated, ((uint8_t*)ifr_data)+i, DATA_SIZE) != 0) |
iv123 | 0:88b85febcb45 | 350 | { |
iv123 | 0:88b85febcb45 | 351 | ret = BLE_UTIL_WRONG_VERIFY; |
iv123 | 0:88b85febcb45 | 352 | break; |
iv123 | 0:88b85febcb45 | 353 | } |
iv123 | 0:88b85febcb45 | 354 | } |
iv123 | 0:88b85febcb45 | 355 | |
iv123 | 0:88b85febcb45 | 356 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 357 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 358 | |
iv123 | 0:88b85febcb45 | 359 | return ret; |
iv123 | 0:88b85febcb45 | 360 | } |
iv123 | 0:88b85febcb45 | 361 | |
iv123 | 0:88b85febcb45 | 362 | uint8_t getBlueNRGVersion(uint8_t *hwVersion, uint16_t *fwVersion) |
iv123 | 0:88b85febcb45 | 363 | { |
iv123 | 0:88b85febcb45 | 364 | uint8_t status; |
iv123 | 0:88b85febcb45 | 365 | uint8_t hci_version, lmp_pal_version; |
iv123 | 0:88b85febcb45 | 366 | uint16_t hci_revision, manufacturer_name, lmp_pal_subversion; |
iv123 | 0:88b85febcb45 | 367 | |
iv123 | 0:88b85febcb45 | 368 | status = hci_le_read_local_version(&hci_version, &hci_revision, &lmp_pal_version, |
iv123 | 0:88b85febcb45 | 369 | &manufacturer_name, &lmp_pal_subversion); |
iv123 | 0:88b85febcb45 | 370 | |
iv123 | 0:88b85febcb45 | 371 | if (status == BLE_STATUS_SUCCESS) { |
iv123 | 0:88b85febcb45 | 372 | *hwVersion = hci_revision >> 8; |
iv123 | 0:88b85febcb45 | 373 | *fwVersion = (hci_revision & 0xFF) << 8; // Major Version Number |
iv123 | 0:88b85febcb45 | 374 | *fwVersion |= ((lmp_pal_subversion >> 4) & 0xF) << 4; // Minor Version Number |
iv123 | 0:88b85febcb45 | 375 | *fwVersion |= lmp_pal_subversion & 0xF; // Patch Version Number |
iv123 | 0:88b85febcb45 | 376 | } |
iv123 | 0:88b85febcb45 | 377 | |
iv123 | 0:88b85febcb45 | 378 | return status; |
iv123 | 0:88b85febcb45 | 379 | } |
iv123 | 0:88b85febcb45 | 380 | |
iv123 | 0:88b85febcb45 | 381 | uint8_t getBlueNRGUpdaterVersion(uint8_t *version) |
iv123 | 0:88b85febcb45 | 382 | { |
iv123 | 0:88b85febcb45 | 383 | |
iv123 | 0:88b85febcb45 | 384 | BlueNRG_HW_Bootloader(); |
iv123 | 0:88b85febcb45 | 385 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 386 | |
iv123 | 0:88b85febcb45 | 387 | if(aci_get_updater_version(version)) |
iv123 | 0:88b85febcb45 | 388 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 389 | |
iv123 | 0:88b85febcb45 | 390 | if(*version < SUPPORTED_BOOTLOADER_VERSION_MIN || *version > SUPPORTED_BOOTLOADER_VERSION_MAX) |
iv123 | 0:88b85febcb45 | 391 | return BLE_UTIL_UNSUPPORTED_VERSION; |
iv123 | 0:88b85febcb45 | 392 | |
iv123 | 0:88b85febcb45 | 393 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 394 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 395 | |
iv123 | 0:88b85febcb45 | 396 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 397 | } |
iv123 | 0:88b85febcb45 | 398 | |
iv123 | 0:88b85febcb45 | 399 | uint8_t getBlueNRGUpdaterHWVersion(uint8_t *version) |
iv123 | 0:88b85febcb45 | 400 | { |
iv123 | 0:88b85febcb45 | 401 | |
iv123 | 0:88b85febcb45 | 402 | BlueNRG_HW_Bootloader(); |
iv123 | 0:88b85febcb45 | 403 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 404 | |
iv123 | 0:88b85febcb45 | 405 | if(aci_updater_hw_version(version)) |
iv123 | 0:88b85febcb45 | 406 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 407 | |
iv123 | 0:88b85febcb45 | 408 | BlueNRG_RST(); |
iv123 | 0:88b85febcb45 | 409 | HCI_Process(); // To receive the EVT_INITIALIZED |
iv123 | 0:88b85febcb45 | 410 | |
iv123 | 0:88b85febcb45 | 411 | return BLE_STATUS_SUCCESS; |
iv123 | 0:88b85febcb45 | 412 | } |
iv123 | 0:88b85febcb45 | 413 | |
iv123 | 0:88b85febcb45 | 414 | uint8_t isHWBootloader_Patched(void) |
iv123 | 0:88b85febcb45 | 415 | { |
iv123 | 0:88b85febcb45 | 416 | uint8_t status, version; |
iv123 | 0:88b85febcb45 | 417 | uint32_t crc, address = 0x10010000; |
iv123 | 0:88b85febcb45 | 418 | |
iv123 | 0:88b85febcb45 | 419 | if(aci_get_updater_version(&version)) |
iv123 | 0:88b85febcb45 | 420 | return BLE_UTIL_ACI_ERROR; |
iv123 | 0:88b85febcb45 | 421 | |
iv123 | 0:88b85febcb45 | 422 | RETRY_COMMAND(aci_updater_calc_crc(address, 1, &crc), 2, status); |
iv123 | 0:88b85febcb45 | 423 | if (status != BLE_STATUS_SUCCESS) |
iv123 | 0:88b85febcb45 | 424 | return 0; |
iv123 | 0:88b85febcb45 | 425 | |
iv123 | 0:88b85febcb45 | 426 | if (crc == BOOTLOADER_CRC_NOT_PATCHED) |
iv123 | 0:88b85febcb45 | 427 | return 0; |
iv123 | 0:88b85febcb45 | 428 | |
iv123 | 0:88b85febcb45 | 429 | return 1; |
iv123 | 0:88b85febcb45 | 430 | } |