NordicSemiconductor / pc-ble-driver-py

Python bindings for the ble-driver library
Other
126 stars 115 forks source link

pc_ble_driver_py.exceptions.NordicSemiException: Failed to open. Error code: 13 #29

Closed thomafred closed 7 years ago

thomafred commented 7 years ago

Installed package using pip on a Ubuntu 16.04 system using PCA10040 NRF52832 development kit.

When attempting to run example advertising.py, I get error code 13.

Steps to (hopefully) reproduce on Ubuntu 16.04 platform, assuming PCA10040 powered and connected to serial interface /dev/ttyACM0 using usb-connection.

$ pip install pc-ble-driver-py
{...}
$ wget https://raw.githubusercontent.com/NordicSemiconductor/pc-ble-driver-py/master/python/pc_ble_driver_py/examples/advertising.py
{...}
$  python advertising.py nrf52 /dev/ttyACM0                     
Serial port used: /dev/ttyACM0
Traceback (most recent call last):
  File "advertising.py", line 79, in <module>
    main(sys.argv[2])
  File "advertising.py", line 55, in main
    driver.open()
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 126, in wrapper
    raise NordicSemiException('Failed to {}. Error code: {}'.format(wrapped.__name__, err_code))
pc_ble_driver_py.exceptions.NordicSemiException: Failed to open. Error code: 13
bencefr commented 7 years ago

@thomafred , would you please check that your user has permission to access the serial device? You should probably be member of the dialup group.

thomafred commented 7 years ago

My user is a member of the group dialout. In addition, the script does not seem to work when running as root or when I change the permissions of the serial interface:

chmod 777 /dev/ttyACM0

I should also add that nrfconnect (version 2.0.0) has to be run as root.

bencefr commented 7 years ago

I just tried and it works as expected. Well not as I expect, but as intended.

You shouldn't just chmod 777 ... anything that is not executable - without owner permissions it wouldn't work anyway - and out of the box /dev/ttyACM0 should appear og+rw (root,dialout) on your box. If the serial port permissions are only o+rw (root,root):

$ ls -l /dev/ttyACM0
crw------- 1 root root 166, 0 Jul 26 08:43 /dev/ttyACM0

then you probably don't have SEGGER tools installed, so the USB device is not identified as a dialout device. It should be:

$ ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Jul 26 08:43 /dev/ttyACM0

You also need to have nrfjprog installed, you'll find these tools here. The nrfjprog package is a mess, just make sure to include the directory of nrfjprog binary in your $PATH.

If you have all these in place it should work.

I should also mention that nRF Connect 2.0 should NOT be run as root, just as any other gui app, that indicates that your environment is not setup correctly.

thomafred commented 7 years ago

I indeed do have the SEGGER tools installed (regularly host a GDB server on a JLink Plus). In addition, my user is a member of dialout, hence the permission-string do match your example (see below).

nrfjprog was not int my PATH. However I had mad a change to the script, setting auto_flash=False, thinking that the image flashed from nrfconnect was sufficient. Assuming this is incorrect, I reverted the change and put nrfjprog into PATH. This prompts a new error 33 (see below).

I have not found any description of the error codes. Do they match errno? (Error code 33 indicates EDOM - "Math argument out of domain of func")

$ ls -l /dev/ttyACM0 
crw-rw---- 1 root dialout 166, 0 juli  26 13:38 /dev/ttyACM0

$ groups ${USER}
tom : tom adm dialout cdrom sudo {...}

$ nrfjprog --version
nrfjprog version: 9.5.0
JLinkARM.dll version: 6.16b

$ python -c "import subprocess; subprocess.call(['nrfjprog --version'], shell=True)"
nrfjprog version: 9.5.0
JLinkARM.dll version: 6.16b

$ python advertising.py NRF52 /dev/ttyACM0
Serial port used: /dev/ttyACM0
Traceback (most recent call last):
  File "advertising.py", line 79, in <module>
    main(sys.argv[2])
  File "advertising.py", line 50, in main
    driver      = BLEDriver(serial_port=serial_port, auto_flash=True)
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 930, in __init__
    if flasher.fw_check() == False:
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 870, in fw_check
    data    = self.read(addr = 0x20000, size = 4)
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 880, in read
    data = self.call_cmd(args)
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/wrapt/decorators.py", line 440, in _synchronized
    return wrapped(*args, **kwargs)
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 908, in call_cmd
    return subprocess.check_output(args + [self.family], stderr=subprocess.STDOUT)
  File "/opt/anaconda/anaconda/lib/python2.7/subprocess.py", line 219, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['nrfjprog', '--snr', '682371416', '--memrd', '131072', '--w', '8', '--n', '4', '--family', 'NRF52']' returned non-zero exit status 33
bencefr commented 7 years ago

It's looks like nrfjprog exited with 33, I don't know if that's errno. Could you now check the output of:

$ nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52
thomafred commented 7 years ago

There seem to be an issue with connecting to the JLINK via USB (see log below)

$ nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52 --log
ERROR: JLinkARM DLL reported an error. Try again. If error condition
ERROR: persists, run the same command again with argument --log, contact Nordic
ERROR: Semiconductor and provide the generated log.log file to them.

$ echo $?
33

$ cat log.log 
--------------------------------------------------------------------------------
nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52 --log
nrfjprog verion 9.5.0
--------------------------------------------------------------------------------
FUNCTION: open_dll.
FUNCTION: open_dll.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: connect_to_emu_with_snr.
FUNCTION: connect_to_emu_with_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
JLinkARM.dll OpenEx returned error 'Cannot connect to J-Link via USB.'.
FUNCTION: close_dll.
FUNCTION: close_dll.
bencefr commented 7 years ago

This is an error lower than the Nordic stack and too generic to know exactly what is wrong. So you can try - if you haven't yet:

  1. to disconnect the device and reconnect it, and try again
  2. install the latest SEGGER software (prior 6.16c it is known to have issues with udev rules), and try again
  3. install the latest nRF5x package (9.6.0 currently), and try again

If everything fails, please include output of lsusb too. Can you also disclose where did you get the device from? (I just read about blacklisted JLink serial numbers, let's eliminate that case.)

thomafred commented 7 years ago

It turned out that I had version 6.16b of the segger software. However, installing 6.16j did not fix my issue, neither did reinstalling the nRF5x package (version 9.6.0).

Here is the appropriate extract from lsusb:

$ lsusb
{...}
Bus 003 Device 013: ID 1366:1015 SEGGER
{...}

I remember having some issues when I initially started to use my JLink Plus as well, and that UDEV-rules were the problem. However this was fixed by making some changes to the file /etc/udev/rules.d/99-jlink.rules. Here is an extract of file in its current state:

ATTR{idProduct}=="0101", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0102", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0103", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0104", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0105", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0107", ATTR{idVendor}=="1366", MODE="666"
ATTR{idProduct}=="0108", ATTR{idVendor}=="1366", MODE="666"

## PCA10040
ATTR{idProduct}=="0115", ATTR{idVendor}=="1366", MODE="666" 

I added the last line, tagged PCA10040, seeing as the idProduct of the PCA10040 was not included in this list. After this I reloaded the udev-rules:

$ sudo udevadm control --reload-rules && sudo udevadm trigger

However, my problem still remains the same.

bencefr commented 7 years ago

What are the state of the LED-5 (LD5) of your device? Is it on/off/blinks(slowly/quickly)? Also could you repeat the nrfjprog line as root?

$ sudo nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52
thomafred commented 7 years ago

LED-5 seem to be on with quick intensity "dips" at ~1 second intervals.

Running nrfjprog as root does work:

$ sudo ~/app/nrfjprog/nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52 
0x00020000: 17 A5 D8 46 

(note nrfjprog is not in PATH for the root-user, hence the full path to the executable)

thomafred commented 7 years ago

I noticed a mistake in my udev rules:

ATTR{idProduct}=="0115", ATTR{idVendor}=="1366", MODE="666" 

should be

ATTR{idProduct}=="1015", ATTR{idVendor}=="1366", MODE="666" 

i.e. (idProdcut set to 1015, not 0015).

After this fix, nrfjprog no longer returns an error, and seemingly flashes the card.

$ nrfjprog --snr 682371416 --memrd 131072 --w 8 --n 4 --family NRF52 --log
0x00020000: 17 A5 D8 46                                       |...F|

However, the examples advertising.py and heart_rate_collector.py still returns errors:

$ python advertising.py NRF52 /dev/ttyACM0
Serial port used: /dev/ttyACM0
Traceback (most recent call last):
  File "advertising.py", line 79, in <module>
    main(sys.argv[2])
  File "advertising.py", line 55, in main
    driver.open()
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 126, in wrapper
    raise NordicSemiException('Failed to {}. Error code: {}'.format(wrapped.__name__, err_code))
pc_ble_driver_py.exceptions.NordicSemiException: Failed to open. Error code: 3

Running the script a second time immidiately after the first attempt prompts a different error code, but still stating that it fails to open:

$ python advertising.py NRF52 /dev/ttyACM0
Serial port used: /dev/ttyACM0
Traceback (most recent call last):
  File "advertising.py", line 79, in <module>
    main(sys.argv[2])
  File "advertising.py", line 55, in main
    driver.open()
  File "/opt/anaconda/anaconda/lib/python2.7/site-packages/pc_ble_driver_py/ble_driver.py", line 126, in wrapper
    raise NordicSemiException('Failed to {}. Error code: {}'.format(wrapped.__name__, err_code))
pc_ble_driver_py.exceptions.NordicSemiException: Failed to open. Error code: 13
bencefr commented 7 years ago

I don't think the LED5 should be blinking. It is constant on for me. Depending on the rate of blinking the device either is sleeping or is in bootloader mode. You'll need to reset it which can be done with the RESET button or by nrfjprog --snr ... -f NRF52 -r .

thomafred commented 7 years ago

Resetting the card still does not solve the problem with the scripts not running.

I suppose one could say that the LED is constantly on, however the seem to be some activity. Any changes in with LED seem to be very quick, and is not immediately noticeable.

bencefr commented 7 years ago

In this case the LED is fine, it's not in bootloader mode.

bencefr commented 7 years ago

Alright, next you could try to get to flash the connectivity firmware again, which is done by the pc-ble-driver automatically. You only need to erase the device by nrfjprog --snr ... -f NRF52 -e . After that running the script will open the driver which starts by reflashing the fw.

thomafred commented 7 years ago

This seem to have solved to problem.

It appears that the firmware must be erased manually if it is not already flashed.

For my use case, where I regularly have to use nrfconnect, the erase-command must be run prior to executing any script using the pc-ble-driver-py - library.