One of the key challenges creating the WICED Feather is that it is based on the Broadcom WICED WiFi stack, and due to the license terms we're unable to release any of the source files.
This poses a bit of a dilemma since we tested almost every embedded WiFi stack out there, and WICED easily climbed to the top in terms of features, performance and reliability. We want that reliability and speed, but we also want to make sure customers have the flexibility to bring all kind of projects to life as well, without having to sign restrictive license agreements themselves.
So how do we make this available to customers in a way they can use in the real world, without signing NDAs themselves?
The answer wasn't obvious at first, but FeatherLib was the end result of a lot of head scratching and firmware dead ends.
The proprietary Broadcom WICED WiFi stack is designed around an RTOS (Real Time Operating System), which handles all of the various tasks involved in WiFi, such as async data requests, security and cryptography, etc. (If you're not familiar with them, an RTOS breaks tasks into 'threads', and then shares MCU cycles between those threads, allowing you to effectively multi-task on a single MCU.)
The RTOS and all of the proprietary Broadcom WiFi stack and code runs behind the scenes in a binary black box we call the FeatherLib (see the Flash Memory Layout section below for details). By providing a binary black box, we solve the legal hurdles of working with WICED, but this still leaves the problem of exposing the WiFi functionality to end user.
We solved this by essentially 'wrapping' every useful function in the WICED stack with a custom command (using an in house protocol called SDEP), and then routing these commands between the Broadcom SDK in FeatherLib and end users. We can freely expose the source related to the SDEP commands (since we wrote 100% of it), while still hiding the proprietary Broadcom functions, header files and structs. The lawyers are happy, and hopefully our customers are too!
By basically reimplementing the entire Broadcom WICED WiFi stack with a new set of SDEP commands and a more focused custom API, you get access to Broadcoms high quality stack, without any of the legal headaches. The headaches were all on our side reimplementing the wheel just to solve a legal problem. :)
This left the problem of how to allow users to write code themselves that talks to FeatherLib via SDEP.
Since FeatherLib runs on an RTOS, we start a single RTOS 'thread' at startup that is used for the user code. FeatherLib will start the Broadcom WiFi stack, and as part of that process it also start the 'user code' thread that runs the custom code that you write and compile in the Arduino IDE.
This custom user code is built in the Arduino IDE like you would for any other MCU, and gets written into a dedicate section of flash memory with it's own chunk of SRAM reserved purely for the user code in Arduino land.
This setup allows you to share the MCU processing time between your own code and the lower level WiFi stack, but the process should normally be invisible to you, and you never really need to worry about the FeatherLib black box.
Communication between the user code and the Feather lib happens via an in-memory messaging system, sending and receiving commands using a custom protocol we call SDEP (Simple Data Exchange Protocol).
An SDEP command is sent to the Feather lib, and a standard response is sent back and interpretted, allowing the two binary blobs to exist entirely independent of each other, and be updated separately.
You normally never need to deal with SDEP commands directly since the commands are all hidden in the public WICED Feather helper classes (AdafruitFeather, AdafruitHTTP, etc.). These helper classes and functions send the SDEP commands for you, and convert the responses into meaningful data.
There is a special AdafruitSDEP helper class that allows you to send SDEP commands directly if the need does every arise, though, and the SDEP commands are all documented elsewhere in this learning guide.
To keep things as simple as possible, and to make updates easy, the flash-memory and SRAM on the STM32F205 MCU is broken up into several Sections, as shown in the diagram below.
Keeping the sections independent allows you to update the user code without having to recompile and reflash the rest of the system, significantly speeding up build and write times.
Your own code ('User Code') will be compiled directly by the Arduino IDE, and has access to 256KB of flash and 20KB of SRAM.
The low level WiFi stack from Broadcom ('Feather Lib') is provided as a single pre-compiled .hex file that gets flashed to a dedicated location in flash memory on the STM32F205 MCU. Because most of the heavy lifting is done here, it has access to most of the flash and SRAM.
Two identical sets of non-volatile config data are stored in this section, and when any changes are made the bank used is switched to make sure that no data is lost during the updates. Normally you will never access this memory directly, and this is managed by the Feather Lib.
This code runs as soon as your device powers up and starts the Feather Lib, and also checks if any User Code is available.
This is what allows you to update the User Code or Feather Lib using USB DFU.
The bootloader code itself can be updated from the Arduino IDE as well, but it requires you have either a Segger J-Link or an STLink/V2 connected to the SWDIO and SWCLK pins on the WICED Feather, and you will normally never need to update the bootloader yourself.
The WICED Feather enumerates several USB classes, depending on the operating mode that the board is in.
When the WICED Feather is in DFU mode (which you can detect thanks to a fast, constant rate blinky on the LED), the following USB classes are available:
- DFU - Allows you to update the firmware on your board using dfu-util
When running in DFU mode the WICED Feather enumerates with the following VID/PID values:
- VID: 0x239A
- PID: 0x0008
When the WICED Feather is running in normal operating mode, meaning it is running user code, three USB classes are enumerated:
- WICED Feather Dummy: Allows SDEP commands to be sent to the WICED Feather using the USB control endpoint (to force a reset, change operating modes, etc.). Note that this is actually just a work around to gain access to the USB control transfer endpoint with libusb since we can't access control transfers directly, ergo the name 'Dummy'.
- Serial Monitor CDC: This USB CDC class is used to handle Serial Monitor input and output
- AT Parser CDC: This (currently unused) USB CDC class enumerates for future expansion and currently exposes an AT Parser with a very limited set of commands, but may be repurposed for other uses in the future.
When running in normal operating mode, the WICED Feather will enumerate with the following VID/PID:
- VID: 0x239A
- PID: 0x0010
The WICED Feather also contains a currently unused 16 MBit (2MB) SPI Flash that will be enabled in a future firmware update. When the solder jumper on the bottom of the WICED Feather is enabled, an addition USB Mass Storage class will enumerate that points to the SPI flash. This feature is not yet enabled, but when enabled the WICED Feather will use the following VID/PID combination:
- VID: 0x239A
- PID: 0x8010
All flash updates happen using USB DFU. There is no serial bootloader on the WICED Feather and the USB CDC ports are not required to perform a firmware update.
To perform a firmware update, the 'Enter DFU Mode' SDEP command is sent to the WICED Feather using the WICED Feather Dummy endpoint, which will cause the device to reset into DFU mode. At this point, dfu-util will be used to update the flash contents of the chip with the appropriate firmware image.