Artemis Nano upload failed

I have a problem very similar to viewtopic.php?f=164&t=50373.

I have the Artemis Nano board and tried to connect a Spectral Sensor Breakout - AS7263 NIR with a Qwiic kabel and run the Example1_BasicReadings. For whatever reason this did not work and now the board constantly sends the string “I2C Error” to the serial port.

Disconnecting the Sensor and Reset did not change the situation and uploading new code fails.

I was also using the Ambiq Secure Bootloader because the SVL never worked for me.

The Sensor board and the Qwiic kabel I used are still working fine, I have checked this using a Thing Plus board.

Operating system is: MacOS 10.15.5

Arduino IDE is v1.8.9

Board Manager is Sparkfun Apollo3 Boards v1.0.4

Any ideas?

I just tried to burn a new bootloader according to this description: viewtopic.php?f=163&t=50480

This failed with the same error message as uploading regular code:

Header Size = 0x80

original app_size 0x2708 ( 9992 )

load_address 0xc000 ( 49152 )

app_size 0x2708 ( 9992 )

w0 = 0xcb002788

Security Value 0x10

w2 = 0x10008080

addrWord = 0xc000

versionKeyWord = 0x0

child0/feature = 0xffffffff

child1 = 0xffffffff

crc = 0x6442ad39

Writing to file /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_OTA_blob.bin

testing: /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_OTA_blob.bin

Header Size = 0x60

app_size 0x2788 ( 10120 )

Writing to file /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_Wired_OTA_blob.bin

Image from 0x0 to 0x2788 will be loaded at 0x20000

Connecting over serial port /dev/cu.wchusbserial1410…

Fail

Fail

Fail

Tries = 3

Upload failed

Header Size = 0x80

original app_size 0x2708 ( 9992 )

load_address 0xc000 ( 49152 )

app_size 0x2708 ( 9992 )

w0 = 0xcb002788

Security Value 0x10

w2 = 0x10008080

addrWord = 0xc000

versionKeyWord = 0x0

child0/feature = 0xffffffff

child1 = 0xffffffff

crc = 0x6442ad39

Writing to file /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_OTA_blob.bin

testing: /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_OTA_blob.bin

Header Size = 0x60

app_size 0x2788 ( 10120 )

Writing to file /Users/asprenger/Library/Arduino15/packages/SparkFun/hardware/apollo3/1.0.4/bootloaders/artemis/artemis_svl_Wired_OTA_blob.bin

Image from 0x0 to 0x2788 will be loaded at 0x20000

Connecting over serial port /dev/cu.wchusbserial1410…

Fail

Fail

Fail

Tries = 3

Upload failed

asprenger, glad you got the code uploaded at least. I do have some ideas for you to investigate more:

  1. I2C Error - right now the Wire library may return some non-standard codes even when things are working alright. Maybe the sensor library is being particularly picky about what comes back? The first example is simplified so much that it is obscuring the problem and will require looking deeper into the code.

  2. For the bootloader… Are you uploading to an Edge board? What baud rate were you using for your Ambiq Secure Bootloader before? Arduino is set up to use the ASB to program the new SVL onto the boards, so you need to make sure that the baud rate is set correctly. It is an OK sign that the bootloader fails with the same error as normal code, because the SVL is just normal code being uploaded by the ASB, and the ASB has not changed in a couple months. Finally, maybe when you installed v1.0.4 of the Arduino core the default baud settings that you were using may have been overwritten. Try changing the ASB and/or the SVL baud rates from the tools menu of Arduino.

Keep me posted! I want to make sure this gets working.

The board is an Artemis Nano, not the Edge board.

At the moment no sensor is connected to the board. The board is probably still running the Example1_BasicReadings code. The Serial Monitor from the Arduino IDE outputs "I2C Error

" in rapid succession.

I have used the ASB with 921600 baud to upload the Example1_BasicReadings code.

To get the board back in a working state I tried to upload the Blink example with all available baud rates and I tried to burn the new bootloader according to viewtopic.php?f=163&t=50480 again with all available baud rates. All of this failed with “Upload failed”.

At the moment the board is bricked. The first priority would be to get it back to a state where new code can be loaded. Getting the sensor working is second.

Alright thanks for the extra information. I am confused by this: “I have used the ASB with 921600 baud to upload the Example1_BasicReadings code.”

The reason is that none of the Artemis boards should be able to use the Ambiq Secure Bootloader at 921600 baud - they have all been programmed here to use 115200 as the ASB baud.

Still, the problem remains. So I just used my Artemis Blackboard to try and recreate the problem. I used “Serial.begin()” (with 9600 and 115200 baud) in setup and “Serial.print(“I2C Error\n”);” as the only line in the loop. I uploaded the code using the ASB (at 115200 baud rate – there is no menu option for Artemis boards ASB rate) and then tried to upload code modified with a “delay(1000);” line added to the loop. With the Serial port spitting out a lot of information the ASB was not reliable, but I was able to observe it successfully bootload a couple times.

I know this is not an acceptable solution but how many times have you tried to upload the new code? Also I’m curious since you are using Linux whether you’ve installed the patched drivers by Juliagoda? (This was a solution to upload problems on the Edge board that had the ASB configured for 921600 baud bc default Linux CH340C drivers could not accurately generate that high baud rate)

I’m going to dive into the ASB Python script and see if I can’t find a solution.

Thanks for your help, I appreciate it!

I’m on MacOS, not Linux (I said so in my first message)

I have just tried to upload the Blink example about 20 times but they all failed.

I took screenshots so you can see the configuration, I hope this makes it clear.

The code that is currently running on the board writes about 170 messages/s to the serial port.

Maybe some other idea. You said from your experiments you learned that the upload works from time to time. From the console output it looks like the upload has a retry configured to 3. Can I change this to a higher value? I don’t mind to let it retry for a couple of hours.

Good idea - I actually have another (temporary) solution for you that I just need to work out the details of. Waiting for confirmation by the engineer for the Artemis module about one thing.

Sorry about thinking you were on Linux – I thought I had seen a path in your debug messages that said ‘tools/artemis/linux’. I have been seeing a lot of these lately!

Hold tight for a moment and I’ll get back to you

Addtl info: I just noticed that sometimes when the ASB fails the board would be left in a state where code was not executing – this is what allowed the next upload to complete.

This confirms my suspicions that this is related to the large amount of Serial traffic. That means two things:

  1. There is probably a way to fix this in Python

  2. You can ensure a good upload if only you have access to the ‘Boot’ pin on the Artemis module.

I’ll work on solution #1, but if you want to get your board working right now you should be able to do this:

  1. Identify the ‘Boot’ pin trace on the Artemis Nano (highlighted in this photo – bottom side of Nano)

  1. Solder a wire to the 3.3V source on your Nano

  2. Force the Nano into ASB bootloader by touching ‘Boot’ with the 3.3V while pressing reset.

  3. Keep 3.3V on the ‘Boot’ line as you use the ASB loader (or you use ‘Burn Bootloader’)

  4. Code should upload successfully. You may need to manually trigger a reset the first time after removing the 3.3V from ‘Boot’

Resetting the board with 3.3V on the ‘Boot’ pin signifies that it should enter the ASB. That should quiet down the Serial port, and then uploading a second time will trigger another reset. Keeping 3.3V on the boot pin just makes sure that the Nano does not ever go to App execution and start flooding Serial data. When the upload is complete you will still have 3.3V on Boot so the boad will go back to ASB bootloader mode on reset. That’s why you might need one more reset (manually, without 3.3V on the boot line)

I’m still planning to look into a better solution, but this should make it possible for you to recover the board.

Thanks for the details description. I’m sure many users here could do this in 20 sec but unfortunately I do not have the right equipment and not the right skills to do this. I would quite likely destroy the board. So maybe I wait and see if you can come up with a software solution.

I took a look into the upload script ambiq_bin2board.py. The script sends a AM_SECBOOT_WIRED_MSGTYPE_HELLO command to the board and expects a response of length 88 bytes.

A sample response looks like this:

[‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’]

In ASCII characters it looks like this:

orI2C ErrorI2C ErrorI2C ErrorI2C ErrorI2C ErrorI2C ErrorI2C ErrorI2C Err

The script continues with a check if the response is of type AM_SECBOOT_WIRED_MSGTYPE_STATUS and this fails of course.

So it looks like the output from the code that runs on the board is the problem.

I’m not happy with this shaky upload procedure, for my take this might be good enough for a hobby project but not for a commercial product 8-(

Is there any way to fix this from the software side? I thought about making the response buffer much larger and than search for the response, something like this?

Thanks a bunch for looking into that in more depth, I have been caught up with some other bugs.

Yes, there should be a way to fix this in SW, by only changing the Python script. I will be trying to use the PySerial ‘reset_input_buffer’ function at the appropriate time to clear out all the “I2C error” (or any other pre-buffered UART junk)

That upload procedure was created by Ambiq (the makers of the Apollo3 microcontroller) as a tertiary upload method after SWD programming (bomber) and wireless OTA programming (I’ve never tried it). We’ve been working to improve it with the SVL, but ultimately in a commercial product you would most likely upload code using a SWD programmer.

Thanks again, and I’ll get back to you if I can rectify the script

aspregner, I’ve just tried out that fix and it seems promising. When trying to upload with the ASB while the Artemis is spitting out “I2C Error\n” continuously I went from about 15-20% reliability to 100% (tested about 5 times in a row without failures, then reverted and got back to poor reliability).

Check out this commit to see the change:

https://github.com/sparkfun/Arduino_Apo … 465991d32a

I will release 1.0.5 with the updated ASB tool, but if you need to get it working sooner you can modify ‘platform.txt’ to call your instance of Python3 and use the ‘tools/ambiq/ambiq_bin2board.py’ script with the same arguments.

v1.0.5 is available with this fix!

Thanks again for your afford!

I had the same idea earlier today, I did not mentioned this because it did not work for me 8-(

I just tried it again with 100 retries and the result looks like this:

Sending Hello.

Received response for Hello

Received Unknown Message

msgType = 0xa0d

Length = 0x3249

[‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’, ‘0x72’, ‘0x72’, ‘0x6f’, ‘0x72’, ‘0xd’, ‘0xa’, ‘0x49’, ‘0x32’, ‘0x43’, ‘0x20’, ‘0x45’]

Fail

Tries = 100

Upload failed

So despite cleaning the buffer before sending the HELLO request, by the time the script reads the response more garbage has already been written to the buffer.

I wonder what the difference is between your setup and mine.

Next thing I’ll try is to ignore the response from the HELLO request. From what I can see in the code the response is only used for verbose output.

Ok thats a super dirty hack but it worked 8-))

I forced the response header check to succeed like this:

#Check if response failed

if response == False:

verboseprint(“Failed to respond”)

return

verboseprint(“Received response for Hello”)

word = word_from_bytes(response, 4)

#if ((word & 0xFFFF) == AM_SECBOOT_WIRED_MSGTYPE_STATUS): # <<<<<<<<<<<<<<<<<<<<<<<<

if True:

Received Status

print(“Bootloader connected”)

Now the Blinking example is running on the board and I can also update it again using the standard way. Nice!

My learning here is to be much more careful about handling error conditions when reading sensors data.

Thanks again for your awesome support!

Oh, very strange…

What I think should be happening is this:

Serial port opens and DTR/RTS are toggled in a specific way that causes the auto-bootload RC circuit on the Artemis to force the board into bootload mode. In that mode it should no longer be outputting UART data.

        with serial.Serial(args.port, args.baud, timeout=0.5) as ser:
            #DTR is driven low when serial port open. DTR has now pulled RST low.

            time.sleep(0.005) #3ms and 10ms work well. Not 50, and not 0.

            #Setting RTS/DTR high causes the bootload pin to go high, then fall across 100ms
            ser.setDTR(0) #Set DTR high
            ser.setRTS(0) #Set RTS high - support the CH340E

            #Give bootloader a chance to run and check bootload pin before communication begins. But must initiate com before bootloader timeout of 250ms.
            time.sleep(0.100) #100ms works well

However, it is possible that before the Serial port opened perhaps the USB-serial bridge, the computer, or the combination of the two buffered N bytes that had been sent out earlier. Then reset input buffer method would zero that out and present a clean slate for further communication:

ser.reset_input_buffer() # reset the input bufer to discard any UART traffic that the device may have generated

Now that all could be wrong if somehow the uC is jumping to the main application after the buffer clear, or if the auto-bootload circuit is not behaving as expected.

Thanks for the explanation, now the code makes a lot more sense for me.

But somehow this did not work in my case. Even with the the reset of the input buffer there has been garbage data in the HELLO response buffer. Maybe some race condition.

I do not have a lot of luck with this board. I’m back on my original goal to connect the AS7263 spectral sensor but the sensor does not return any readings. I’ll open another thread for this.

@asprenger : I’m struggling with similar issues ( viewtopic.php?p=206453#p206453 ) Can you explain your solution at viewtopic.php?p=206414#p206414 ? Did you recreate ambiq_bin2board on MacOS with those changes?