1

Problem: As soon as I write to the USB serial port after accessing my I2C device asynchronously (polling it in main loop rather than a blocking loop), I get a CPU exception

Background: I have an Arduino project running under Microchip studio (for debugging via the J-Link interface). I am communicating with a VCNL4010 proximity sensor via I2C. I have a working synchronous function that reads proximity as such:

Zult<uint16_t> ProximitySensor::readProximity(void) {
    auto res = setIntMask(0x80);
    if (res.isError())
        return Zult<uint16_t>(res);

    res = write8(VCNL4010_COMMAND, VCNL4010_MEASUREPROXIMITY);
    if (res.isError())
        return Zult<uint16_t>(res);
    auto start = millis();
    do {
        auto cmd = read8(VCNL4010_COMMAND);
        if (cmd.isError())
            return Zult<uint16_t>(cmd);
        if (cmd.getResult() & VCNL4010_PROXIMITYREADY) {
            return read16(VCNL4010_PROXIMITYDATA);
        }
        delay(1);
    } while (millis() - start < 1000);
    return Zult<uint16_t>(0, "timeout in readProximity");
}

This code works fine, but blocks my main loop until the sensor reading is complete. I need to avoid blocking because I'm also controlling a motor. I wrote an async version that's broken into these functions:

Zult<bool> ProximitySensor::readProximityBegin() {
    auto res = setIntMask(0x80);
    if (res.isError())
        return Zult<uint16_t>(res);
    res = write8(VCNL4010_COMMAND, VCNL4010_MEASUREPROXIMITY);
    if (res.isError())
        return Zult<uint16_t>(res);
    asyncStart = millis();
    asyncReady = false;
    asyncResult = NotReadyZult;
}
    
bool ProximitySensor::readProximityReady() {
    return asyncReady;
}

void ProximitySensor::stopAsync() {
    asyncReady = true;
    asyncStart = 0;
}

void ProximitySensor::update() {
    if (asyncStart != 0) {
        auto cmd = read8(VCNL4010_COMMAND);
        if (cmd.isError()) {
            asyncResult = Zult<uint16_t>(cmd);
            stopAsync();
            return;
        }
        if (cmd.getResult() & VCNL4010_PROXIMITYREADY) {
            asyncResult = read16(VCNL4010_PROXIMITYDATA);
            stopAsync();
            return;
        }
        if (millis() - asyncStart > 1000) {
            asyncResult = Zult<uint16_t>(0, "timeout in readProximity");
            stopAsync();
        }
    }
}
    
Zult<uint16_t> ProximitySensor::readProximityResult() {
    return asyncResult;
}

In response to a serial command I invoke readProximityBegin and call update in my main loop until readProximityReady becomes true, at which time I read the value using readProximityResult. As mentioned, as soon as I write to the USB serial port after all this, I get a CPU exception (the error originates from the serial write in the RTL). I'm not sure which exception exactly because in cortex_handlers.c it looks like the arduino code for the SAMD21 routes all sorts of exceptions to this same function:

void Dummy_Handler(void)
{
#if defined DEBUG
  __BKPT(3); // this is where my debugger stops
#endif
  for (;;) { }
}

Here's an example of one of my I2C functions referenced by the above:

Zult<uint8_t> ProximitySensor::read8(uint8_t command) {
    Wire.beginTransmission(_i2caddr);
    Wire.write(command);
    auto result = Wire.endTransmission();
    if (result != 0) {
        return Zult<uint8_t>((int)result, "Writing request to read8");
    }

    delayMicroseconds(170); // delay required

    Wire.requestFrom(_i2caddr, (uint8_t)1);
    auto start = millis();
    while (!Wire.available()) {
        if (millis() - start > 1000)
            return Zult<uint16_t>(0, "Timeout waiting for read");
    }
    return Zult<uint8_t>(Wire.read());
}
N8allan
  • 2,138
  • 19
  • 32
  • While at Dummy_Handler, open Debug > Windows > I/O window. Find and expand "Nested Vectored Interrupt Controller (NVIC)" option and have a look at "ISPR" state - it contains all the interrupt flags corresponding to the Interrupt Line Mapping (SAMD Family Datasheet - 11.2.2 Interrupt Line Mapping). This way you will be able to identify the unhandled interrupt causing the problem. – Mephistt Dec 23 '21 at 19:15
  • That sounds like just what I need to chase this down. Thank you @Mephistt – N8allan Feb 03 '22 at 23:48

0 Answers0