This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to deny a patch update?



I'm using this CC3000 module: http://www.digikey.ca/product-detail/en/CC3000MODR/296-35512-1-ND/3768439

When I first started writing software for the module (for STM32F429), I sent it HCI_CMND_SIMPLE_LINK_START with argument 0x00 (load patch from EEPROM) and it responded properly with HCI_EVNT_SIMPLE_LINK_START. Any commands after that would return 02 00 FF 00 00 for some reason. Recently the behaviour of the module changed. When I send it HCI_CMND_SIMPLE_LINK_START with argument 0x00 it responds with HCI_EVENT_PATCHES_FW_REQ and keeps the IRQ line pulled high indefinitely. If I try to send it a command while IRQ is high it responds with 02 00 FF 00 00 or 02 00 FA 00 00. According to this page: http://processors.wiki.ti.com/index.php/CC3000_HCI_PATCH_messages I can send the module a patch with length 0 to skip the update, but again, I'm unable to try this since IRQ stays high. Why is my module requesting a patch update all of the sudden and how can I make IRQ go low so I can continue sending commands?

The next thing I tried was to send HCI_CMND_SIMPLE_LINK_START with argument 0x02 (don't load patches) to which the module responded with HCI_EVNT_SIMPLE_LINK_START. However, the IRQ line is still pulled high indefinitely after that. What's going on here? What should I try next? Most importantly, is it possible to 'brick' the module by uploading an incorrect patch? I'm avoiding writing a patch programmer for the time being because I'm scared that the module will become useless.

  • For some reason your EEPROM got corrupted. To fix it you need to re-patch it. First do the driver patch then the firmware patch.

  • >> For some reason your EEPROM got corrupted

    I thought so too at first. Looks like I should have RTFM. Turns out I had my IRQ and CS timing mixed up, as people in threads dealing with similar problems had mentioned. For some reason I assumed I had the CS and IRQ figured out and didn't even bother checking it. Now I can fully initialize the CC3000 (HCI_CMND_SIMPLE_LINK_START and HCI_CMND_READ_BUFFER_SIZE) as long as I send HCI_CMND_SIMPLE_LINK_START with argument 0x02. Otherwise, the module still requests a firmware update.

  • Hi Ivan,
    this behaviour sounds as you have only patched the driver part and not yet the firmware part.

    See here: http://processors.wiki.ti.com/index.php/CC3000_Patch_Programmer

    Cheers,
    Risto

  • I can't find much information on the low level commands used for patching. If I understand correctly, I need to first send HCI_CMND_SIMPLE_LINK_START with argument 2, then send HCI_CMND_NVMEM_CREATE_ENTRY to create an 8024 byte entry in file ID 4 (driver patch), and finally send HCI_DATA_NVMEM_WRITE with the entire 8024 byte patch. Is this even remotely correct?

    I've already tried sending HCI_CMND_NVMEM_CREATE_ENTRY, but there is no documentation on the return event. Here is what the cc3000 returned: 02 00 00 00 05 04 03 02 01 00

  • Hi Ivan,
    here's bidirectional SPI communication capture of TI's original PatchProgrammer_DR for EXP-MSP430FR5739 board (HCI_CMND* is sent on MOSI line, HCI_EVNT* on MISO):

    HCI_CMND_SIMPLE_LINK_START, Argument 0x02 instead of standard 0x00, with 50us pause after first 4 bytes.
    HCI_EVNT_SIMPLE_LINK_START
    HCI_CMND_READ_BUFFER_SIZE
    HCI_EVNT_READ_BUFFER_SIZE
    HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: 'T', 'T', 'T'
    HCI_EVNT_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX
    HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: 0,0,0
    HCI_EVNT_WLAN_IOCTL_SET_CONNECTION_POLICY
    HCI_CMND_WLAN_IOCTL_DEL_PROFILE: 0x000000FF (delete all profiles)
    HCI_EVNT_WLAN_IOCTL_DEL_PROFILE
    HCI_CMND_EVENT_MASK: 0x8244
    HCI_EVNT_EVENT_MASK

    Read and temporarily store the MAC Address:
    HCI_CMND_NVMEM_READ: NVMEM_MAC_FILEID(=0x06)
    HCI_EVNT_NVMEM_READ
    HCI_DATA_NVMEM (Arguments length=0x18)

    Read in and temporarily store the Radio Module (RM) parameters (File ID 11) in 16 8-byte (together 128 bytes) chunks (in order to work with tiny driver):
    16 times, offset incremented by 8 at each consequent iteration:
    HCI_CMND_NVMEM_READ: NVMEM_RM_FILEID=(0x0B=11)
    HCI_EVNT_NVMEM_READ
    HCI_DATA_NVMEM (Arguments length=0x18)

    Write new File-Allocation-Table (FAT) into NVMEM/EEPROM:
    HCI_DATA_NVMEM_WRITE: NVMEM_MAX_ENTRY, offset=0, 2 bytes 0x4C, 0x53, first, write the magic number 0x4C, 0x53 ("LS")
    HCI_EVNT_NVMEM_WRITE
    Second, write the FAT contents in two 24-byte parts to work with tiny driver. This vector is a constant, defined in top of main source file in PatchProgrammer_DR source code.
    HCI_DATA_NVMEM_WRITE: NVMEM_MAX_ENTRY, offset 4, 24b(16b args)
    HCI_EVNT_NVMEM_WRITE
    HCI_DATA_NVMEM_WRITE: NVMEM_MAX_ENTRY, offset 28=0x1C, 24b(16b args)
    HCI_EVNT_NVMEM_WRITE
    Third, erase any user files starting from AES128 for smart config (4 entries, 4 bytes each). Write 0x00 there.
    HCI_DATA_NVMEM_WRITE, NVMEM_MAX_ENTRY, offset 52=0x34, 16b (16b args)
    HCI_EVNT_NVMEM_WRITE

    Write back the Radio Module (RM) parameters read out previously. Write happens in 4x 32-byte chunks (in order to work with tiny driver).
    HCI_DATA_NVMEM_WRITE, NVMEM_RM_FILEID, 32 bytes
    HCI_EVNT_NVMEM_WRITE
    HCI_DATA_NVMEM_WRITE, NVMEM_RM_FILEID, offset 32, 32b
    HCI_EVNT_NVMEM_WRITE
    HCI_DATA_NVMEM_WRITE, NVMEM_RM_FILEID, offset 64, 32b
    HCI_EVNT_NVMEM_WRITE
    HCI_DATA_NVMEM_WRITE, NVMEM_RM_FILEID, offset 96, 32b
    HCI_EVNT_NVMEM_WRITE

    Write back the MAC address read out previously:
    HCI_DATA_NVMEM_WRITE, NVMEM_MAC_FILEID
    HCI_EVNT_NVMEM_WRITE

    Write the driver patch. V1.12 Patch has 8076 bytes (The contents of patch (the 8076 byte vector/array) is defined in the main source file of PatchProgrammer_DR source code):
    Write in chunks of 32 bytes (252 times). Remainder 8076-252*32=12 bytes will be written separately:
    HCI_DATA_NVMEM_WRITE, NVMEM_WLAN_DRIVER_SP_FILEID, 32b
    HCI_EVNT_NVMEM_WRITE
    Write the remainder:
    HCI_DATA_NVMEM_WRITE, NVMEM_WLAN_DRIVER_SP_FILEID, offset
    HCI_EVNT_NVMEM_WRITE

    Turn WLAN_SW_EN low.
    Wait.
    Turn WLAN_SW_EN back up. This triggers CC3000 to restart.

    HCI_CMND_SIMPLE_LINK_START, Argument=0x00
    HCI_EVNT_PATCHES_REQ, Argument1=0x02, Unsolicited incoming event from CC3000, requests Firmware patches, as driver is now finished
    As DR (driver) Patch does not include any firmware patch, it answers with 0:
    HCI_EVENT_PATCHES_FW_REQ

    Normal start continued:
    HCI_EVNT_SIMPLE_LINK_START
    HCI_CMND_READ_BUFFER_SIZE
    HCI_EVNT_READ_BUFFER_SIZE
    HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: 'T', 'T', 'T'
    HCI_EVNT_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX
    HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: 0,0,0
    HCI_EVNT_WLAN_IOCTL_SET_CONNECTION_POLICY
    HCI_CMND_WLAN_IOCTL_DEL_PROFILE: 0x000000FF (delete all profiles)
    HCI_EVNT_WLAN_IOCTL_DEL_PROFILE
    HCI_CMND_EVENT_MASK: 0x8244
    HCI_EVNT_EVENT_MASK

    Cheers,
    Risto

  • You should always first patch the driver, then the firmware.

    The PatchProgrammer_FW (firmware patch) is similar to driver patch, but little bit simpler as it does not need to backup and restore the MAC nor the Radio Parameters.

    Here's the capture:

    HCI_CMND_SIMPLE_LINK_START=0x4000, 50us pause after first 4 bytes.
    HCI_EVNT_PATCHES_REQ=0x1000, Argument1=0x02, Unsolicited incoming event from CC3000, requests Firmware patches, as driver patch is finished, but the version of the firmware is still old (assuming driver was already patched before).
    As the PatchProgrammer_FW update code is written to use HCI_DATA_NVMEM_WRITE instead of answering to this event, the PatchProgrammer_FW answers to HCI_EVNT_PATCHES_REQ with 0:
    HCI_PATCH, 0

    Normal start continued:
    HCI_EVNT_SIMPLE_LINK_START
    HCI_CMND_READ_BUFFER_SIZE=0x400B
    HCI_EVNT_READ_BUFFER_SIZE=0x400B
    HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX='T', 'T', 'T'
    HCI_EVNT_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX
    HCI_CMND_EVENT_MASK=0x0008 0x8244
    HCI_EVNT_EVENT_MASK

    Write the firmware patch. For V1.12 the patch is 5700 bytes long. Write in 32 byte chunks. 178 chunks, plus remainder 5700-178*32 = 4 bytes. The 5700 byte long patch vector/array is defined in the main source file in the PatchProgrammer_FW source code.
    Repeat following 178 times:
    HCI_DATA_NVMEM_WRITE=0x90, NVMEM_WLAN_FW_SP_FILEID=5
    HCI_EVNT_NVMEM_WRITE=0x0202

    Write the remainder:
    HCI_DATA_NVMEM_WRITE=0x90, offset
    HCI_EVNT_NVMEM_WRITE=0x0202

    Turn WLAN_SW_EN low.
    Wait.
    Turn WLAN_SW_EN back up. This triggers CC3000 to restart.

    HCI_CMND_SIMPLE_LINK_START, Argument=0x00
    HCI_EVNT_SIMPLE_LINK_START
    HCI_CMND_READ_BUFFER_SIZE
    HCI_EVNT_READ_BUFFER_SIZE
    HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: 'T', 'T', 'T'
    HCI_EVNT_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX
    HCI_CMND_EVENT_MASK: 0x8244
    HCI_EVNT_EVENT_MASK

    Cheers,
    Risto

  • Thank you for the capture, I'm now slowly implementing this. However, I'm having trouble with the first NVMEM read:

    Read and temporarily store the MAC Address:
    HCI_CMND_NVMEM_READ: NVMEM_MAC_FILEID(=0x06)
    HCI_EVNT_NVMEM_READ
    HCI_DATA_NVMEM (Arguments length=0x18)

    HCI_EVNT_NVMEM_READ returns with a status of 0x03, which is undocumented. The HCI_DATA_NVMEM returns as expected, but with a bogus MAC address which changes every time I read it and some other unexpected data (0x03 0x10). Here is the full output starting with HCI_CMND_NVMEM_READ:

    > 01 00 11 00 00 01 01 02 0C 06 00 00 00 06 00 00 00 00 00 00 00 00
    < 02 00 00 00 05 04 01 02 01 03
    < 02 00 00 00 23 02 91 18 1E 00 06 00 00 00 06 00 00 00 00 00 00 00 03 10 00 00 00 00 00 00 00 00 00 00 EC DE 71 04 D4 60

  • Hi Ivan,

    It looks like your MAC address is corrupted inside the EERPOM. You need to write a new one before you can read it successfully.

    This step is not required for a successful driver and firmware patch. It can be performed later.

  • Ok, I stopped messing around trying to write my own code and ported the patch programmer for my MCU. However the patch programmer is still unable to write the patches correctly it seems. First I ran the WLAN driver patch programmer, which failed at initDriver(0) after writing the patch. As expected, when initializing with argument 0, the CC3000 requested a FW patch update. The program then hit this peice of code:

    case HCI_EVENT_PATCHES_FW_REQ:
    
    		if (tSLInformation.sFWPatches)
    		{
    			patch = tSLInformation.sFWPatches(&ucLength);
    
    			// Build and send a patch
    			if (patch)
    			{
    				hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, 
    					tSLInformation.pucTxCommandBuffer, patch, ucLength);
    				return;
    			}
    		}
    
    		// Send 0 length Patches response event
    		hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
    			tSLInformation.pucTxCommandBuffer, 0, 0);
    		break;

    which supposedly wrote the firmware patch, but the problem still persists. I tried running the firmware patch programmer too, but it gets stuck at the first line, which is initDriver(0); same problem. After supposedly writing the firmware patch, both programs get stuck in hci_event_handler waiting for HCI_EVENT_SIMPLE_LINK_START.

  • Hi Ivan,

    to make the story short: There are 3 defines

    #define SL_PATCHES_REQUEST_DEFAULT        (0)
    #define SL_PATCHES_REQUEST_FORCE_HOST    (1)
    #define SL_PATCHES_REQUEST_FORCE_NONE    (2)

    The one with value 1 is the obsolete case. Comment out SL_PATCHES_REQUEST_FORCE_HOST and check if you can compile. If not, you are using old sources. Please download latest patch programmer sources and compare them with your used sources.

    You can search the forum for SL_PATCHES_REQUEST_FORCE_HOST to find more detailed explanations.

    Best regards,

    Martin

  • Hi Ivan,
    as you wrote that by reading out the MAC you get different values read out every time, I am assuming, as Ivor already wrote as well, that your EEPROM is corrupt, or at least the File-Allocation-Table in EEPROM is not valid. In this case, you probably also do not have any valid Radio Parameters anymore. It might be that while porting the PatchProgrammer to other platform, you did a mistake and wiped all or parts of the EEPROM contents.

    Maybe someone from TI can clarify if all CC3000 modules are shipped with same radio parameters? If this is the case, you could read them out from other CC3000 (or we can provide you the vector/array here in forum) and you can write new FAT and write the RM section bluntly back to your CC3000. If although the radio parameters in EEPROM are unique to each CC3000, then I guess they are lost for your CC3000 and you might need to get a replacement CC3000 to experiment further.

    Cheers,
    Risto

  • I commented out #define SL_PATCHES_REQUEST_FORCE_HOST    (1), but that had no effect on the problem. Then, while looking through some of the threads on SL_PATCHES_REQUEST_FORCE_HOST I discovered that one person just changed initDriver(0) to initDriver(2) and it worked for him. Just tried that and it worked for me too. Even if I change it back to initDriver(0) now, it works. If the firmware patch works when initialized with initDriver(2) then why does the stock patch programmer (version 1.13.7.15.28) initialize with initDriver(0)? Just seems like it could (and did) cause unnecessary trouble.

    @Risto I'm assuming that if the FAT and other data is wiped I'll have problems using the module. I'm currently writing a simple program to connect to the internet as a test to see if the patching worked or if anything else is broken. I'll post results shortly.

  • @Risto

    As far as I can remember the patch programmer has default radio module parameter in its source code
     which are used when the block cannot be read. Search for

    "cRMdefaultParams"

  • Hi Martin,
    you are perfectly correct, the PatchProgrammer_DR_Patch.c includes default Radio Module parameters (128-byte long vector/array).

    This is great news for Ivan, as in his case when the EEPROM contents is messed up, he only needs to apply valid MAC address using API-calls and his CC3000 should be back operational.

    Cheers,
    Risto

  • Does anyone actually have a very simple program to connect to an AP, then connect to the internet and download a webpage? I don't have a clue where to begin as usual :) I tried

    initDriver(0);
    result = wlan_connect(WLAN_SEC_WPA2, WLAN_SSID, 9, NULL, WLAN_KEY, 5);

    but wlan_connect returns 0 (success) no matter what the SSID and key...

    Also I don't get an HCI_EVNT_WLAN_UNSOL_CONNECT event as I should.

  • For me the best place to begin was the Basic WiFi Application. You should start with connecting to an open AP, then an AP with WPA2. Only then you should look into connecting to a web server.

    Small steps! :)

  • Have you called wlan_init and wlan_start before wlan_connect?

  • Hi Ivan,
    After you have verifyied AP-connectivity with TI's BasicWifiApplication, you could have a look at Adafruit CC3000 library here: https://learn.adafruit.com/adafruit-cc3000-wifi/cc3000-library-software

    They show numerous WebClient and Server examples. Although Adafruit code is for Arduino, the underlying hostdriver API-calls are the same as in original TI CC3000HostDriver.

    Cheers,
    Risto

  • I ported the smartConfig part of the Basic WiFi application, and the function StartSmartConfig() returns indicating a successful connection. However, wlan_ioctl_statusget() returns 0 (disconnected) and netapp_ipconfig(&ipConf) also returns all zeros, indication no connection. This is really driving me nuts.

    EDIT: I put wlan_ioctl_statusget() and netapp_ipconfig(&ipConf) in a loop that prints to a terminal and I can see that the module is actually trying to connect and then giving up. When it's trying to connect wlan_ioctl_statusget() returns 2 (connecting) and the SSID returned by netapp_ipconfig(&ipConf) is correct. Everything else is still 0.

    EDIT 2: Ok, now it works for some reason. wlan_ioctl_statusget() returns 3 (connected) and netapp_ipconfig(&ipConf) returns all the right info

  • Hi Ivan,


    It takes time for the CC3000 to connect to an AP and get an IP address. The recommend thing to do is listen to the HCI_EVNT_WLAN_UNSOL_CONNECT and HCI_EVNT_WLAN_UNSOL_DHCP events. Once you get them both you are properly connected to the Internet.

  • Yes, I'm aware. It's just that the first 10 or so times I ran the program I didn't receive either event after waiting at least 30 seconds. I don't know if I changed anything after that, but now it connects in a few seconds.

    As expected, I'm not having much luck getting further. The next step I suppose is pinging the AP which I did like this:

    uint32_t remoteIp = 0xc0a801fe;//192.168.1.254
    result = netapp_ping_send(&remoteIp, 4, 32, 1000);

    I never receive HCI_EVNT_WLAN_UNSOL_PING_REPORT as I'm supposed to. I've tried calling netapp_ping_report() to force a ping report, but that didn't work either. If I log into the AP and ping the CC3000 from there, it responds back, so it's not a connection issue.

  • Make sure the HCI_EVNT_WLAN_ASYNC_PING_REPORT event is not masked through wlan_set_event_mask(...), which is the default situation in the Basic WiFi Application for some reason. Once you can receive it you should handle it like this:

    ...

        else if (lEventType == HCI_EVNT_WLAN_ASYNC_PING_REPORT)
        {
            netapp_pingreport_args_t* report = (netapp_pingreport_args_t*)data;
            if (report->packets_received > 0)
            {
                // Flash some LEDs or something
            }
        }

    ...

  • Hi Ivan,
    attached is a communication capture of pinging with CC3000.

    Cheers,
    Risto

  • Doh, I should have checked what was being masked out. I guess that's the problem with not writing my own code; I don't notice small things like this.

    It still didn't work the first time though, as netapp_ping_send apparently requires the ip in little endian. Once I switched that around, I got results similar to Risto's; more packets were sent than requested. In my case, I asked to send 4 packets, but got this back from HCI_EVNT_WLAN_ASYNC_PING_REPORT: 7 sent, 2 received. Risto had 8 sent, 4 received when pinging with 4 packets. I tried again with 40 packets and got 79 sent, 38 received. Not a particularly important issue, but strange for sure.

    Thank you to everyone who has helped me get up to this point. On my own, it would have taken months to figure out how to connect to an AP, let alone the rest of the internet.

  • Hi Ivan,
    great that you got it working! The wrong number of packets sent in the CC3000 PING report is a bug in CC3000 firmware (last I checked with v1.12). On the Wireshark capture I always see the correct number of ICMP packets I told CC3000 to send out, so I am assuming only the report of CC3000 is wrong.

    Cheers,
    Risto