adafruit / RTClib

A fork of Jeelab's fantastic RTC Arduino library
MIT License
798 stars 709 forks source link

ESP32 crashes when .now() is called before .begin() #293

Closed DIYLabsED closed 1 year ago

DIYLabsED commented 1 year ago

I'm having an issue where my ESP32 crashes when I call .now() before calling .begin(). I am using a generic ESP32 dev board, which has an ESP32-WROOM-32 chip. Arduino IDE version is 2.2.1, RTClib version is 2.1.1. I installed the RTClib library through the Arduino IDE's library manager.

This is the code which crashes my ESP32:

`#include

RTC_DS1307 rtc;

void setup() { // put your setup code here, to run once:

//When rtc.begin() is commented out, the ESP32 crashes //rtc.begin();

DateTime time = rtc.now(); //This line causes a crash when rtc.begin() is not called

}

void loop() { // put your main code here, to run repeatedly:

} `

If rtc.begin() is uncommented, everything works fine. The ESP32 prints this in the serial terminal:

`ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:1184 load:0x40078000,len:13232 load:0x40080400,len:3028 entry 0x400805e4 Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.

Core 1 register dump: PC : 0x400d1337 PS : 0x00060030 A0 : 0x800d1419 A1 : 0x3ffc5150
A2 : 0x00000000 A3 : 0x3ffc51a9 A4 : 0x00000001 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x3ffc2630
A10 : 0x400825f8 A11 : 0x00000001 A12 : 0x3ffbcca0 A13 : 0x3ffbcc80
A14 : 0x00000000 A15 : 0x3ffc21cc SAR : 0x00000000 EXCCAUSE: 0x0000001c
EXCVADDR: 0x0000000c LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000

Backtrace: 0x400d1334:0x3ffc5150 0x400d1416:0x3ffc5170 0x400d12a8:0x3ffc5190 0x400d1288:0x3ffc51d0 0x400d239e:0x3ffc5200

ELF file SHA256: 31cee8c7bff2a5e3`

I suspect it's caused by a pointer being uninitialized, and causing garbage values to be used instead.

edgar-bonet commented 1 year ago

It is indeed a stray pointer: i2c_dev is a member of RTC_I2C (the parent class of RTC_DS1307), initially NULL:

  Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface

It is properly initialized in RTC_DS1307::begin():

  i2c_dev = new Adafruit_I2CDevice(DS1307_ADDRESS, wireInstance);

and dereferenced in RTC_DS1307::now():

  i2c_dev->write_then_read(buffer, 1, buffer, 7);

The solution to your problem is to simply call begin(). Whereas it would be possible for the library to check the validity of the pointer within now(), that would bring its own issues:

IMHO, in this situation it makes sense to just say that, if any method accessing the RTC is called before begin(), the behavior is undefined.

caternuson commented 1 year ago

begin() should be called first.

DIYLabsED commented 1 year ago

Yes, I didn't think of all the issues that would come with checking the validity of a pointer. There is absolutely no reason to call now() before begin(). I spent a good half-hour going through my code trying to see what was causing the crash, before finding out that a function that I was calling was using now() and I hadn't noticed. Also, how do you guys manage to babysit so many Adafruit libraries? Like handling all the issues and pull requests.