I’m using an Adafruit WINC1500 WiFi Shield for Arduino as part of a project based on a NXP Freedom ARM board. These have Arduino compatible headers so that shields such as the wifi shield can be added to a freedom board using only the two parallel SIL headers (not the 6-pin SPI header). The jumpers had been soldered to route the SPI comms to the Digital 10,11,12,13 pins.

I had found the sources for the WiFi driver code as part of the ASF3.0 and ported this to the NXP ARM. With successful SPI communications between the ARM and the WiFi module it then errored out with a firmware version mismatch. The firmware on the WiFi module was several versions too old for the driver sources. The challenge now was to update the firmware on the WiFi shield in the WINC1500 module. Now the Arduino IDEs contain sketches and a firmware update tool plugin, so the obvious route is to use an Arduino board to do the firmware updating of the shield. We had an Arduino Uno handy that had the right headers.

The following is carried out using Arduino IDE 1.8.19. The version 2.0 IDE firmware updater tool won’t accept the Uno as a supported board.

The CheckWifi101FirmwareVersion sketch produced the following output:

WiFi101 firmware check.

Firmware version installed: 19.5.2
Latest firmware version available : 19.6.1

Check result: NOT PASSED
 - The firmware version on the shield do not match the
   version required by the library, you may experience
   issues or failures.

Loading and compiling the FirmwareUpdater sketch threw errors regarding the available memory on the Uno. One change is necessary, to reduce the max payload size to 256 bytes:

static const int MAX_PAYLOAD_SIZE = 256;

Exploring the code and listening in on the serial comms shows that the PC updater tool queries the Uno for max payload size and uses this when transferring the flash binary.

This worked for getting the code onto the Uno but when “Test connection” was tried in the firmware updater it failed to get the hello message response back.

Searching on various forums showed plenty of other people facing the same issue:

I wrote a Python script to send the hello message to the FirmwareUpdater sketch running on the Aruino Uno to test basic comms. It kept failing, and then I remembered a colleague had mentioned that you needed a delay after opening the comm port on the PC before you could communicate with the Arduino.

I then discovered that Arduinos restart when the COM port is opened. Possibly the DTR line from the USB-Serial converter is connected to the reset pin. On the lower end AVR based Arduinos this restart process will likely be longer than for a faster ARM based Arduino. So adding a delay after opening the serial port in the Python code then allowed the hello messages to reach the Arduino Uno and for the correct “v10000” response to be sent back to the PC.

So the theory was that the Firmware Updater tool in the IDE wasn’t giving sufficient delay after opening the COM port to the Arudino before then sending the hello message.

At this point I was developing on hardware that was sat in the lab, whilst I was remoting into the lab PC. So the hardware solution of cutting the link from DTR to reset wasn’t available to me. However, this would likely be the simplest solution. Another solution is for a software update to the Firmware Updater plugin to give sufficient delay for the restart of the Arduino before sending the first communications.

The software solution available to me at this stage is for the COM port to the Arduino to already be open ahead of the firmware updater tool connecting to it. So, using com0com a virtual null modem connection was created between two purely virtual COM ports (COM13 <-> COM14). And, a Python script was created to simply move bytes from one serial port to another, and vice-versa. With the Arduino UNO on COM10.

import serial
import time

with serial.Serial('COM10', 115200, timeout=1) as serUno:
    with serial.Serial('COM13', 115200, timeout=1) as serVirtual:
        time.sleep(2)  # wait for serial ports to initialise
        while (True):
            # Now read from each and send to the other
            while serVirtual.in_waiting > 0:
                b = serVirtual.read()
                print("PC-U:" + str(b))
            while serUno.in_waiting > 0:
                b = serUno.read()
                print("U-PC:" + str(b))

Running this script and then connecting the Firmware Updater tool to COM14 meant the Arudino Uno was already up and running when the hello message was sent from the IDE. With sucessful response then received by the programmer. The Update firmware was then selected: WINC1501 Model B (19.6.1) (Arduino/Genuino MKR1000). And the firmware was successfuly written to the shield and verified by the updater tool.

Now running the CheckWifi101FirmwareVersion sketch produced the following output:

WiFi101 firmware check.

WiFi101 shield: DETECTED
Firmware version installed: 19.6.1
Latest firmware version available : 19.6.1

Check result: PASSED

So in conclusion an Arduino Uno can be used to update the firmware on a Adafruit WINC1500 WiFi Shield. Reduce MAX_PAYLOAD_SIZE to 256 and prevent the DTR from resetting the processor when the COM port is opened.

Update 2022-11-18

The Driver version on the K66 was 19.7.3 and this was still incompatible with the Firmware version 19.6.1.

The up to date firmware can be found at github.com/Microchip-MPLAB-Harmony/wireless_wifi. Using the winc_flash_tool.cmd script to generate an aio (all-in-one) raw binary (with the size set to 512K) produced the 19.7.7 binary m2m_aio_3a0_19_7_7.bin. To get the Ardunio Firmware Updater Tool to push this to the shield, this file was renamed and overwrote the existing 19.6.1 binary in the arduino-1.8.19/tools/WiFi101/tool/firmwares/WINC1500/19.6.1/ directory. The steps as above were used to push this to the shield and the output for CheckWifi101FirmwareVersion now shows:

WiFi101 firmware check.

WiFi101 shield: DETECTED
Firmware version installed: 19.7.7
Latest firmware version available : 19.6.1

Check result: PASSED