|
| 1 | +// Adafruit CC3000 Firmware V1.13 Upgrade Sketch |
| 2 | +// Based on firmware patcher for MSP430 chips published by Texas Instruments. |
| 3 | +// |
| 4 | +// This sketch will upgrade CC3000 modules up to firmware version 1.13. |
| 5 | +// |
| 6 | +// You can find more details about the changes in the 1.13 firmware from TI at: |
| 7 | +// http://processors.wiki.ti.com/index.php/CC3000_Release_Notes |
| 8 | +// |
| 9 | +// In general the 1.13 release is a bug fix release with fixes for stability |
| 10 | +// issues that caused the CC3000 to hand when under load. |
| 11 | +// |
| 12 | +// WARNING: Upgrade firmware at your own risk! In general if the CC3000 is |
| 13 | +// currently working fine for your needs then hold off on the upgrade. |
| 14 | +// |
| 15 | +// Usage (read all the steps before strarting): |
| 16 | +// - Wire up your Arduino to the CC3000 just like you're running buildtest or |
| 17 | +// other examples. |
| 18 | +// - Adjust the ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_VBAT |
| 19 | +// defines below to match your wiring (just like running buildtest). |
| 20 | +// - Load the sketch on your Arduino and open the serial monitor at 115200 baud. |
| 21 | +// - You should see a prompt waiting for a key press to continue. Enter text |
| 22 | +// and press enter to start the upgrade. |
| 23 | +// - You will see text printed as the firmware is upgraded. The upgrade process |
| 24 | +// should be quick and take less than a minute. |
| 25 | +// - You might see a message at the end that the firmware version or MAC address |
| 26 | +// couldn't be read--this can be ignored. |
| 27 | +// - Once the firmware upgrade is complete, run the buildtest sketch to check |
| 28 | +// the CC3000 functionality. |
| 29 | +// - During the firmware upgrade the CC3000 MAC address might be lost. You can |
| 30 | +// write a new MAC address by uncommenting the appropriate line in the buildtest |
| 31 | +// example. Make sure to save your MAC address before upgrading the firmware |
| 32 | +// if you'd like to keep it the same after |
| 33 | + |
| 34 | +#include <Adafruit_CC3000.h> |
| 35 | +#include <ccspi.h> |
| 36 | +#include <SPI.h> |
| 37 | +#include <string.h> |
| 38 | +#include <EEPROM.h> |
| 39 | + |
| 40 | +#include "utility/debug.h" |
| 41 | +#include "utility/nvmem.h" |
| 42 | +#include "driverpatchinc_1_13.h" |
| 43 | + |
| 44 | +#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin! |
| 45 | +#define ADAFRUIT_CC3000_CS 10 |
| 46 | +#define ADAFRUIT_CC3000_VBAT 5 |
| 47 | + |
| 48 | +Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT); |
| 49 | + |
| 50 | +/**************************************************************************/ |
| 51 | +/*! |
| 52 | + @brief Displays the driver mode (tiny of normal), and the buffer |
| 53 | + size if tiny mode is not being used |
| 54 | +
|
| 55 | + @note The buffer size and driver mode are defined in cc3000_common.h |
| 56 | +*/ |
| 57 | +/**************************************************************************/ |
| 58 | +void displayDriverMode(void) |
| 59 | +{ |
| 60 | + #ifdef CC3000_TINY_DRIVER |
| 61 | + Serial.println(F("CC3000 is configure in 'Tiny' mode")); |
| 62 | + #else |
| 63 | + Serial.print(F("RX Buffer : ")); |
| 64 | + Serial.print(CC3000_RX_BUFFER_SIZE); |
| 65 | + Serial.println(F(" bytes")); |
| 66 | + Serial.print(F("TX Buffer : ")); |
| 67 | + Serial.print(CC3000_TX_BUFFER_SIZE); |
| 68 | + Serial.println(F(" bytes")); |
| 69 | + #endif |
| 70 | +} |
| 71 | + |
| 72 | +/**************************************************************************/ |
| 73 | +/*! |
| 74 | + @brief Tries to read the CC3000's internal firmware patch ID |
| 75 | +*/ |
| 76 | +/**************************************************************************/ |
| 77 | +void displayFirmwareVersion(void) |
| 78 | +{ |
| 79 | + #ifndef CC3000_TINY_DRIVER |
| 80 | + uint8_t major, minor; |
| 81 | + |
| 82 | + if(!cc3000.getFirmwareVersion(&major, &minor)) |
| 83 | + { |
| 84 | + Serial.println(F("Unable to retrieve the firmware version!\r\n")); |
| 85 | + } |
| 86 | + else |
| 87 | + { |
| 88 | + Serial.print(F("Firmware V. : ")); |
| 89 | + Serial.print(major); Serial.print(F(".")); Serial.println(minor); |
| 90 | + } |
| 91 | + #endif |
| 92 | +} |
| 93 | + |
| 94 | +/**************************************************************************/ |
| 95 | +/*! |
| 96 | + @brief Tries to read the 6-byte MAC address of the CC3000 module |
| 97 | +*/ |
| 98 | +/**************************************************************************/ |
| 99 | +boolean MACvalid = false; |
| 100 | +// array to store MAC address from EEPROM |
| 101 | +uint8_t cMacFromEeprom[MAC_ADDR_LEN]; |
| 102 | +void displayMACAddress(void) |
| 103 | +{ |
| 104 | + if(!cc3000.getMacAddress(cMacFromEeprom)) |
| 105 | + { |
| 106 | + Serial.println(F("Unable to retrieve MAC Address!\r\n")); |
| 107 | + MACvalid = false; |
| 108 | + } |
| 109 | + else |
| 110 | + { |
| 111 | + Serial.print(F("MAC Address : ")); |
| 112 | + cc3000.printHex((byte*)&cMacFromEeprom, 6); |
| 113 | + MACvalid = true; |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | +/**************************************************************************/ |
| 120 | +/*! |
| 121 | + @brief Sets up the HW and the CC3000 module (called automatically |
| 122 | + on startup) |
| 123 | +*/ |
| 124 | +/**************************************************************************/ |
| 125 | + |
| 126 | +uint8_t ucStatus_Dr, return_status = 0xFF; |
| 127 | +uint8_t counter = 0; |
| 128 | + |
| 129 | +// array to store RM parameters from EEPROM |
| 130 | +unsigned char cRMParamsFromEeprom[128]; |
| 131 | + |
| 132 | + |
| 133 | +// 2 dim array to store address and length of new FAT |
| 134 | +uint16_t aFATEntries[2][NVMEM_RM_FILEID + 1] = |
| 135 | +/* address */ {{0x50, 0x1f0, 0x1390, 0x0390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, |
| 136 | +/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200 }}; |
| 137 | +/* 0. NVS */ |
| 138 | +/* 1. NVS Shadow */ |
| 139 | +/* 2. Wireless Conf */ |
| 140 | +/* 3. Wireless Conf Shadow */ |
| 141 | +/* 4. BT (WLAN driver) Patches */ |
| 142 | +/* 5. WiLink (Firmware) Patches */ |
| 143 | +/* 6. MAC addr */ |
| 144 | +/* 7. Frontend Vars */ |
| 145 | +/* 8. IP config */ |
| 146 | +/* 9. IP config Shadow */ |
| 147 | +/* 10. Bootloader Patches */ |
| 148 | +/* 11. Radio Module params */ |
| 149 | +/* 12. AES128 for smart config */ |
| 150 | +/* 13. user file */ |
| 151 | +/* 14. user file */ |
| 152 | +/* 15. user file */ |
| 153 | + |
| 154 | + |
| 155 | +void setup(void) |
| 156 | +{ |
| 157 | + Serial.begin(115200); |
| 158 | + Serial.println(F("Hello, CC3000!\n")); |
| 159 | + |
| 160 | + Serial.println(F("Hit any key & return to start")); |
| 161 | + while (!Serial.available()); |
| 162 | + |
| 163 | + pinMode(9, OUTPUT); |
| 164 | + pinMode(8, OUTPUT); |
| 165 | + pinMode(7, OUTPUT); |
| 166 | + pinMode(6, OUTPUT); |
| 167 | + digitalWrite(9, LOW); |
| 168 | + digitalWrite(8, LOW); |
| 169 | + digitalWrite(7, LOW); |
| 170 | + digitalWrite(6, LOW); |
| 171 | + |
| 172 | + displayDriverMode(); |
| 173 | + displayFreeRam(); |
| 174 | + |
| 175 | + /* Initialise the module */ |
| 176 | + Serial.println(F("\nInitialising the CC3000 ...")); |
| 177 | + if (!cc3000.begin(2)) // init with NO patches! |
| 178 | + { |
| 179 | + Serial.println(F("Unable to initialise the CC3000! Check your wiring?")); |
| 180 | + while(1); |
| 181 | + } |
| 182 | + |
| 183 | + displayFirmwareVersion(); |
| 184 | + displayMACAddress(); |
| 185 | + |
| 186 | + return_status = 1; |
| 187 | + uint8_t index; |
| 188 | + uint8_t *pRMParams; |
| 189 | + |
| 190 | + while ((return_status) && (counter < 3)) { |
| 191 | + // read RM parameters |
| 192 | + // read in 16 parts to work with tiny driver |
| 193 | + |
| 194 | + return_status = 0; |
| 195 | + pRMParams = cRMParamsFromEeprom; |
| 196 | + |
| 197 | + for (index = 0; index < 16; index++) { |
| 198 | + return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); |
| 199 | + Serial.print(F("\n\rRead NVRAM $")); Serial.print(8*index); Serial.print("\t"); |
| 200 | + for(uint8_t x=0; x<8; x++) { |
| 201 | + Serial.print("0x"); Serial.print(pRMParams[x], HEX); Serial.print(", "); |
| 202 | + } |
| 203 | + pRMParams += 8; |
| 204 | + } |
| 205 | + counter++; |
| 206 | + } |
| 207 | + // if RM file is not valid, load the default one |
| 208 | + if (counter == 3) { |
| 209 | + Serial.println(F("\n\rLoad default params")); |
| 210 | + pRMParams = (uint8_t *)cRMdefaultParams; |
| 211 | + } else { |
| 212 | + Serial.println(F("\n\rLoad EEPROM params")); |
| 213 | + pRMParams = cRMParamsFromEeprom; |
| 214 | + if (EEPROM.read(0) == 0xFF) { |
| 215 | + for (uint8_t e=0; e<128; e++) { |
| 216 | + EEPROM.write(e, cRMParamsFromEeprom[e]); |
| 217 | + } |
| 218 | + Serial.println(F("Backed up to eeprom!")); |
| 219 | + } |
| 220 | + } |
| 221 | + |
| 222 | + |
| 223 | + return_status = 1; |
| 224 | + |
| 225 | + while (return_status) { |
| 226 | + // write new FAT |
| 227 | + return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); |
| 228 | + Serial.print(F("Wrote FAT entries: ")); Serial.println(return_status, DEC); |
| 229 | + } |
| 230 | + |
| 231 | + //Serial.println(F("Stopping...")); |
| 232 | + //cc3000.stop(); |
| 233 | + |
| 234 | + //Serial.println(F("\nInitialising the CC3000 ...")); |
| 235 | + |
| 236 | + //if (!cc3000.begin(2)) // no patches! |
| 237 | + //{ |
| 238 | + // Serial.println(F("Unable to initialise the CC3000! Check your wiring?")); |
| 239 | + // while(1); |
| 240 | + //} |
| 241 | + |
| 242 | + return_status = 1; |
| 243 | + |
| 244 | + Serial.println(F("Write params")); |
| 245 | + |
| 246 | + while (return_status) { |
| 247 | + // write RM parameters |
| 248 | + // write in 4 parts to work with tiny driver |
| 249 | + |
| 250 | + return_status = 0; |
| 251 | + |
| 252 | + for (index = 0; index < 4; index++) { |
| 253 | + return_status |= nvmem_write(NVMEM_RM_FILEID, 32, 32*index, (pRMParams + 32*index)); |
| 254 | + Serial.println(F("Wrote 32 bytes to NVRAM")); |
| 255 | + } |
| 256 | + } |
| 257 | + Serial.println(F("Wrote params")); |
| 258 | + |
| 259 | + return_status = 1; |
| 260 | + |
| 261 | + // write back the MAC address, only if exist |
| 262 | + if (MACvalid) { |
| 263 | + // zero out MCAST bit if set |
| 264 | + cMacFromEeprom[0] &= 0xfe; |
| 265 | + while (return_status) { |
| 266 | + return_status = nvmem_set_mac_address(cMacFromEeprom); |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + ucStatus_Dr = 1; |
| 271 | + Serial.println(F("Writing driver patch")); |
| 272 | + |
| 273 | + while (ucStatus_Dr) { |
| 274 | + //writing driver patch to EEPRROM - PROTABLE CODE |
| 275 | + // Note that the array itself is changing between the different Service Packs |
| 276 | + ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, drv_length, wlan_drv_patch); |
| 277 | + } |
| 278 | + |
| 279 | + |
| 280 | + Serial.println(F("Wrote driver patch")); |
| 281 | + |
| 282 | + Serial.println(F("Starting w/o patches")); |
| 283 | + |
| 284 | + //if (!cc3000.begin(2)) |
| 285 | + //{ |
| 286 | + // Serial.println(F("Unable to initialise the CC3000! Check your wiring?")); |
| 287 | + // while(1); |
| 288 | + //} |
| 289 | + |
| 290 | + Serial.println(F("Writing firmware")); |
| 291 | + |
| 292 | + unsigned char ucStatus_FW = 1; |
| 293 | + |
| 294 | + while (ucStatus_FW) { |
| 295 | + //writing FW patch to EAPRROM - PROTABLE CODE |
| 296 | + //Note that the array itself is changing between the different Service Packs |
| 297 | + ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, fw_length, fw_patch); |
| 298 | + } |
| 299 | + |
| 300 | + Serial.println(F("Starting w/patches")); |
| 301 | + |
| 302 | + if (!cc3000.begin(0)) |
| 303 | + { |
| 304 | + Serial.println(F("Unable to initialise the CC3000! Check your wiring?")); |
| 305 | + while(1); |
| 306 | + } |
| 307 | + Serial.println(F("Patched!")); |
| 308 | + displayFirmwareVersion(); |
| 309 | + displayMACAddress(); |
| 310 | +} |
| 311 | + |
| 312 | + |
| 313 | +//***************************************************************************** |
| 314 | +// |
| 315 | +//! fat_write_content |
| 316 | +//! |
| 317 | +//! \param[in] file_address array of file address in FAT table:\n |
| 318 | +//! this is the absolute address of the file in the EEPROM. |
| 319 | +//! \param[in] file_length array of file length in FAT table:\n |
| 320 | +//! this is the upper limit of the file size in the EEPROM. |
| 321 | +//! |
| 322 | +//! \return on succes 0, error otherwise |
| 323 | +//! |
| 324 | +//! \brief parse the FAT table from eeprom |
| 325 | +// |
| 326 | +//***************************************************************************** |
| 327 | +uint8_t fat_write_content(uint16_t *file_address, uint16_t *file_length) |
| 328 | +{ |
| 329 | + uint16_t index = 0; |
| 330 | + uint8_t ucStatus; |
| 331 | + uint8_t fatTable[48]; |
| 332 | + uint8_t* fatTablePtr = fatTable; |
| 333 | + uint8_t LS[3] = "LS"; |
| 334 | + |
| 335 | + // first, write the magic number |
| 336 | + ucStatus = nvmem_write(16, 2, 0, LS); |
| 337 | + |
| 338 | + for (; index <= NVMEM_RM_FILEID; index++) |
| 339 | + { |
| 340 | + // write address low char and mark as allocated |
| 341 | + *fatTablePtr++ = (uint8_t)(file_address[index] & 0xff) | _BV(0); |
| 342 | + |
| 343 | + // write address high char |
| 344 | + *fatTablePtr++ = (uint8_t)((file_address[index]>>8) & 0xff); |
| 345 | + |
| 346 | + // write length low char |
| 347 | + *fatTablePtr++ = (uint8_t)(file_length[index] & 0xff); |
| 348 | + |
| 349 | + // write length high char |
| 350 | + *fatTablePtr++ = (uint8_t)((file_length[index]>>8) & 0xff); |
| 351 | + } |
| 352 | + |
| 353 | + // second, write the FAT |
| 354 | + // write in two parts to work with tiny driver |
| 355 | + ucStatus = nvmem_write(16, 24, 4, fatTable); |
| 356 | + ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); |
| 357 | + |
| 358 | + // third, we want to erase any user files |
| 359 | + memset(fatTable, 0, sizeof(fatTable)); |
| 360 | + ucStatus = nvmem_write(16, 16, 52, fatTable); |
| 361 | + |
| 362 | + return ucStatus; |
| 363 | +} |
| 364 | + |
| 365 | + |
| 366 | +void loop(void) |
| 367 | +{ |
| 368 | + delay(1000); |
| 369 | +} |
0 commit comments