Hi!
I have a project where I need to communicate via SPI with an STM32F439ZI. I found on this forum that there also people that occurs this problem. I`m using DMA mode on STM32, but it seems SPI class from Micropython library does not as proposed to. Also, I saw that there is a RPC library, however it is unclear how to use it in connection with a microcontroller such as STM32.
Hi, are you using an OpenMV Cam?
Also, your question is not specific. You say it works strange. Not much to help there. Keep in mind DMA only does 65536 bytes at a time.
Hi, yes I am using an OpenMV H7 cam. I have 2 of them so I need both to be slave in SPI communication. There is a problem at synchronization. I was trying to use pyb.ExtInt() to set an interrupt when CS pin is set to low level. When using this method, on Master I see 95 when I should see 85. Here is also the code:
OpenMV Code:
type or paste code here
# This work is licensed under the MIT license.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# SPI with the Arduino as the master device and the OpenMV Cam as the slave.
#
# Please wire up your OpenMV Cam to your Arduino like this:
#
# OpenMV Cam Master Out Slave In (P0) - Arduino Uno MOSI (11)
# OpenMV Cam Master In Slave Out (P1) - Arduino Uno MISO (12)
# OpenMV Cam Serial Clock (P2) - Arduino Uno SCK (13)
# OpenMV Cam Slave Select (P3) - Arduino Uno SS (10)
# OpenMV Cam Ground - Arduino Ground
import pyb
import struct
import time
text = "Hello World!\n"
data = struct.pack("<bi%ds" % len(text), 85, len(text), text) # 85 is a sync char.
data1 = struct.pack("<bBBBB", 85, 1, 2, 3, 4)
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)
def nss_callback(line):
global spi, data, data1
try:
spi.send(data1, timeout=1000)
except OSError as err:
pass # Don't care about errors - so pass.
# Note that there are 3 possible errors. A timeout error, a general purpose error, or
# a busy error. The error codes are 116, 5, 16 respectively for "err.arg[0]".
# Configure NSS/CS in IRQ mode to send data when requested by the master.
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)
while True:
time.sleep_ms(1000)
STM32 code (Configured on SPI Mode 0 with DMA Interrupt on):
uint8_t data[4] = {0};
volatile uint8_t rxDone = 1;
volatile uint8_t synced = 1;
uint8_t msgCounter = 0;
uint8_t testTxBuffer[8] = {0x0A, 0X0B, 0XA0, 0XB0, 0XAA, 0X80, 0X80, 0XFF};
uint8_t testRxBuffer[4] = {0};
char test[128] = {0};
int32_t len = 0xFF;
uint8_t l = 0;
...
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
synced = 0;
if(rxDone == 1)
{
rxDone = 0;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_SPI_TransmitReceive_DMA(&hspi4, testTxBuffer, &l, 1);
if(l == 85)
{
HAL_SPI_TransmitReceive_DMA(&hspi4, testTxBuffer, testRxBuffer, 4);
}
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET);
HAL_Delay(1);
}
Image from debugger:
Hi, I created the RPC library for the OpenMV Cam for this purpose. We get tons of help and support questions about comms communication. The library solves these.
rpc — rpc library — MicroPython 1.24 documentation
See the SPI Slave for the camera side, if you don’t want to use the RPC library it shows how to use SPI slave mode to receive data at minimum: openmv/scripts/libraries/rpc.py at master · openmv/openmv
Then, you can modify the Arduino library to work with the STM32: openmv/openmv-arduino-rpc: Remote Procedure/Python Call Library for Arduino
As for your particular issue note how the code works for the SPI slave. I deinit and reinit the SPI device each transaction after I see the CS line go low.
…
As for the issue of 95 versus 85. Not sure, it could be a bit phase mismatch. I’d check what data is on the wires using a logic analyzer.
Hello!
Regarding rpc library, I get this error:
Traceback (most recent call last):
File "<stdin>", line 12, in <module>
File "rpc.py", line 608, in put_bytes
AttributeError: 'rpc_spi_slave' object has no attribute '_put_short_timeout'
OpenMV v4.6.20; MicroPython v1.24.62; OPENMV4P with STM32H743
Type "help()" for more information.
My code looks something like:
import rpc
interface = rpc.rpc_spi_slave()
data = bytearray(3)
data[0] = 0x01
data[1] = 0x02
data[2] = 0x03
interface.put_bytes(data, 1000)
Do you know why I occur this error? Is this an error on library side?
Hi, the put_bytes can only be used after establishing a link sync. _put_short_timeout isn’t defined until that has occured.
You need to use the RPC calls to establish the link first, then you can use the lower level ones which don’t try to sync the link.
Please see the documentation: rpc — rpc library — MicroPython 1.24 documentation