此问题仅与 3.5 之前的 spidev 版本有关。下面的评论是在假设我使用 spidev 的升级版本的情况下完成的。
#################################################### ############################
我可以确认这个问题。它对于 RPi3B 和 RPi4B 都是持久的。在 RPi3 和 RPi4 上使用 python 3.7.3。我尝试过的spidev版本是3.3、3.4和最新的3.5。通过简单地循环这一行,我能够多次重现此错误。
spidevice2.xfer2([0x00, 0x00, 0x00, 0x00])
根据 RPi 版本,最多需要 11 小时。在 1073014000 次调用(四舍五入到 1000)之后,脚本因“无效指针”而崩溃。发送的总字节数与中相同danmcb的情况。看起来 2^32 字节代表了一个限制。
我尝试了不同的方法。例如,时不时地调用 close(),然后调用 open()。这没有帮助。
然后,我尝试在本地创建 spiDev 对象,以便为每批数据重新创建它。
def spiLoop():
spidevice2 = spidev.SpiDev()
spidevice2.open(0, 1)
spidevice2.max_speed_hz = 15000000
spidevice2.mode = 1 # Data is clocked in on falling edge
for j in range(100000):
spidevice2.xfer2([0x00, 0x00, 0x00, 0x00])
spidevice2.close()
大约之后它仍然崩溃。 xfer2([0x00, 0x00, 0x00, 0x00]) 的 2^30 次调用相当于大约2^32 字节。
EDIT1
为了加快该过程,我使用下面的代码以 4096 字节的块进行发送。我在本地反复创建了 SpiDev 对象。花了 2 个小时才达到 2^32 字节数。
def spiLoop():
spidevice2 = spidev.SpiDev()
spidevice2.open(0, 1)
spidevice2.max_speed_hz = 25000000
spidevice2.mode = 1 # Data is clocked in on falling edge
to_send = [0x00] * 2**12 # 4096 bytes
for j in range(100):
spidevice2.xfer2(to_send)
spidevice2.close()
del spidevice2
def runSPI():
for i in range(2**31 - 1):
spiLoop()
print((2**12 * 100 * (i + 1)) / 2**20, 'Mbytes')
EDIT2
即时重新加载 spidev 也没有帮助。我在 RPi3 和 RPi4 上尝试了此代码,结果相同:
import importlib
def spiLoop():
importlib.reload(spidev)
spidevice2 = spidev.SpiDev()
spidevice2.open(0, 1)
spidevice2.max_speed_hz = 25000000
spidevice2.mode = 1 # Data is clocked in on falling edge
to_send = [0x00] * 2**12 # 4096 bytes
for j in range(100):
spidevice2.xfer2(to_send)
spidevice2.close()
del spidevice2
def runSPI():
for i in range(2**31 - 1):
spiLoop()
print((2**12 * 100 * (i + 1)) / 2**20, 'Mbytes')
EDIT3
执行代码片段也没有隔离问题。在发送第 4 个 1G 字节数据后,它崩溃了。
program = '''
import spidev
spidevice = None
def configSPI():
global spidevice
# We only have SPI bus 0 available to us on the Pi
bus = 0
#Device is the chip select pin. Set to 0 or 1, depending on the connections
device = 1
spidevice = spidev.SpiDev()
spidevice.open(bus, device)
spidevice.max_speed_hz = 250000000
spidevice.mode = 1 # Data is clocked in on falling edge
def spiLoop():
to_send = [0xAA] * 2**12
loops = 1024
for j in range(loops):
spidevice.xfer2(to_send)
return len(to_send) * loops
configSPI()
bytes_total = 0
while True:
bytes_sent = spiLoop()
bytes_total += bytes_sent
print(int(bytes_total / 2**20), "Mbytes", int(1000 * (bytes_total / 2**30)) / 10, "% finished")
if bytes_total > 2**30:
break
'''
for i in range(100):
exec(program)
print("program executed", i + 1, "times, bytes sent > ", (i + 1) * 2**30)