From c9c4f2e71487f21c7017d81509f374d004158084 Mon Sep 17 00:00:00 2001 From: cyberman54 Date: Sat, 5 Mar 2022 13:30:34 +0100 Subject: [PATCH 1/2] remove i2c mutex (now done in arduino-esp v2) --- include/globals.h | 5 -- src/bmesensor.cpp | 60 +++++++------------ src/display.cpp | 146 +++++++++++++++++++-------------------------- src/i2c.cpp | 123 ++++++++++++++++---------------------- src/main.cpp | 5 -- src/rtctime.cpp | 107 +++++++++++++++------------------ src/timekeeper.cpp | 25 ++------ 7 files changed, 186 insertions(+), 285 deletions(-) diff --git a/include/globals.h b/include/globals.h index 9b141b09..9150be80 100644 --- a/include/globals.h +++ b/include/globals.h @@ -30,11 +30,6 @@ // length of display buffer for lmic event messages #define LMIC_EVENTMSG_LEN 17 -// I2C bus access control -#define I2C_MUTEX_LOCK() \ - (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(DISPLAYREFRESH_MS)) == pdTRUE) -#define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess)) - // pseudo system halt function, useful to prevent writeloops to NVRAM #ifndef _ASSERT #define _ASSERT(cond) \ diff --git a/src/bmesensor.cpp b/src/bmesensor.cpp index eada87ff..edda04f8 100644 --- a/src/bmesensor.cpp +++ b/src/bmesensor.cpp @@ -52,42 +52,28 @@ int bme_init(void) { int rc = 0; #ifdef HAS_BME680 - // block i2c bus access - if (I2C_MUTEX_LOCK()) { + Wire.begin(HAS_BME680); + iaqSensor.begin(BME680_ADDR, Wire); - Wire.begin(HAS_BME680); - iaqSensor.begin(BME680_ADDR, Wire); + ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major, + iaqSensor.version.minor, iaqSensor.version.major_bugfix, + iaqSensor.version.minor_bugfix); - ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major, - iaqSensor.version.minor, iaqSensor.version.major_bugfix, - iaqSensor.version.minor_bugfix); + iaqSensor.setConfig(bsec_config_iaq); + loadState(); + iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); + iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); - iaqSensor.setConfig(bsec_config_iaq); - loadState(); - iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); - iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); - - rc = checkIaqSensorStatus(); - - } else - ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error"); + rc = checkIaqSensorStatus(); #elif defined HAS_BME280 - if (I2C_MUTEX_LOCK()) { - rc = bme.begin(BME280_ADDR); - } else - ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error"); - + rc = bme.begin(BME280_ADDR); #elif defined HAS_BMP180 - if (I2C_MUTEX_LOCK()) { - // Wire.begin(21, 22); - rc = bmp.begin(); - } else - ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error"); + // Wire.begin(21, 22); + rc = bmp.begin(); #endif - I2C_MUTEX_UNLOCK(); // release i2c bus access if (rc) bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit return rc; @@ -123,8 +109,7 @@ int checkIaqSensorStatus(void) { // store current BME sensor data in struct void bme_storedata(bmeStatus_t *bme_store) { - if ((cfg.payloadmask & MEMS_DATA) && - (I2C_MUTEX_LOCK())) { // block i2c bus access + if (cfg.payloadmask & MEMS_DATA) #ifdef HAS_BME680 if (iaqSensor.run()) { // if new data is available @@ -143,20 +128,17 @@ void bme_storedata(bmeStatus_t *bme_store) { } #elif defined HAS_BME280 bme_store->temperature = bme.readTemperature(); - bme_store->pressure = (bme.readPressure() / 100.0); // conversion Pa -> hPa - // bme.readAltitude(SEALEVELPRESSURE_HPA); - bme_store->humidity = bme.readHumidity(); - bme_store->iaq = 0; // IAQ feature not present with BME280 + bme_store->pressure = (bme.readPressure() / 100.0); // conversion Pa -> hPa + // bme.readAltitude(SEALEVELPRESSURE_HPA); + bme_store->humidity = bme.readHumidity(); + bme_store->iaq = 0; // IAQ feature not present with BME280 #elif defined HAS_BMP180 bme_store->temperature = bmp.readTemperature(); - bme_store->pressure = (bmp.readPressure() / 100.0); // conversion Pa -> hPa - // bme.readAltitude(SEALEVELPRESSURE_HPA); - bme_store->iaq = 0; // IAQ feature not present with BME280 + bme_store->pressure = (bmp.readPressure() / 100.0); // conversion Pa -> hPa + // bme.readAltitude(SEALEVELPRESSURE_HPA); + bme_store->iaq = 0; // IAQ feature not present with BME280 #endif - I2C_MUTEX_UNLOCK(); // release i2c bus access - } - } // bme_storedata() #ifdef HAS_BME680 diff --git a/src/display.cpp b/src/display.cpp index 692b352d..99642ab4 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -90,85 +90,72 @@ void dp_setup(int contrast) { void dp_init(bool verbose) { -#if (HAS_DISPLAY) == 1 // i2c - // block i2c bus access - if (!I2C_MUTEX_LOCK()) - ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); - else { -#endif + dp_setup(DISPLAYCONTRAST); - dp_setup(DISPLAYCONTRAST); + if (verbose) { - if (verbose) { - - // show startup screen - // to come -> display .bmp file with logo + // show startup screen + // to come -> display .bmp file with logo // show chip information #if (VERBOSE) - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); - dp_setFont(MY_FONT_NORMAL); - dp_printf("** PAXCOUNTER **"); - dp_println(); - dp_printf("Software v%s", PROGVERSION); - dp_println(); - dp_printf("ESP32 %d cores", chip_info.cores); - dp_println(); - dp_printf("Chip Rev.%d", chip_info.revision); - dp_println(); - dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", - (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); - dp_println(); - dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024), - (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." - : "ext."); + dp_setFont(MY_FONT_NORMAL); + dp_printf("** PAXCOUNTER **"); + dp_println(); + dp_printf("Software v%s", PROGVERSION); + dp_println(); + dp_printf("ESP32 %d cores", chip_info.cores); + dp_println(); + dp_printf("Chip Rev.%d", chip_info.revision); + dp_println(); + dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", + (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); + dp_println(); + dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024), + (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); - // give user some time to read or take picture - dp_dump(displaybuf); - delay(2000); - dp_clear(); + // give user some time to read or take picture + dp_dump(displaybuf); + delay(2000); + dp_clear(); #endif // VERBOSE #if (HAS_LORA) - // generate DEVEUI as QR code and text - uint8_t buf[8], *p = buf; - char deveui[17]; - os_getDevEui((u1_t *)buf); - snprintf(deveui, 17, "%016llX", (*(uint64_t *)(p))); + // generate DEVEUI as QR code and text + uint8_t buf[8], *p = buf; + char deveui[17]; + os_getDevEui((u1_t *)buf); + snprintf(deveui, 17, "%016llX", (*(uint64_t *)(p))); - // display DEVEUI as QR code on the left - dp_contrast(30); - dp_printqr(3, 3, deveui); + // display DEVEUI as QR code on the left + dp_contrast(30); + dp_printqr(3, 3, deveui); - // display DEVEUI as plain text on the right - const int x_offset = QR_SCALEFACTOR * 29 + 14; - dp_setTextCursor(x_offset, 0); - dp_setFont(MY_FONT_NORMAL); - dp_printf("DEVEUI"); - dp_println(); - for (uint8_t i = 0; i <= 3; i++) { - dp_setTextCursor(x_offset, i + 3); - dp_printf("%4.4s", deveui + i * 4); - } + // display DEVEUI as plain text on the right + const int x_offset = QR_SCALEFACTOR * 29 + 14; + dp_setTextCursor(x_offset, 0); + dp_setFont(MY_FONT_NORMAL); + dp_printf("DEVEUI"); + dp_println(); + for (uint8_t i = 0; i <= 3; i++) { + dp_setTextCursor(x_offset, i + 3); + dp_printf("%4.4s", deveui + i * 4); + } - // give user some time to read or take picture - dp_dump(displaybuf); + // give user some time to read or take picture + dp_dump(displaybuf); #if !(BOOTMENU) - delay(8000); + delay(8000); #endif #endif // HAS_LORA - } // verbose + } // verbose - dp_power(cfg.screenon); // set display off if disabled - -#if (HAS_DISPLAY) == 1 // i2c - I2C_MUTEX_UNLOCK(); // release i2c bus access - } // mutex -#endif + dp_power(cfg.screenon); // set display off if disabled } // dp_init @@ -182,29 +169,22 @@ void dp_refresh(bool nextPage) { if (!DisplayIsOn && (DisplayIsOn == cfg.screenon)) return; - // block i2c bus access - if (!I2C_MUTEX_LOCK()) - ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); - else { - // set display on/off according to current device configuration - if (DisplayIsOn != cfg.screenon) { - DisplayIsOn = cfg.screenon; - dp_power(cfg.screenon); - } + // set display on/off according to current device configuration + if (DisplayIsOn != cfg.screenon) { + DisplayIsOn = cfg.screenon; + dp_power(cfg.screenon); + } #ifndef HAS_BUTTON - // auto flip page if we are in unattended mode - if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) { - framecounter = 0; - nextPage = true; - } + // auto flip page if we are in unattended mode + if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) { + framecounter = 0; + nextPage = true; + } #endif - dp_drawPage(nextPage); + dp_drawPage(nextPage); - I2C_MUTEX_UNLOCK(); // release i2c bus access - - } // mutex } // refreshDisplay() void dp_drawPage(bool nextpage) { @@ -600,14 +580,8 @@ void dp_power(uint8_t screenon) { void dp_shutdown(void) { #if (HAS_DISPLAY) == 1 - // block i2c bus access - if (!I2C_MUTEX_LOCK()) - ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); - else { - obdPower(&ssoled, false); - delay(DISPLAYREFRESH_MS / 1000 * 1.1); - I2C_MUTEX_UNLOCK(); // release i2c bus access - } + obdPower(&ssoled, false); + delay(DISPLAYREFRESH_MS / 1000 * 1.1); #elif (HAS_DISPLAY) == 2 // to come #endif diff --git a/src/i2c.cpp b/src/i2c.cpp index c908d250..9731e09d 100644 --- a/src/i2c.cpp +++ b/src/i2c.cpp @@ -12,7 +12,7 @@ void i2c_init(void) { Wire.begin(); } -//void i2c_deinit(void) { Wire.end(); } +// void i2c_deinit(void) { Wire.end(); } void i2c_deinit(void) { Wire.~TwoWire(); } void i2c_scan(void) { @@ -49,90 +49,71 @@ void i2c_scan(void) { ESP_LOGI(TAG, "Starting I2C bus scan..."); - // block i2c bus access - if (I2C_MUTEX_LOCK()) { + memset(&bbi2c, 0, sizeof(bbi2c)); + bbi2c.bWire = 0; + bbi2c.iSDA = MY_DISPLAY_SDA; + bbi2c.iSCL = MY_DISPLAY_SCL; + I2CInit(&bbi2c, 100000L); // Scan at 100KHz low speed + delay(100); // allow devices to power up - memset(&bbi2c, 0, sizeof(bbi2c)); - bbi2c.bWire = 0; - bbi2c.iSDA = MY_DISPLAY_SDA; - bbi2c.iSCL = MY_DISPLAY_SCL; - I2CInit(&bbi2c, 100000L); // Scan at 100KHz low speed - delay(100); // allow devices to power up + uint8_t map[16]; + uint8_t i; + int iDevice, iCount; - uint8_t map[16]; - uint8_t i; - int iDevice, iCount; - - I2CScan(&bbi2c, map); // get bitmap of connected I2C devices - if (map[0] == 0xfe) // something is wrong with the I2C bus + I2CScan(&bbi2c, map); // get bitmap of connected I2C devices + if (map[0] == 0xfe) // something is wrong with the I2C bus + { + ESP_LOGI(TAG, "I2C pins are not correct or the bus is being pulled low " + "by a bad device; unable to run scan"); + } else { + iCount = 0; + for (i = 1; i < 128; i++) // skip address 0 (general call address) since + // more than 1 device can respond { - ESP_LOGI(TAG, "I2C pins are not correct or the bus is being pulled low " - "by a bad device; unable to run scan"); - } else { - iCount = 0; - for (i = 1; i < 128; i++) // skip address 0 (general call address) since - // more than 1 device can respond + if (map[i >> 3] & (1 << (i & 7))) // device found { - if (map[i >> 3] & (1 << (i & 7))) // device found - { - iCount++; - iDevice = I2CDiscoverDevice(&bbi2c, i); - ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i, - szNames[iDevice]); // show the device name as a string - } - } // for i - ESP_LOGI(TAG, "%u I2C device(s) found", iCount); - } - - I2C_MUTEX_UNLOCK(); // release i2c bus access - } else - ESP_LOGE(TAG, "I2C bus busy - scan error"); + iCount++; + iDevice = I2CDiscoverDevice(&bbi2c, i); + ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i, + szNames[iDevice]); // show the device name as a string + } + } // for i + ESP_LOGI(TAG, "%u I2C device(s) found", iCount); + } } -// mutexed functions for i2c r/w access +// functions for i2c r/w access, mutexing is done by Wire.cpp int 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) + 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) { ret = 0xFF; - uint16_t index = 0; - while (Wire.available()) { - if (index > len) { - ret = 0xFF; - goto finish; - } - data[index++] = Wire.read(); + goto finish; } - - finish: - I2C_MUTEX_UNLOCK(); // release i2c bus access - return ret; - } else { - ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); - return 0xFF; + data[index++] = Wire.read(); } + +finish: + return ret ? ret : 0xFF; } int 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 ? ret : 0xFF; - } else { - ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); - return 0xFF; + 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(); + + return ret ? ret : 0xFF; } diff --git a/src/main.cpp b/src/main.cpp index 6292380e..608f5f8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -87,11 +87,6 @@ void setup() { char features[100] = ""; - // create some semaphores for syncing / mutexing tasks - I2Caccess = xSemaphoreCreateMutex(); // for access management of i2c bus - _ASSERT(I2Caccess != NULL); - I2C_MUTEX_UNLOCK(); - // disable brownout detection #ifdef DISABLE_BROWNOUT // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 diff --git a/src/rtctime.cpp b/src/rtctime.cpp index 9b12cd94..e0142d45 100644 --- a/src/rtctime.cpp +++ b/src/rtctime.cpp @@ -10,88 +10,75 @@ RtcDS3231 Rtc(Wire); // RTC hardware i2c interface // initialize RTC uint8_t rtc_init(void) { - if (I2C_MUTEX_LOCK()) { // block i2c bus access + Wire.begin(HAS_RTC); + Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL); - Wire.begin(HAS_RTC); - Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL); + // configure RTC chip + Rtc.Enable32kHzPin(false); + Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); - // configure RTC chip - Rtc.Enable32kHzPin(false); - Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); - - if (!Rtc.GetIsRunning()) { - ESP_LOGI(TAG, "RTC not running, starting now"); - Rtc.SetIsRunning(true); - } + if (!Rtc.GetIsRunning()) { + ESP_LOGI(TAG, "RTC not running, starting now"); + Rtc.SetIsRunning(true); + } #if (TIME_SYNC_COMPILEDATE) - // initialize a blank RTC without battery backup with build time - RtcDateTime tt = Rtc.GetDateTime(); - time_t t = tt.Epoch32Time(); // sec2000 -> epoch + // initialize a blank RTC without battery backup with build time + RtcDateTime tt = Rtc.GetDateTime(); + time_t t = tt.Epoch32Time(); // sec2000 -> epoch - if (!Rtc.IsDateTimeValid() || !timeIsValid(t)) { - ESP_LOGW(TAG, "RTC has no recent time, setting to compiletime"); - Rtc.SetDateTime(RtcDateTime(mkgmtime(compileTime()) - - SECS_YR_2000)); // epoch -> sec2000 - } + if (!Rtc.IsDateTimeValid() || !timeIsValid(t)) { + ESP_LOGW(TAG, "RTC has no recent time, setting to compiletime"); + Rtc.SetDateTime(RtcDateTime(mkgmtime(compileTime()) - + SECS_YR_2000)); // epoch -> sec2000 + } #endif - I2C_MUTEX_UNLOCK(); // release i2c bus access - ESP_LOGI(TAG, "RTC initialized"); - return 1; // success - } else { - ESP_LOGE(TAG, "RTC initialization error, I2C bus busy"); - return 0; // failure - } + ESP_LOGI(TAG, "RTC initialized"); + return 1; // success + + // failure + // return 0 } // rtc_init() uint8_t set_rtctime(time_t t) { // t is sec epoch time - if (I2C_MUTEX_LOCK()) { + #ifdef RTC_INT // sync rtc 1Hz pulse on top of second - Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off - Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start + Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off + Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start #endif - Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000 - I2C_MUTEX_UNLOCK(); - ESP_LOGI(TAG, "RTC time synced"); - return 1; // success - } else { - ESP_LOGE(TAG, "RTC set time failure"); - return 0; // failure - } + Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000 + ESP_LOGI(TAG, "RTC time synced"); + return 1; // success + + // failure + // return 0 + } // set_rtctime() time_t get_rtctime(uint16_t *msec) { + time_t t = 0; *msec = 0; - if (I2C_MUTEX_LOCK()) { - if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) { - RtcDateTime tt = Rtc.GetDateTime(); - t = tt.Epoch32Time(); // sec2000 -> epoch - } - I2C_MUTEX_UNLOCK(); -#ifdef RTC_INT - // adjust time to top of next second by waiting TimePulseTick to flip - bool lastTick = TimePulseTick; - while (TimePulseTick == lastTick) { - }; - t++; -#endif - return t; - } else { - ESP_LOGE(TAG, "RTC get time failure"); - return 0; // failure + if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) { + RtcDateTime tt = Rtc.GetDateTime(); + t = tt.Epoch32Time(); // sec2000 -> epoch } +#ifdef RTC_INT + // adjust time to top of next second by waiting TimePulseTick to flip + bool lastTick = TimePulseTick; + while (TimePulseTick == lastTick) { + }; + t++; +#endif + return t; + } // get_rtctime() float get_rtctemp(void) { - if (I2C_MUTEX_LOCK()) { - RtcTemperature temp = Rtc.GetTemperature(); - I2C_MUTEX_UNLOCK(); - return temp.AsFloatDegC(); - } - return 0; + RtcTemperature temp = Rtc.GetTemperature(); + return temp.AsFloatDegC(); } // get_rtctemp() #endif // HAS_RTC \ No newline at end of file diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 32b1e0fe..1f30eb09 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -63,8 +63,7 @@ void calibrateTime(void) { } // calibrateTime() // set system time (UTC), calibrate RTC and RTC_INT pps -bool setMyTime(uint32_t t_sec, uint16_t t_msec, - timesource_t mytimesource) { +bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) { struct timeval tv = {0}; @@ -141,22 +140,12 @@ uint8_t timepulse_init() { // if we have, use pulse from on board RTC chip as time base for calendar time #if defined RTC_INT - // setup external rtc 1Hz clock pulse - if (I2C_MUTEX_LOCK()) { - Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz); - Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); - I2C_MUTEX_UNLOCK(); - pinMode(RTC_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING); - ESP_LOGI(TAG, "Timepulse: external (RTC)"); - return 1; // success - } else { - ESP_LOGE(TAG, "RTC initialization error, I2C bus busy"); - return 0; // failure - } - return 1; // success - + Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz); + Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); + pinMode(RTC_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING); + ESP_LOGI(TAG, "Timepulse: external (RTC)"); #else // use ESP32 hardware timer as time base for calendar time ppsIRQ = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec @@ -164,8 +153,6 @@ uint8_t timepulse_init() { timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, false); timerAlarmEnable(ppsIRQ); ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)"); - return 1; // success - #endif // start cyclic time sync From dd41b6e9da58bb3c5ff5f1e5f3a42ead97ea9178 Mon Sep 17 00:00:00 2001 From: cyberman54 Date: Sat, 5 Mar 2022 14:07:48 +0100 Subject: [PATCH 2/2] timesync cleanups --- include/timekeeper.h | 15 +++-- src/cyclic.cpp | 4 -- src/main.cpp | 14 +---- src/timekeeper.cpp | 128 +++++++++++++++++++++++-------------------- 4 files changed, 78 insertions(+), 83 deletions(-) diff --git a/include/timekeeper.h b/include/timekeeper.h index e28b60d9..88d3c8e8 100644 --- a/include/timekeeper.h +++ b/include/timekeeper.h @@ -10,7 +10,8 @@ #include "dcf77.h" #include "esp_sntp.h" -#define HAS_LORA_TIME ((HAS_LORA) && ((TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN))) +#define HAS_LORA_TIME \ + ((HAS_LORA) && ((TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN))) #define SECS_YR_2000 (946684800UL) // the time at the start of y2k #define GPS_UTC_DIFF 315964800UL // seconds diff between gps and utc epoch @@ -26,16 +27,14 @@ extern DRAM_ATTR bool TimePulseTick; // 1sec pps flag set by GPS or RTC extern DRAM_ATTR unsigned long lastPPS; extern hw_timer_t *ppsIRQ; -void IRAM_ATTR CLOCKIRQ(void); -void IRAM_ATTR GPSIRQ(void); -void clock_init(void); -void clock_loop(void *pvParameters); +//void IRAM_ATTR CLOCKIRQ(void); +//void IRAM_ATTR GPSIRQ(void); +//void clock_loop(void *pvParameters); void setTimeSyncIRQ(void); -uint8_t timepulse_init(void); +void time_init(void); bool timeIsValid(time_t const t); void calibrateTime(void); -bool setMyTime(uint32_t t_sec, uint16_t t_msec, - timesource_t mytimesource); +bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource); time_t compileTime(void); time_t mkgmtime(const struct tm *ptm); TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config, diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 27697efc..f5d905c0 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -18,10 +18,6 @@ void doHousekeeping() { if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE)) do_reset(true); // warmstart - // try to get time if we don't yet have a recent timesource - if (timeSource == _unsynced || timeSource == _set) - calibrateTime(); - // print heap and task storage information ESP_LOGD(TAG, "Heap: Free:%d, Min:%d, Size:%d, Alloc:%d, StackHWM:%d", ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(), diff --git a/src/main.cpp b/src/main.cpp index 608f5f8a..b9176b0c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -476,20 +476,8 @@ void setup() { // only if we have a timesource we do timesync #if ((HAS_LORA_TIME) || (HAS_GPS) || (HAS_RTC)) - -#if (defined HAS_IF482 || defined HAS_DCF77) - ESP_LOGI(TAG, "Starting Clock Controller..."); - clock_init(); -#endif - -#if (HAS_LORA_TIME) - timesync_init(); // create loraserver time sync task -#endif - - ESP_LOGI(TAG, "Starting Timekeeper..."); - _ASSERT(timepulse_init()); // starts pps and cyclic time sync + time_init(); strcat_P(features, " TIME"); - #endif // timesync // show compiled features diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 1f30eb09..3545d915 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -31,6 +31,40 @@ Ticker timesyncer; void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); } +// interrupt service routine triggered by GPS PPS +void IRAM_ATTR GPSIRQ(void) { + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + // take timestamp + lastPPS = millis(); // last time of pps + + // yield only if we should + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} + +// interrupt service routine triggered by esp32 hardware timer +void IRAM_ATTR CLOCKIRQ(void) { + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + +// advance wall clock, if we have +#if (defined HAS_IF482 || defined HAS_DCF77) + xTaskNotifyFromISR(ClockTask, uint32_t(time(NULL)), eSetBits, + &xHigherPriorityTaskWoken); +#endif + +// flip time pulse ticker, if needed +#ifdef HAS_DISPLAY + TimePulseTick = !TimePulseTick; // flip global variable pulse ticker +#endif + + // yield only if we should + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} + void calibrateTime(void) { // kick off asynchronous lora timesync if we have @@ -125,7 +159,7 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) { } // helper function to setup a pulse per second for time synchronisation -uint8_t timepulse_init() { +void timepulse_init(void) { // set esp-idf API sntp sync mode // sntp_init(); @@ -155,49 +189,15 @@ uint8_t timepulse_init() { ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)"); #endif - // start cyclic time sync - timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); - // get time if we don't have one if (timeSource != _set) setTimeSyncIRQ(); // init systime by RTC or GPS or LORA + // start cyclic time sync + timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); + } // timepulse_init -// interrupt service routine triggered by GPS PPS -void IRAM_ATTR GPSIRQ(void) { - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - // take timestamp - lastPPS = millis(); // last time of pps - - // yield only if we should - if (xHigherPriorityTaskWoken) - portYIELD_FROM_ISR(); -} - -// interrupt service routine triggered by esp32 hardware timer -void IRAM_ATTR CLOCKIRQ(void) { - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - -// advance wall clock, if we have -#if (defined HAS_IF482 || defined HAS_DCF77) - xTaskNotifyFromISR(ClockTask, uint32_t(time(NULL)), eSetBits, - &xHigherPriorityTaskWoken); -#endif - -// flip time pulse ticker, if needed -#ifdef HAS_DISPLAY - TimePulseTick = !TimePulseTick; // flip global variable pulse ticker -#endif - - // yield only if we should - if (xHigherPriorityTaskWoken) - portYIELD_FROM_ISR(); -} - // helper function to check plausibility of a given epoch time bool timeIsValid(time_t const t) { // is t a time in the past? we use compile time to guess @@ -218,26 +218,6 @@ TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config, return round(txTime); } -void clock_init(void) { - -// setup clock output interface -#ifdef HAS_IF482 - IF482.begin(HAS_IF482); -#elif defined HAS_DCF77 - pinMode(HAS_DCF77, OUTPUT); -#endif - - xTaskCreatePinnedToCore(clock_loop, // task function - "clockloop", // name of task - 3072, // stack size of task - (void *)1, // task parameter - 6, // priority of the task - &ClockTask, // task handle - 1); // CPU core - - _ASSERT(ClockTask != NULL); // has clock task started? -} // clock_init - void clock_loop(void *taskparameter) { // ClockTask uint32_t current_time = 0, previous_time = 0; @@ -320,6 +300,26 @@ void clock_loop(void *taskparameter) { // ClockTask } // for } // clock_loop() +void clock_init(void) { + +// setup clock output interface +#ifdef HAS_IF482 + IF482.begin(HAS_IF482); +#elif defined HAS_DCF77 + pinMode(HAS_DCF77, OUTPUT); +#endif + + xTaskCreatePinnedToCore(clock_loop, // task function + "clockloop", // name of task + 3072, // stack size of task + (void *)1, // task parameter + 6, // priority of the task + &ClockTask, // task handle + 1); // CPU core + + _ASSERT(ClockTask != NULL); // has clock task started? +} // clock_init + // we use compile date to create a time_t reference "in the past" time_t compileTime(void) { @@ -378,4 +378,16 @@ time_t mkgmtime(const struct tm *ptm) { secs += ptm->tm_min * SecondsPerMinute; secs += ptm->tm_sec; return secs; +} + +void time_init(void) { +#if (HAS_LORA_TIME) + timesync_init(); // create loraserver time sync task +#endif + ESP_LOGI(TAG, "Starting time pulse..."); + timepulse_init(); // starts pps and cyclic time sync +#if (defined HAS_IF482 || defined HAS_DCF77) + ESP_LOGI(TAG, "Starting clock controller..."); + clock_init(); +#endif } \ No newline at end of file