AXP192 low level I2C mutexing

This commit is contained in:
Verkehrsrot 2019-09-30 12:35:03 +02:00
parent 58ed680a92
commit c93b0867a9
2 changed files with 121 additions and 93 deletions

View File

@ -19,6 +19,8 @@ void power_event_IRQ(void);
void AXP192_power(bool on); void AXP192_power(bool on);
void AXP192_init(void); void AXP192_init(void);
void AXP192_showstatus(void); void AXP192_showstatus(void);
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
#endif // HAS_PMU #endif // HAS_PMU
#endif #endif

View File

@ -11,48 +11,41 @@ AXP20X_Class pmu;
void power_event_IRQ(void) { void power_event_IRQ(void) {
if (!I2C_MUTEX_LOCK()) pmu.readIRQ();
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
else {
pmu.readIRQ(); if (pmu.isVbusOverVoltageIRQ())
// put your power event handler code here ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000);
if (pmu.isVbusPlugInIRQ())
ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000,
pmu.getVbusCurrent());
if (pmu.isVbusRemoveIRQ())
ESP_LOGI(TAG, "USB unplugged.");
if (pmu.isVbusOverVoltageIRQ()) if (pmu.isBattPlugInIRQ())
ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000); ESP_LOGI(TAG, "Battery is connected.");
if (pmu.isVbusPlugInIRQ()) if (pmu.isBattRemoveIRQ())
ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000, ESP_LOGI(TAG, "Battery was removed.");
pmu.getVbusCurrent()); if (pmu.isChargingIRQ())
if (pmu.isVbusRemoveIRQ()) ESP_LOGI(TAG, "Battery charging.");
ESP_LOGI(TAG, "USB unplugged."); if (pmu.isChargingDoneIRQ())
ESP_LOGI(TAG, "Battery charging done.");
if (pmu.isBattTempLowIRQ())
ESP_LOGI(TAG, "Battery high temperature.");
if (pmu.isBattTempHighIRQ())
ESP_LOGI(TAG, "Battery low temperature.");
if (pmu.isBattPlugInIRQ()) // display on/off
ESP_LOGI(TAG, "Battery is connected."); if (pmu.isPEKShortPressIRQ()) {
if (pmu.isBattRemoveIRQ()) cfg.screenon = !cfg.screenon;
ESP_LOGI(TAG, "Battery was removed."); }
if (pmu.isChargingIRQ())
ESP_LOGI(TAG, "Battery charging.");
if (pmu.isChargingDoneIRQ())
ESP_LOGI(TAG, "Battery charging done.");
if (pmu.isBattTempLowIRQ())
ESP_LOGI(TAG, "Battery high temperature.");
if (pmu.isBattTempHighIRQ())
ESP_LOGI(TAG, "Battery low temperature.");
// display on/off // shutdown power
if (pmu.isPEKShortPressIRQ()) { if (pmu.isPEKLongtPressIRQ()) {
cfg.screenon = !cfg.screenon; AXP192_power(false); // switch off Lora, GPS, display
} pmu.shutdown();
}
// shutdown power pmu.clearIRQ();
if (pmu.isPEKLongtPressIRQ()) {
AXP192_power(false); // switch off Lora, GPS, display
pmu.shutdown();
}
pmu.clearIRQ();
I2C_MUTEX_UNLOCK();
} // mutex
// refresh stored voltage value // refresh stored voltage value
read_voltage(); read_voltage();
@ -75,70 +68,103 @@ void AXP192_power(bool on) {
void AXP192_showstatus(void) { void AXP192_showstatus(void) {
if (!I2C_MUTEX_LOCK()) if (pmu.isBatteryConnect())
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); if (pmu.isChargeing())
else { ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent());
if (pmu.isBatteryConnect())
if (pmu.isChargeing())
ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent());
else
ESP_LOGI(TAG, "Battery not charging");
else else
ESP_LOGI(TAG, "No Battery"); ESP_LOGI(TAG, "Battery not charging");
else
ESP_LOGI(TAG, "No Battery");
if (pmu.isVBUSPlug()) if (pmu.isVBUSPlug())
ESP_LOGI(TAG, "USB powered, %.0fmW", ESP_LOGI(TAG, "USB powered, %.0fmW",
pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent()); pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent());
else else
ESP_LOGI(TAG, "USB not present"); ESP_LOGI(TAG, "USB not present");
I2C_MUTEX_UNLOCK();
} // mutex
} }
void AXP192_init(void) { void AXP192_init(void) {
// block i2c bus access if (pmu.begin(i2c_readBytes, i2c_writeBytes, AXP192_PRIMARY_ADDRESS) == AXP_FAIL)
if (I2C_MUTEX_LOCK()) { ESP_LOGI(TAG, "AXP192 PMU initialization failed");
else {
if (pmu.begin(Wire, AXP192_PRIMARY_ADDRESS)) // configure AXP192
ESP_LOGI(TAG, "AXP192 PMU initialization failed"); pmu.setDCDC1Voltage(3300); // for external OLED display
else { pmu.setTimeOutShutdown(false); // no automatic shutdown
pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); // TS pin mode off to save power
// configure AXP192 // switch ADCs on
pmu.setDCDC1Voltage(3300); // for external OLED display pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true);
pmu.setTimeOutShutdown(false); // no automatic shutdown pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true);
pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); // TS pin mode off to save power pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true);
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
// switch ADCs on // switch power rails on
pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true); AXP192_power(true);
pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true);
pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true);
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
// switch power rails on
AXP192_power(true);
// I2C access of AXP202X library currently is not mutexable
// so we better should disable AXP interrupts... ?
#ifdef PMU_INT #ifdef PMU_INT
pinMode(PMU_INT, INPUT_PULLUP); pinMode(PMU_INT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING); attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING);
pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ |
AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ |
AXP202_CHARGING_FINISHED_IRQ, AXP202_CHARGING_FINISHED_IRQ,
1); 1);
pmu.clearIRQ(); pmu.clearIRQ();
#endif // PMU_INT #endif // PMU_INT
ESP_LOGI(TAG, "AXP192 PMU initialized"); ESP_LOGI(TAG, "AXP192 PMU initialized");
} }
I2C_MUTEX_UNLOCK(); // release i2c bus access
} else
ESP_LOGE(TAG, "I2c bus busy - PMU initialization error");
} }
// helper functions for mutexing i2c access
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
if (I2C_MUTEX_LOCK()) {
uint8_t ret = 0;
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission(false);
uint8_t cnt = Wire.requestFrom(addr, (uint8_t)len, (uint8_t)1);
if (!cnt) {
ret = 0xFF;
}
uint16_t index = 0;
while (Wire.available()) {
if (index > len)
return 0xFF;
data[index++] = Wire.read();
}
I2C_MUTEX_UNLOCK(); // release i2c bus access
return ret;
} else {
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
return 0xFF;
}
}
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
if (I2C_MUTEX_LOCK()) {
uint8_t ret = 0;
Wire.beginTransmission(addr);
Wire.write(reg);
for (uint16_t i = 0; i < len; i++) {
Wire.write(data[i]);
}
ret = Wire.endTransmission();
I2C_MUTEX_UNLOCK(); // release i2c bus access
return ret ? 0xFF : ret;
//return ret ? ret : 0xFF;
} else {
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
return 0xFF;
}
}
#endif // HAS_PMU #endif // HAS_PMU
#ifdef BAT_MEASURE_ADC #ifdef BAT_MEASURE_ADC
@ -196,12 +222,12 @@ uint16_t read_voltage() {
uint16_t voltage = 0; uint16_t voltage = 0;
#ifdef HAS_PMU #ifdef HAS_PMU
if (!I2C_MUTEX_LOCK()) // if (!I2C_MUTEX_LOCK())
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); // ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
else { // else {
voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage(); voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage();
I2C_MUTEX_UNLOCK(); // I2C_MUTEX_UNLOCK();
} // }
#else #else
#ifdef BAT_MEASURE_ADC #ifdef BAT_MEASURE_ADC