test

Dependents:   BLE_HeartRate_IDB0XA1_EPUDEE_Avril2018

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bluenrg_utils.c Source File

bluenrg_utils.c

00001 
00002 #include "ble_hal.h"
00003 #include "ble_hal_types.h"
00004 #include "ble_status.h"
00005 #include "bluenrg_aci.h"
00006 #include "bluenrg_utils.h"
00007 #include "ble_hci.h"
00008 #include "ble_osal.h"
00009 #include "string.h"
00010 #include "stm32_bluenrg_ble.h "
00011 
00012 #define SUPPORTED_BOOTLOADER_VERSION_MIN  3
00013 #define SUPPORTED_BOOTLOADER_VERSION_MAX  5
00014 
00015 #define BASE_ADDRESS 0x10010000
00016 
00017 #define FW_OFFSET       (2*1024)  // 2 KB
00018 #define FW_OFFSET_MS    0
00019 #define FULL_STACK_SIZE (66*1024) // 66 KB
00020 #define BOOTLOADER_SIZE (2*1024)  // 2 kB
00021 #define SECTOR_SIZE     (2*1024)  // 2 KB
00022 #define DATA_SIZE       64        // 64 bytes
00023 
00024 // x**32 + x**26 + x**23 + x ** 22 + x**16 + x**12 + x**11 +
00025 // x**10 + x**8 + x**7 + x**5 + x**4 + x**2 + x**1 + x**0
00026 #define CRC_POLY        0x04C11DB7      // the poly without the x**32
00027 
00028 #define BOOTLOADER_CRC_NOT_PATCHED 0x878FB3FC
00029 
00030 #define IFR_SIZE 192
00031 #define IFR_BASE_ADDRESS 0x10020000
00032 #define IFR_CONFIG_DATA_OFFSET (SECTOR_SIZE-IFR_SIZE)  // Offset in IFR sector containing configuration data
00033 
00034 #if BLUENRG_MS
00035 #define IFR_WRITE_OFFSET_BEGIN IFR_CONFIG_DATA_OFFSET
00036 #else
00037 #define IFR_WRITE_OFFSET_BEGIN 0
00038 #endif
00039 
00040 
00041 #define BLUE_FLAG_OFFSET 0x8C0
00042 #define MAX_ERASE_RETRIES 2
00043 #define MAX_WRITE_RETRIES 2
00044 #define MIN_WRITE_BLOCK_SIZE 4
00045 
00046 #define RETRY_COMMAND(func, num_ret, error)  \
00047 {                   \
00048   uint8_t num_retries;                  \
00049   num_retries = 0;          \
00050   error = 0;                \
00051   while (num_retries++ < num_ret)  {    \
00052     if (func == BLE_STATUS_SUCCESS) \
00053       break;                \
00054     if (num_retries == num_ret)     \
00055       error = BLE_UTIL_ACI_ERROR;   \
00056   }                 \
00057 }
00058 
00059 typedef struct{
00060   uint8_t cold_ana_act_config_table[64];
00061 }cold_table_TypeDef;
00062 
00063 /* This function calculates the CRC of a sector of flash, if bytes passed are less than sector size, 
00064    they are extended with 0xFF until sector size is reached
00065 */
00066 static uint32_t updater_calc_crc(const uint8_t* data, uint16_t nr_of_bytes)
00067 {
00068     uint32_t i, j, a1;
00069     uint32_t crc, value;
00070 
00071     crc = 0;
00072     for (i = 0; i < SECTOR_SIZE; i += 4) {
00073       uint8_t *dataw = (uint8_t *) &value;
00074      
00075       dataw[0] = (i < nr_of_bytes) ? data[i] : 0xFF;
00076       dataw[1] = ((i + 1) < nr_of_bytes) ? data[i+1] : 0xFF;
00077       dataw[2] = ((i + 2) < nr_of_bytes) ? data[i+2] : 0xFF;
00078       dataw[3] = ((i + 3) < nr_of_bytes) ? data[i+3] : 0xFF;
00079 
00080       crc = crc ^ value;
00081       for (j = 0; j < 32; j ++) {
00082     a1 = (crc >> 31) & 0x1;
00083     crc = (crc << 1) ^ (a1 * CRC_POLY);
00084       }
00085     }
00086 
00087     return crc;
00088 }
00089 
00090 int program_device(const uint8_t *fw_image, uint32_t fw_size)
00091 {
00092   uint8_t version, num_erase_retries=0, status, data_size;
00093   uint8_t number_sectors, module;
00094   uint32_t address, j;
00095   uint32_t crc, crc2, crc_size;
00096   uint32_t fw_offset = FW_OFFSET;
00097   
00098   BlueNRG_HW_Bootloader();
00099   HCI_Process(); // To receive the EVT_INITIALIZED
00100 
00101   if(aci_get_updater_version(&version))
00102     return BLE_UTIL_ACI_ERROR;
00103   
00104   if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX)
00105     return BLE_UTIL_UNSUPPORTED_VERSION;
00106   
00107   if(aci_updater_hw_version(&version))
00108     return BLE_UTIL_ACI_ERROR;
00109   
00110   if(version==0x31){
00111     // It does not contain bootloader inside first sector. It may contain code.
00112     fw_offset = FW_OFFSET_MS;
00113   }
00114   
00115   if (fw_size != FULL_STACK_SIZE)
00116     return BLE_UTIL_WRONG_IMAGE_SIZE;
00117 
00118   if (fw_size % MIN_WRITE_BLOCK_SIZE)
00119     return BLE_UTIL_WRONG_IMAGE_SIZE;
00120 
00121   /* Calculate the number of sectors necessary to contain the fw image.*/
00122   number_sectors = ((fw_size + SECTOR_SIZE - 1) / SECTOR_SIZE);
00123 
00124   /***********************************************************************
00125   * Erase BLUE flag
00126   ************************************************************************/
00127   RETRY_COMMAND(aci_erase_blue_flag(), MAX_WRITE_RETRIES, status);
00128   if (status != BLE_STATUS_SUCCESS)
00129     return status;
00130 
00131   /***********************************************************************
00132   * Erase and Program sectors
00133   ************************************************************************/  
00134   for(unsigned int i = fw_offset; i < (number_sectors * SECTOR_SIZE); i += SECTOR_SIZE) {
00135     num_erase_retries = 0;
00136     while (num_erase_retries++ < MAX_ERASE_RETRIES) {
00137       aci_updater_erase_sector(BASE_ADDRESS + i);
00138       if ((i/SECTOR_SIZE) < (unsigned int)(number_sectors-1))
00139     data_size = DATA_SIZE;
00140       else
00141     data_size = MIN_WRITE_BLOCK_SIZE;   
00142       for (j=i; ((j<SECTOR_SIZE+i)&&(j<fw_size)); j += data_size) {
00143     RETRY_COMMAND(aci_updater_program_data_block(BASE_ADDRESS+j, data_size, fw_image+j), MAX_WRITE_RETRIES, status);
00144     if (status != BLE_STATUS_SUCCESS)
00145       break;
00146       }
00147       if (status == BLE_STATUS_SUCCESS)
00148     break;
00149     }
00150     if (num_erase_retries == MAX_ERASE_RETRIES)
00151       return BLE_UTIL_ACI_ERROR;
00152   }
00153   
00154   /***********************************************************************
00155   * Verify firmware
00156   ************************************************************************/
00157   module = fw_size % SECTOR_SIZE;
00158   crc_size = SECTOR_SIZE;
00159   for(int i = fw_offset; i < (number_sectors*SECTOR_SIZE); i += SECTOR_SIZE){
00160     address = BASE_ADDRESS + i;
00161     if(aci_updater_calc_crc(address, 1, &crc))
00162       return BLE_UTIL_ACI_ERROR;
00163     
00164     if ((module != 0)  && ((i/SECTOR_SIZE) == (number_sectors-1)))
00165     crc_size = module;
00166 
00167     crc2 = updater_calc_crc(fw_image+i,crc_size);
00168     if(crc!=crc2)
00169       return BLE_UTIL_CRC_ERROR;
00170   }
00171 
00172   /***********************************************************************
00173   * Write BLUE flag
00174   ************************************************************************/
00175   RETRY_COMMAND(aci_reset_blue_flag(), MAX_WRITE_RETRIES, status);
00176   if (status != BLE_STATUS_SUCCESS)
00177     return status;
00178   
00179   BlueNRG_RST();
00180   HCI_Process(); // To receive the EVT_INITIALIZED
00181   
00182   return BLE_STATUS_SUCCESS;
00183 }
00184 
00185 int read_IFR(uint8_t *data)
00186 {
00187   uint8_t version, offset;
00188   tBleStatus ret;
00189   
00190   offset = 0;
00191   aci_updater_start();
00192   if(aci_get_updater_version(&version))
00193     return BLE_UTIL_ACI_ERROR;
00194   
00195   if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX)
00196     return BLE_UTIL_UNSUPPORTED_VERSION;
00197   
00198   /***********************************************************************
00199   * Reading last 3 IFR 64-byte blocks
00200   ************************************************************************/
00201   for(int i = (FULL_STACK_SIZE - IFR_SIZE); i < FULL_STACK_SIZE; i += DATA_SIZE){
00202     ret = aci_updater_read_data_block(BASE_ADDRESS+i, DATA_SIZE, (data+offset));
00203     offset += DATA_SIZE;
00204     if(ret) return BLE_UTIL_ACI_ERROR;
00205   }
00206   
00207   BlueNRG_RST();
00208   HCI_Process(); // To receive the EVT_INITIALIZED
00209 
00210   return BLE_STATUS_SUCCESS;
00211   
00212 }
00213 
00214 void parse_IFR_data_config(const uint8_t data[64], IFR_config2_TypeDef *IFR_config)
00215 {
00216   IFR_config->stack_mode = data[0];
00217   IFR_config->slave_sca_ppm = LE_TO_HOST_16(data+28);
00218   IFR_config->master_sca = data[30];
00219   IFR_config->hs_startup_time = LE_TO_HOST_16(data+32);
00220   IFR_config->year = BCD_TO_INT(data[41]);
00221   IFR_config->month = BCD_TO_INT(data[42]);
00222   IFR_config->day = BCD_TO_INT(data[43]);    
00223 }
00224 
00225 int IFR_validate(IFR_config2_TypeDef *IFR_config)
00226 {
00227 #if BLUENRG_MS
00228   if(IFR_config->stack_mode < 1 || IFR_config->stack_mode > 4)
00229 #else
00230     if(IFR_config->stack_mode < 1 || IFR_config->stack_mode > 3)
00231 #endif
00232       return BLE_UTIL_PARSE_ERROR; // Unknown Stack Mode
00233   if(IFR_config->master_sca > 7)
00234     return BLE_UTIL_PARSE_ERROR; // Invalid Master SCA
00235   if(IFR_config->month > 12 || IFR_config->month < 1)
00236     return BLE_UTIL_PARSE_ERROR; // Invalid date
00237   if(IFR_config->day > 31 || IFR_config->day < 1)
00238     return BLE_UTIL_PARSE_ERROR; // Invalid date
00239   if(IFR_config->month > 12 || IFR_config->month < 1)
00240     return BLE_UTIL_PARSE_ERROR; // Invalid date
00241   
00242   return BLE_STATUS_SUCCESS;
00243 }
00244 
00245 /* TODO: Function to generate data from given options. */
00246 
00247 void change_IFR_data_config(IFR_config2_TypeDef *IFR_config, uint8_t data[64])
00248 {
00249   data[0] = IFR_config->stack_mode;
00250   HOST_TO_LE_16(data+28, IFR_config->slave_sca_ppm);
00251   data[30] = IFR_config->master_sca;
00252   HOST_TO_LE_16(data+32, IFR_config->hs_startup_time);  
00253   data[41] = INT_TO_BCD(IFR_config->year);
00254   data[42] = INT_TO_BCD(IFR_config->month);
00255   data[43] = INT_TO_BCD(IFR_config->day);
00256 }
00257 
00258 
00259 int program_IFR(const IFR_config_TypeDef *ifr_image)
00260 {
00261   uint8_t version, num_erase_retries;
00262   tBleStatus ret;
00263 #if BLUENRG_MS
00264   const uint8_t *ifr_data = (uint8_t *)ifr_image;
00265 #else
00266   uint8_t ifr_data[SECTOR_SIZE];
00267 #endif
00268   uint8_t hwVersion;
00269   uint16_t fwVersion;
00270     
00271   if(getBlueNRGVersion(&hwVersion, &fwVersion))
00272     return BLE_UTIL_ACI_ERROR;
00273   
00274   BlueNRG_HW_Bootloader();
00275   HCI_Process(); // To receive the EVT_INITIALIZED
00276   
00277   if(aci_get_updater_version(&version))
00278     return BLE_UTIL_ACI_ERROR;
00279   
00280   if(version < SUPPORTED_BOOTLOADER_VERSION_MIN || version > SUPPORTED_BOOTLOADER_VERSION_MAX)
00281     return BLE_UTIL_UNSUPPORTED_VERSION;
00282   
00283 #ifndef BLUENRG_MS
00284     /***********************************************************************
00285    * READ IFR data
00286    ************************************************************************/  
00287   for(int i = 0; i < SECTOR_SIZE; i += DATA_SIZE){
00288     ret = aci_updater_read_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_data+i);
00289     if(ret != BLE_STATUS_SUCCESS){
00290       return ret;
00291     }
00292   }
00293 #endif
00294   
00295   /***********************************************************************
00296   * Erase & Flashing IFR sectors
00297   ************************************************************************/
00298 #ifndef BLUENRG_MS  
00299   Osal_MemCpy(&ifr_data[SECTOR_SIZE-IFR_SIZE], ifr_image, IFR_SIZE);
00300 #endif
00301   num_erase_retries = 0;
00302   while (num_erase_retries++ < MAX_ERASE_RETRIES) {
00303     aci_updater_erase_sector(IFR_BASE_ADDRESS);
00304     for(int i = IFR_WRITE_OFFSET_BEGIN, j = 0; i < SECTOR_SIZE; i += DATA_SIZE, j += DATA_SIZE) {
00305       RETRY_COMMAND(aci_updater_program_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_data+j), MAX_WRITE_RETRIES, ret);
00306       if (ret != BLE_STATUS_SUCCESS)
00307     break;
00308     }
00309     if (ret == BLE_STATUS_SUCCESS)
00310       break;
00311   }
00312   if (num_erase_retries == MAX_ERASE_RETRIES)
00313     return BLE_UTIL_ACI_ERROR;
00314 
00315   /***********************************************************************
00316   * Verify IFR
00317   ************************************************************************/  
00318   {
00319     uint8_t ifr_updated[DATA_SIZE];
00320     for(int i = IFR_WRITE_OFFSET_BEGIN, j = 0; i < SECTOR_SIZE; i += DATA_SIZE, j += DATA_SIZE){
00321       ret = aci_updater_read_data_block(IFR_BASE_ADDRESS+i, DATA_SIZE, ifr_updated);
00322       if(ret != BLE_STATUS_SUCCESS){
00323     return ret;
00324       }
00325       if (memcmp(ifr_updated, ifr_data+j, DATA_SIZE) != 0)
00326     return BLE_UTIL_WRONG_VERIFY;
00327     }
00328   }
00329 
00330   BlueNRG_RST();
00331   HCI_Process(); // To receive the EVT_INITIALIZED
00332     
00333   return BLE_STATUS_SUCCESS;
00334 }
00335 
00336 uint8_t verify_IFR(const IFR_config_TypeDef *ifr_data)
00337 {
00338   uint8_t ifr_updated[DATA_SIZE];
00339   uint8_t version, ret = BLE_STATUS_SUCCESS;
00340     
00341   aci_updater_start();
00342   if(aci_get_updater_version(&version))
00343     return BLE_UTIL_ACI_ERROR;
00344   for(int i = 0; i < IFR_SIZE; i += DATA_SIZE){
00345     ret = aci_updater_read_data_block((IFR_BASE_ADDRESS+SECTOR_SIZE-IFR_SIZE)+i, DATA_SIZE, ifr_updated);
00346     if(ret != BLE_STATUS_SUCCESS){
00347       return ret;
00348     }
00349     if (memcmp(ifr_updated, ((uint8_t*)ifr_data)+i, DATA_SIZE) != 0)
00350     {
00351       ret = BLE_UTIL_WRONG_VERIFY;
00352       break;
00353     }
00354   }
00355 
00356   BlueNRG_RST();
00357   HCI_Process(); // To receive the EVT_INITIALIZED
00358   
00359   return ret;
00360 }
00361 
00362 uint8_t getBlueNRGVersion(uint8_t *hwVersion, uint16_t *fwVersion)
00363 {
00364   uint8_t status;
00365   uint8_t hci_version, lmp_pal_version;
00366   uint16_t hci_revision, manufacturer_name, lmp_pal_subversion;
00367 
00368   status = hci_le_read_local_version(&hci_version, &hci_revision, &lmp_pal_version, 
00369                      &manufacturer_name, &lmp_pal_subversion);
00370 
00371   if (status == BLE_STATUS_SUCCESS) {
00372     *hwVersion = hci_revision >> 8;
00373     *fwVersion = (hci_revision & 0xFF) << 8;              // Major Version Number
00374     *fwVersion |= ((lmp_pal_subversion >> 4) & 0xF) << 4; // Minor Version Number
00375     *fwVersion |= lmp_pal_subversion & 0xF;               // Patch Version Number
00376   }
00377   
00378   return status;
00379 }
00380 
00381 uint8_t getBlueNRGUpdaterVersion(uint8_t *version)
00382 {
00383 
00384   BlueNRG_HW_Bootloader();
00385   HCI_Process(); // To receive the EVT_INITIALIZED
00386 
00387   if(aci_get_updater_version(version))
00388     return BLE_UTIL_ACI_ERROR;
00389   
00390   if(*version < SUPPORTED_BOOTLOADER_VERSION_MIN || *version > SUPPORTED_BOOTLOADER_VERSION_MAX)
00391     return BLE_UTIL_UNSUPPORTED_VERSION;
00392 
00393   BlueNRG_RST();
00394   HCI_Process(); // To receive the EVT_INITIALIZED
00395 
00396   return BLE_STATUS_SUCCESS;
00397 }
00398 
00399 uint8_t getBlueNRGUpdaterHWVersion(uint8_t *version)
00400 {
00401 
00402   BlueNRG_HW_Bootloader();
00403   HCI_Process(); // To receive the EVT_INITIALIZED
00404 
00405   if(aci_updater_hw_version(version))
00406     return BLE_UTIL_ACI_ERROR;
00407   
00408   BlueNRG_RST();
00409   HCI_Process(); // To receive the EVT_INITIALIZED
00410 
00411   return BLE_STATUS_SUCCESS;
00412 }
00413 
00414 uint8_t isHWBootloader_Patched(void)
00415 {
00416   uint8_t status, version;
00417   uint32_t crc, address = 0x10010000;
00418 
00419   if(aci_get_updater_version(&version))
00420     return BLE_UTIL_ACI_ERROR;
00421 
00422   RETRY_COMMAND(aci_updater_calc_crc(address, 1, &crc), 2, status);
00423   if (status != BLE_STATUS_SUCCESS)
00424     return 0;
00425 
00426   if (crc == BOOTLOADER_CRC_NOT_PATCHED)
00427     return 0;
00428 
00429   return 1;
00430 }