BLE shield

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