Skip to content

Initializing with board.I2C() multiple times causing crash into safe mode #1603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
makermelissa opened this issue Feb 28, 2019 · 24 comments
Closed
Assignees

Comments

@makermelissa
Copy link
Collaborator

I was experimenting with changing from busio.I2C over to board.I2C() for another issue due to conflicts. It worked great in CP 3.1.2, but in both CP4 Beta 2 and the latest build off master, it causes the board to go into safe mode.

@makermelissa
Copy link
Collaborator Author

I forgot to add that this was on a Feather M4 Express.

@makermelissa
Copy link
Collaborator Author

The setup I had for reproduction purposes is I was using the test code Jerry had at:
adafruit/Adafruit_CircuitPython_FeatherWing#35 as code.py, the latest master branch at: https://github.com/makermelissa/Adafruit_CircuitPython_FeatherWing, and the latest uncompressed versions of the minimal supporting libraries.

I was just doing a quick test in CP4 before merging when I discovered this.

@jerryneedell
Copy link
Collaborator

when I try that test code with your feathewrwing library on a particle argon, I get

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-alpha-1966-g3b58be9c7-dirty on 2019-02-24; Particle Argon with nRF52840
>>> import uv_temp_test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "uv_temp_test.py", line 10, in <module>
  File "/lib/adafruit_sht31d.py", line 95, in __init__
  File "/lib/adafruit_bus_device/i2c_device.py", line 66, in __init__
AttributeError: 'dict' object has no attribute 'try_lock'
>>> 
>>> 

It works if I use my version of the alphanunum_featherewing.py

# The MIT License (MIT)
#
# Copyright (c) 2019 Melissa LeBlanc-Williams for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_featherwing.alphanum_featherwing`
====================================================

Helper for using the `14-Segment AlphaNumeric FeatherWing <https://www.adafruit.com/product/3139>`_.

* Author(s): Melissa LeBlanc-Williams
"""

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_FeatherWing.git"

import board
import adafruit_ht16k33.segments as segments
from adafruit_featherwing.led_segments import Segments

class AlphaNumFeatherWing(Segments):
    """Class representing an `Adafruit 14-segment AlphaNumeric FeatherWing
       <https://www.adafruit.com/product/3139>`_.

       Automatically uses the feather's I2C bus."""
    def __init__(self, address=0x70):
        super().__init__()
        self._segments = segments.Seg14x4(board.I2C(), address)
        self._segments.auto_write = False

@jerryneedell
Copy link
Collaborator

updated to current master CP -- same result


Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-beta.2-141-g2c9fbb5d4 on 2019-02-24; Particle Argon with nRF52840
>>> 
>>> import uv_temp_test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "uv_temp_test.py", line 10, in <module>
  File "/lib/adafruit_sht31d.py", line 95, in __init__
  File "/lib/adafruit_bus_device/i2c_device.py", line 66, in __init__
AttributeError: 'function' object has no attribute 'try_lock'
>>> 


still works with my version

@dhalbert
Copy link
Collaborator

Is someone calling board.I2C instead of board.I2C() ?

@jerryneedell
Copy link
Collaborator

jerryneedell commented Feb 28, 2019

sorry - no @makermelissa has

import board
try:
    I2C_BUS = board.I2C()
except AttributeError:
    import busio
    I2C_BUS = busio.I2C(board.SCL, board.SDA)

@jerryneedell
Copy link
Collaborator

and the failure is on the sht31d device, not on the featherwing

@jerryneedell
Copy link
Collaborator

jerryneedell commented Feb 28, 2019

if I change the test code to this -- it works with the new featherwing code
the changes are to import shared and then call shared.I2C_BUS for the additional sensors

While this works, I think it makes more sense to just eliminate shared.py.

import time
import board
import busio
import adafruit_sht31d
import adafruit_veml6070

from adafruit_featherwing import alphanum_featherwing,shared

display = alphanum_featherwing.AlphaNumFeatherWing()
sensor = adafruit_sht31d.SHT31D(shared.I2C_BUS)
uv = adafruit_veml6070.VEML6070(shared.I2C_BUS)



loopcount = 0
while True:
    uv_raw = uv.read
    risk_level = uv.get_index(uv_raw)
    print('Reading: {0} | Risk Level: {1}'.format(uv_raw, risk_level))
    display.print(uv_raw)
    time.sleep(2)
    temperature = sensor.temperature
    print("\nTemperature: %0.1f C" % temperature)
    display.print(temperature)
    print("Humidity: %0.1f %%" % sensor.relative_humidity)
    loopcount += 1
    time.sleep(2)
    # every 10 passes turn on the heater for 1 second
    if loopcount == 10:
        loopcount = 0
        sensor.heater = True
        print("Sensor Heater status =", sensor.heater)
        time.sleep(1)
        sensor.heater = False
        print("Sensor Heater status =", sensor.heater)


Both this is a discussion fo rthe library
Is it acceptable for the SAMD51 to crash to safe mode in this case?

@jerryneedell
Copy link
Collaborator

jerryneedell commented Feb 28, 2019

Ran both version on a feather_m4_ express -- the original version reproduces the safe mode crash
the modified version above work normally.

While this works, I think it makes more sense to just eliminate shared.py.
But this is a discussion for the featherwing library
Is it acceptable for the SAMD51 to crash to safe mode in the orginal case? Why does the nrf throw an error, but the SAMD51 crashes

@jerryneedell
Copy link
Collaborator

FYI -- the safe mode crash on the SAMD51 is

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

You are running in safe mode which means something unanticipated happened.
Looks like our core CircuitPython code crashed hard. Whoops!
Please file an issue at https://github.com/adafruit/circuitpython/issues
 with the contents of your CIRCUITPY drive and this message:
Crash into the HardFault_Handler.

Press any key to enter the REPL. Use CTRL-D to reload.



@dhalbert
Copy link
Collaborator

No, it shouldn't crash.

@dhalbert
Copy link
Collaborator

dhalbert commented Feb 28, 2019

I'm trying to reproduce this in the simplest way possible, and not succeeding. Are you saying that your shared.py has:

import board
try:import board
try:
    I2C_BUS = board.I2C()
except AttributeError:
    import busio
    I2C_BUS = busio.I2C(board.SCL, board.SDA)

And then you get a crash when referencing board.I2C() in other code?
The simple REPL version of this on a board with board.I2C() (I'm testing on a Metro M4) is

Adafruit CircuitPython 4.0.0-beta.2-141-g2c9fbb5d4 on 2019-02-26; Adafruit Metro M4 Express with samd51j19
>>> import board,busio
>>> i = board.I2C()
>>> j = board.I2C()
>>> i == j
True

which is what I'd expect. And if I try this, I get an expected error:

>>> import board,busio
>>> i = busio.I2C(board.SCL, board.SDA)
>>> j = board.I2C()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: SDA in use

@makermelissa
Copy link
Collaborator Author

I couldn't get it to happen in the REPL either and I wondered if it might have something to do with calling it in different files or through an import or something. Also, the entire contents of shared.py is basically what @jerryneedell posted above.

@makermelissa
Copy link
Collaborator Author

I also tried commenting out everything except this in shared and it still crashed.

import board
I2C_BUS = board.I2C()

@dhalbert
Copy link
Collaborator

This might have to do with class and global dictionaries or something like that. I'm not sure it's related to I2C at all, really. If you can give me the simplest test case you can muster that would be really helpful. Thanks.

@makermelissa
Copy link
Collaborator Author

Ok, I'll keep playing with it and see what I can come up with.

@makermelissa
Copy link
Collaborator Author

I kept trying to boil this down and even just removing a little of the SHT31D module made it behave as expected. It seems to be some kind of bad combination of things. I can go ahead and close this is you want or leave it open for later.

@makermelissa
Copy link
Collaborator Author

Nevermind, I got it to crash again, so I'll keep working on it.

@dhalbert
Copy link
Collaborator

dhalbert commented Mar 1, 2019

I can go ahead and close this is you want or leave it open for later.\

No, please leave it open. A crash is a crash, and needs to be fixed.

@makermelissa
Copy link
Collaborator Author

Ok, thanks Danh. I'll leave it be.

@tannewt tannewt added this to the 4.0.0 - Bluetooth milestone Mar 8, 2019
@tannewt
Copy link
Member

tannewt commented Mar 13, 2019

What is the smallest repro case we have for this? I can take a look tomorrow.

@makermelissa
Copy link
Collaborator Author

Other than the scenario I originally described, I haven't been able to get it to reproduce with anything smaller.

@tannewt
Copy link
Member

tannewt commented Mar 14, 2019

I've reproduced this on a Feather M4. Will now try on Metro M4 where I can run a debugger.

@tannewt tannewt self-assigned this Mar 14, 2019
@tannewt
Copy link
Member

tannewt commented Mar 14, 2019

I've reproduced this on Metro M4 and confirmed it's long-lived related. (The bug disappears if I turn long-living off.) Still digging into why.

dhalbert pushed a commit that referenced this issue Mar 15, 2019
Without long living them you may clone them when long living a
module that uses them.

Fixes #1603
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants