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