1

问题:在异步访问我的 I2C 设备(在主循环而不是阻塞循环中轮询它)后,一旦我写入 USB 串行端口,就会出现 CPU 异常

背景:我有一个在 Microchip Studio 下运行的 Arduino 项目(用于通过 J-Link 接口进行调试)。我正在通过 I2C 与 VCNL4010 接近传感器通信。我有一个有效的同步函数,可以读取接近度:

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");
}

此代码工作正常,但会阻塞我的主循环,直到传感器读取完成。我需要避免阻塞,因为我也在控制电机。我写了一个异步版本,分为以下功能:

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;
}

作为对串行命令的响应,我readProximityBegin在主循环中调用并调用 update 直到readProximityReady变为真,此时我使用readProximityResult. 如前所述,一旦我在这一切之后写入 USB 串行端口,就会出现 CPU 异常(错误源于writeRTL 中的串行)。我不确定究竟是哪个异常,因为在 cortex_handlers.c 中,SAMD21 的 arduino 代码将各种异常路由到同一函数:

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

这是上面引用的我的 I2C 函数之一的示例:

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());
}
4

0 回答 0