loboris / MicroPython_K210_LoBo

MicroPython implementation for Kendryte K210
128 stars 24 forks source link

I2C device already used / Error initializing I2C hardware #5

Closed Qutix closed 4 years ago

Qutix commented 4 years ago

Hello!

This piece of code used to work before. Now all I get is:

from machine import I2C

i2c = I2C(0, freq=100000, scl=40, sda=41)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: I2C device already used

i2c = machine.I2C(1, freq=100000, scl=40, sda=41)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Error initializing I2C hardware

This code runs after a restart so there should be nothing using/locking any I2C hardware.

Can I somehow see what hardware is being used and maybe grab it's reference via a global "getter" method? Is this a bug that you can/could reproduce?

loboris commented 4 years ago

No, I cannot reproduce this. I've tried by adding the following code to "boot.py":

print("Initializing i2c")

import machine
from machine import I2C

i2c = I2C(0, freq=100000, scl=40, sda=41)

print(i2c)

machine.pinstat()

print("boot.py done")

Here is the result after reset:

M (3219) [MAIXPY]: Configuration loaded from flash
Q (7734) [MAIXPY]: PLL0=988000000, PLL1=398666666, PLL2=45066666, SPI3clk=494000000
Q (16067) [MAIXPY]: RAM buffer of 1024 bytes allocated at 0x80596500
M (25234) [MAIXPY]: Heaps: FreeRTOS=3748 KB (811 KB free), MPy=2852 KB, other=419 KB
Initializing i2c
I2C (Device=0, Mode=MASTER, Speed=100000 Hz, sda=41, scl=40)
 Pin  GpioHS     Used by      as  Fpioa
---------------------------------------
   4       -    ISP_UART      Rx     18
   5       -    ISP_UART      Tx     19
  40       -         I2C     scl    126
  41       -         I2C     sda    127
---------------------------------------
boot.py done

 __  __              _____  __   __  _____   __     __ 
|  \/  |     /\     |_   _| \ \ / / |  __ \  \ \   / /
| \  / |    /  \      | |    \ V /  | |__) |  \ \_/ / 
| |\/| |   / /\ \     | |     > <   |  ___/    \   /  
| |  | |  / ____ \   _| |_   / . \  | |         | |   
|_|  |_| /_/    \_\ |_____| /_/ \_\ |_|         |_|
------------------------------------------------------

MaixPy-FreeRTOS by LoBo v1.11.6
-------------------------------
MicroPython 1.11.6 (eecb962-dirty) built on 2019-07-27; Sipeed_board with Kendryte-K210
Type "help()" for more information.
>>> i2c
I2C (Device=0, Mode=MASTER, Speed=100000 Hz, sda=41, scl=40)
>>> 

To check the hardware used, you can use the machine.pinstat(). The only used hardware after reset is HSUART (gpios 4&5) which is used for REPL serial communication and SPI3 used for accessing the Flash memory.

Have you started any other hardware before I2C ?

Qutix commented 4 years ago

Dang it. I miss the "import machine" line. I am only doing the "from machine import I2C". It's a mistake on my end. Some other scripts might have imported that for me previously. Sorry.

If you remove that import then it complains about already used resource, instead of missing module which is wierd.

loboris commented 4 years ago

import machine should not be necessary. I've put it only for calling machine.pinstat().

Qutix commented 4 years ago

Wierd. This is what I get:

MPY: soft reboot
boot.py found on SD card. About to start running it...
pinstat before i2c init
 Pin  GpioHS     Used by      as  Fpioa
---------------------------------------
   4       -    ISP_UART      Rx     18
   5       -    ISP_UART      Tx     19
  26       -     SD Card   data1     71
  27       -     SD Card     clk     83
  28       -     SD Card   data0     70
  29       0     SD Card      cs     24
  40       -         I2C     scl    126
  41       -         I2C     sda    127
---------------------------------------
Traceback (most recent call last):
  File "/flash/boot.py", line 17, in <module>
  File "boot.py", line 10, in <module>
OSError: I2C device already used

And here is my boot.py:


import machine
from machine import I2C
import time

from Power import BQ27531

print('pinstat before i2c init')
machine.pinstat()

i2c = I2C(0, freq=100000, scl=40, sda=41)
pwr = BQ27531(i2c)

print('pinstat after i2c init')
machine.pinstat()

i = 0
while True:
    print(i)
    print(pwr.read_temperature())
    time.sleep(1)
    i = i + 1
    if i == 3:
        break
Qutix commented 4 years ago

After unpowering the device and doing a cold start I can start i2c. If I do a software restart it says it's been already used. Like a soft reset does not clear the resource usage.

loboris commented 4 years ago

I see you are doing "soft reboot" by pressing the Ctrl-D. This only restarts the REPL and does not initialize the hardware.

To make a proper soft reset you must use the machine.reset().

Qutix commented 4 years ago

Ahh. Since boot.py is executed on each "soft reboot" I thought the resources are cleared. Okay. Now I know. Thanks!

loboris commented 4 years ago

Well, it is kind of a bug. The used peripherals should be deinitialized, but they are currently not. Thanks for reminding me to check it.