-
Notifications
You must be signed in to change notification settings - Fork 7
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
Framing error #7
Comments
Hi, can you give me an example of code that I can verify? P.S. |
Close for no, reopen it if you need help. |
Apologies, I am not sure how I missed your response! dmazella_imitation_BLESPItest.txt In the file I attached (which I ran from the REPL), I attempted to copy your SPI code almost line-for-line, and was met with the same issue I described above. As you can see, I did have to port my code to fit the microcontroller I was using, the STM32 B-L475E-IOT01A, which contains an SPBTLE-RF on board. |
no problem, ➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/ww.py
bytearray(b'\x04\x10\x01\x00')
➜ micropython (master) ✗ Adding the reset, the behavior is correct: ➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/ww.py
bytearray(b'\x04\xff\x03\x01\x00\x01')
➜ micropython (master) ✗ This is the code I tried: # hail mary BLE SPI test
import machine
import pyb
import utime
import micropython
from micropython import const
from machine import Pin
# spi = machine.SPI(3, baudrate=8000000, polarity=0, phase=0,
# bits=8, firstbit=machine.SPI.MSB)
spi = machine.SPI(2, baudrate=8000000, polarity=0)
#CS = Pin('D13', Pin.OUT_PP, pull=Pin.PULL_NONE)
CS = machine.Pin('B12', machine.Pin.OUT_PP)
CS.on()
#RS = Pin('A8', Pin.OUT_PP, pull=Pin.PULL_NONE)
RS = machine.Pin('B9', machine.Pin.OUT_PP)
RS.on()
_READ_HEADER_MASTER = b'\x0B\x00\x00\x00\x00'
_WRITE_HEADER_MASTER = b'\x0A\x00\x00\x00\x00'
HCI_READ_PACKET_SIZE = const(128)
# IR = Pin('E6', Pin.IN, pull=Pin.PULL_DOWN)
IR = machine.Pin('B8', machine.Pin.IN, machine.Pin.PULL_DOWN)
class CSContext(object):
def __init__(self, pin):
self._pin = pin
def __enter__(self):
# Assert CS line
self._pin.off()
def __exit__(self, exc_type, exc_value, traceback):
# Release CS line
self._pin.on()
# return all(map(lambda x: x is None, [exc_type, exc_value, traceback]))
def write(retry=5, header=b'\x10\x03', param=0):
"""
Write packet to BlueNRG-MS module
"""
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
result = None
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_WRITE_HEADER_MASTER,
_rw_header_slave
)
rx_write_bytes = _rw_header_slave[1]
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and (
rx_write_bytes > 0 or rx_read_bytes > 0):
# SPI is ready
if header:
# avoid to write more data that size of the buffer
if rx_write_bytes >= len(header):
result = bytearray(len(header))
spi.write_readinto(header, result)
if param:
rx_write_bytes -= len(header)
# avoid to read more data that size of the
# buffer
if len(param) > rx_write_bytes:
tx_bytes = rx_write_bytes
else:
tx_bytes = len(param)
result = bytearray(tx_bytes)
spi.write_readinto(param, result)
break
else:
break
else:
break
else:
break
else:
utime.sleep_us(50)
retry -= 1
return result
def read(size=HCI_READ_PACKET_SIZE, retry=5):
"""
Read packet from BlueNRG-MS module
"""
result = None
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_READ_HEADER_MASTER,
_rw_header_slave
)
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and rx_read_bytes > 0:
# SPI is ready
# avoid to read more data that size of the buffer
if rx_read_bytes > size:
rx_read_bytes = size
data = b'\xFF' * rx_read_bytes
result = bytearray(rx_read_bytes)
spi.write_readinto(data, result)
break
else:
utime.sleep_us(50)
retry -= 1
# Add a small delay to give time to the BlueNRG to set the IRQ pin low
# to avoid a useless SPI read at the end of the transaction
utime.sleep_us(150)
return result
def run():
# reset
RS.off()
utime.sleep_us(5)
RS.on()
utime.sleep_us(5)
write() # retry=5, header=b'\x10\x03', param=0)
while True:
utime.sleep_us(12)
if (IR.value() == 1):
hi = read(size=HCI_READ_PACKET_SIZE, retry=5)
print(hi)
break
utime.sleep_us(25)
run() Let me know how it goes. |
Ok, I probably should have mentioned in my previous post that I always reset the BlueNRG-MS module before running the code. My mistake. When I run the code you posted, I get the correct initialization response like you did, but all of my following commands are met with the 0x04 0x10 0x01 0x00 error code. Below is an example with a few further modifications I added to continuously send commands to the chip. As you can see, I am trying to send the HCI_Read_Local_Supported_Features command. I get the same response if I send HCI_Read_Local_Supported_Commands, HCI_Read_Remote_Version_Information, or HCI_Read_Local_Version_Information as defined on page 7 in the blueNRG-MS document found here: code:
and here is the output from the REPL:
|
with your example: # hail mary BLE SPI test
import machine
import pyb
import ustruct
import utime
import micropython
from micropython import const
from machine import Pin
# spi = machine.SPI(3, baudrate=8000000, polarity=0, phase=0,
# bits=8, firstbit=machine.SPI.MSB)
spi = machine.SPI(2, baudrate=8000000, polarity=0)
#CS = Pin('D13', Pin.OUT_PP, pull=Pin.PULL_NONE)
CS = machine.Pin('B12', machine.Pin.OUT_PP)
CS.on()
#RS = Pin('A8', Pin.OUT_PP, pull=Pin.PULL_NONE)
RS = machine.Pin('B9', machine.Pin.OUT_PP)
RS.on()
_READ_HEADER_MASTER = b'\x0B\x00\x00\x00\x00'
_WRITE_HEADER_MASTER = b'\x0A\x00\x00\x00\x00'
HCI_READ_PACKET_SIZE = const(128)
# IR = Pin('E6', Pin.IN, pull=Pin.PULL_DOWN)
IR = machine.Pin('B8', machine.Pin.IN, machine.Pin.PULL_DOWN)
class CSContext(object):
def __init__(self, pin):
self._pin = pin
def __enter__(self):
# Assert CS line
self._pin.off()
def __exit__(self, exc_type, exc_value, traceback):
# Release CS line
self._pin.on()
# return all(map(lambda x: x is None, [exc_type, exc_value, traceback]))
def write(retry=5, header=b'', param=0):
"""
Write packet to BlueNRG-MS module
"""
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
result = None
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_WRITE_HEADER_MASTER,
_rw_header_slave
)
rx_write_bytes = _rw_header_slave[1]
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and (
rx_write_bytes > 0 or rx_read_bytes > 0):
# SPI is ready
if header:
# avoid to write more data that size of the buffer
if rx_write_bytes >= len(header):
result = bytearray(len(header))
spi.write_readinto(header, result)
if param:
rx_write_bytes -= len(header)
# avoid to read more data that size of the
# buffer
if len(param) > rx_write_bytes:
tx_bytes = rx_write_bytes
else:
tx_bytes = len(param)
result = bytearray(tx_bytes)
spi.write_readinto(param, result)
break
else:
break
else:
break
else:
break
else:
utime.sleep_us(50)
retry -= 1
return result
def read(size=HCI_READ_PACKET_SIZE, retry=5):
"""
Read packet from BlueNRG-MS module
"""
result = None
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_READ_HEADER_MASTER,
_rw_header_slave
)
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and rx_read_bytes > 0:
# SPI is ready
# avoid to read more data that size of the buffer
if rx_read_bytes > size:
rx_read_bytes = size
data = b'\xFF' * rx_read_bytes
result = bytearray(rx_read_bytes)
spi.write_readinto(data, result)
break
else:
utime.sleep_us(50)
retry -= 1
# Add a small delay to give time to the BlueNRG to set the IRQ pin low
# to avoid a useless SPI read at the end of the transaction
utime.sleep_us(150)
return result
def run():
# reset
RS.off()
utime.sleep_us(5)
RS.on()
utime.sleep_us(5)
# wait event "device ready"
while True:
if IR.value() and read() == b'\x04\xff\x03\x01\x00\x01':
break
# HCI_Read_Local_Version_Information: OGF: 0x04 OCF: 0x01 OPCODE: 0x1001
param = b''
ogf = 0x04
ocf = 0x01
opcode = ustruct.pack("<H", (ocf & 0x03ff) | (ogf << 10)) # OPCODE
header = ustruct.pack("<B3s", 0x01, opcode)
print(header, param)
write(header=header, param=param)
while True:
if IR.value():
hi = read()
print("-------", hi)
break
# HCI_Read_Local_Supported_Features: OGF: 0x04 OCF: 0x03 OPCODE: 0x1003
param = b''
ogf = 0x04
ocf = 0x03
opcode = ustruct.pack("<H", (ocf & 0x03ff) | (ogf << 10)) # OPCODE
header = ustruct.pack("<B3s", 0x01, opcode)
print(header, param)
write(header=header, param=param)
while True:
if IR.value():
hi = read()
print("-------", hi)
break
run() expected output: ➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/test_uble.py
b'\x01\x01\x10\x00' b''
------- bytearray(b'\x04\x0e\x0c\x01\x01\x10\x00\x07\x071\x070\x00#\x00')
b'\x01\x03\x10\x00' b''
------- bytearray(b'\x04\x0e\x0c\x01\x03\x10\x00\x00\x00\x00\x00`\x00\x00\x00')
➜ micropython (master) ✗ Please try it and give me feedback. |
It worked! I can't believe it. The issue was definitely the header format. For example, when I told you I sent the HCI_Read_Local_Supported_Features command, I was sending the header in a simple bytearray as it was given in the spec: OpCode = 0x1003. I can't thank you enough, especially because you mentioned this is an old project. Without your help I doubt I ever would have ever solved this problem. I am a relative newcomer when it comes to embedded python, and never would have thought to use a struct. Many thanks! |
I'm glad that everything works. Best regards, |
Apologies, this is not an issue with your library
I am writing an application the STM32 B-L475E-IOT01A discovery board that uses the SPBTLE-RF BlueNRG chip as well.
I have been dealing with the following issue for a few days now. If you ever encountered a similar issue, I am wondering what you did to fix it.
The Issue:
I am having trouble interfacing with the B-L475E-IOT01A's on-board SPBTLE-RF bluetooth chip.
I am able to send header packets inquiring about the the bluetooth chip's write and read buffers. I have confirmed that I am doing this correctly, because I get responses in the correct format: 0x02 0x?? 0x00 0x?? 0x00. The ?? bytes always give me the correct number of available writable bytes and bytes to be read, respectively.
I am also able to read messages from the bluetooth chip, as I always receive the expected packet when I perform a chip reset: 0x04 0xff 0x03 0x01 0x00 0x01, and after sending an HCI command packet I am able to poll for and read the responses described below.
The issue that I am having is that, whenever I check that the write buffer is available and attempt to send a full write message such as ...
header = 0x0A 0x00 0x00 0x00 0x00 (check write buffer... only sends rest of message if write buffer > 0)
HCI command packet = 0x1003 (example: Read_Local_Supported_Features)
param total length = 0x00 (i have also tried not including this byte at all and raising the chip select one byte sooner instead)
params: none
... I always receive the same HCI event packet in response, no matter the contents of my HCI command packet's body:
response: 0x04 0x10 0x01 0x00
This implies that I am having a hardware framing error with my SPI, and I have no idea what may be causing that. As I just described, the rest of the processes work fine, so the SPI bus seems to be functional in most cases.
Note: My send an receive methods are almost identical in structure to yours
If you can offer me any advice, I would appreciate it immensely. Otherwise, thank you for the awesome library!
The text was updated successfully, but these errors were encountered: