Turning off CM3L via MCU results in CM3L immediately booting back up

Background

I am trying to write a firmata sysex command that allows for the CM3L to be turned off by the MCU for a period of time. The code is based on balena-fin-coprocessor-firmata and can be found on this branch here.

How it works

When a Firmata sysex command is sent with type 0x0F, the MCU will wait for a period of time before cutting power to the CM3L by clearing GPIO PF5 (PW_ON_3V3). The MCU will then further wait for a period of time before reapplying the power to the CM3L. These times are configurable via the sysex command itself.

The issue

With the code I can successfully cut power to the CM3L via the MCU, but the CM3L will immediately boot back up again, instead of remaining off for a period of time.

Here is a list of things that I have tried:

  • Removing non-core routines in the main loop (commented out ADC, digital) -> no effect
  • Testing the powersave FSM separately -> FSM works as it should in test_powersave.cpp
  • Comment out GPIO commands that turn the CM3L off -> CM3L and MCU stay on and work like normal
  • Created a noop systemresethandler -> no effect
  • Shutdown the CM3L using shutdown -h now via ssh -> CM3L no longer accepts ssh connections (indicating the CM3L is off)

And finally:

  • Putting an infinite loop immediately after turning the CM3L off -> CM3L powers off then immediately comes back on and MCU is not reachable via firmata (indicating the MCU stuck in infinite loop despite CM3L reset)

Is this something related to the MCU or related to the hardware? I have tried to look through the schematics and the firmware code to find why such a reset might happen but I am now stuck as to what to try next.

Any suggestions?

Hi @rohfle - first of all, we really appreciate the effort you put on updating our firmata story - this happens to be almost exactly what we are working on our side too!

Regarding the issue, can you please tell me if you are testing against a balenaFin v1.0 or v1.1, so that I can work on reproducing and get back to you asap?

Also, on the bottom side of the board there is a sticker with the lot ID, F XX/XX could you please also share the value on it?

Hi @curcuz, thanks for the reply!

I have a Balena v1.0 developer kit
The Lot ID is F 48/18

Also for completeness sake, here is the main.js file that I am running inside the docker container:

const Firmata = require("firmata");
const board = new Firmata("/dev/ttyUSB0");

console.log("Checking Firmata version...")

board.on("queryfirmware", () => {
    // Encoded terminal text colors, i.e. green is \x1b[32m
    console.log('\x1b[32m%s\x1b[0m', board.firmware.name +"  ✔ firmware name");
    console.log('\x1b[32m%s\x1b[0m', board.firmware.version.major + "." + board.firmware.version.minor + "              ✔ firmata version")
});

board.on("ready", function() {
  const POWERSAVE_CMD = 0xF;
  const CLOCKREAD_CMD = 0xD;

  const SHUTDOWN_DELAY = 10 // seconds
  const STARTUP_DELAY = 5 // minutes

  console.log('\x1b[32m%s\x1b[0m', "balenaFin        ✔ ready");

  board.sysexResponse(POWERSAVE_CMD, function(data) {
    console.log("POWERSAVE %s...", data)
    require('child_process').exec('/sbin/shutdown -h now', function (msg) { console.log(msg) });
  })

  board.sysexResponse(CLOCKREAD_CMD, function(data) {
    console.log("CLOCKREAD %s...", data)
  })

  function triggerPowersave() {
    console.log("Going into powersave mode for %d minutes...", STARTUP_DELAY);
    packet = [POWERSAVE_CMD, SHUTDOWN_DELAY, STARTUP_DELAY, 0]
    console.log("SENDING %s...", packet)
    board.sysexCommand(packet)
  }

  function triggerClockRead() {
    packet = [CLOCKREAD_CMD]
    console.log("SENDING %s...", packet)
    board.sysexCommand(packet)
  }

  setInterval(triggerClockRead, 1000)
  setTimeout(triggerPowersave, 10000);
});

process.on('SIGINT', function() {
  console.log("Resetting Firmata");
  // board.reset();
  process.exit();
});


Today I hooked it up to an oscilloscope and I got signals that look like this:

The cyan trace is PW_ON_3V3 - when low, the power for +3V3 (and CM3L) is turned off.
The yellow trace is MCU_RST - when low, it resets the ARTIK 020 MCU

PW_ON_3V3 only stays off only for around 2.2ms!

Kind of looks like a reset glitch doesn’t it?

Possible cause:

  • MCU_RST is connected to the FT2232H used for USB-JTAG
  • FT2232H runs from the +3V3 rail
  • +3V3 is the rail which is being turned off by PW_ON_3V3

Confirmation / Possible workarounds:

  • R216 could possibly be removed to prevent MCU_RST from being pulled low. Maybe someone knows where is it located on the PCB?
  • Looking at the FT2232H datasheet, there might be a way to set ADBUS7 to a value which doesn’t conflict with MCU_RST

Relevant schematics (v1.0)

USB-JTAG

ARTIK 020
image

3V3 SWITCH
image

1 Like

@rohfle we’ve been following this conversation via email, but I will update the thread in case some else in the community finds the information useful.

As you pointed out, the issue is indeed caused by a glitch when turning the power off, that comes from the FTDI chip we use to flash the coprocessor. Since it doesn’t happen on every board (and not even consistently on the boards that experiment the issue), we found it to be very elusive to debug.

We’ve traced the issue to the output pin of the FTDI that’s connected to the reset pin of the coprocessor. Since the FTDI chip is connected to the same power rail as the Compute Module, it’s shut down when the CM is. When that happens (the FTDI chip is shut down), the output pins get pulled to GND. When that pull is strong enough, it resets the coprocessor, which in turn releases the power rail and powers the compute module back up.

Since the newest v1.1 doesn’t use the FTDI chip to flash the coprocessor, the reset line is not connected and the issue is not present.
We are currently working on alternative solutions for the v1.0 balenaFin and will update the thread once we have updates.

Cheers,
Nico.

1 Like