I’m trying to communicate via SPI between KRIA KV260 (master) and an ESP8266 (slave), through the PMOD port of the FPGA. I used PYNQ library provided by Xillinx, so that I can work in Jupyter Notebook and make C functions for communications and have them to be executed like a pith function (workflow recommended by their documentation). So I loaded the default Overlay (base.bit) to have access to the PMOD port and wrote the following functions in Jupyter Notebook (based on their wiki doc.: https://pynq.readthedocs.io/en/v3.0.0/pynq_libraries/pynqmb_reference.html#spi-devices):
%%microblaze base.PMODA
#include <spi.h>
#include <pmod_grove.h>
spi dev;
void init() {
// SCLK, MISO, MOSI, CS
dev = spi_open(PMOD_G3_B, PMOD_G4_B, PMOD_G2_A, PMOD_G1_A);
spi_configure(dev, 0, 0); // clock phase 0 and polarity 0
}
void send(int number) {
char read_data[2] = {0};
char write_data[2] = {0};
// convert the number to 2 bytes and place them in the write_data buffer
write_data[0] = number & 0xFF;
write_data[1] = (number >> 8) & 0xFF;
// spi_transfer(spi dev_id, const char* write_data, char* read_data, unsigned int length)
spi_transfer(dev, write_data, read_data, 2);
}
int read() {
char read_data[2] = {0};
char write_data[2] = {0}; // sending dummy bytes to receive data ...
// spi_transfer(spi dev_id, const char* write_data, char* read_data, unsigned int length)
spi_transfer(dev, write_data, read_data, 2);
int received_number = (read_data[1] << 8) | read_data[0];
return received_number;
}
void close() {
spi_close(dev);
}
Then executed them like this:
init()
send(1234)
received_number = read()
print("Received number:", received_number)
close()
This is the ESP8266 NodeMCU, which receives the number, increments by 1 and tries to send it back (wiring done right, including common ground):
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
SPISlave.onData([](uint8_t *data, size_t len) {
Serial.print("Received data: ");
for (size_t i = 0; i < len; i++) {
Serial.printf("%02X ", data[i]);
}
Serial.println();
int received_number = (data[1] << 8) | data[0];
Serial.printf("Received number: %dn", received_number);
int response_number = received_number + 1;
uint8_t response_data[2];
response_data[0] = response_number & 0xFF;
response_data[1] = (response_number >> 8) & 0xFF;
Serial.printf("Response bytes: %02X %02Xn", response_data[0], response_data[1]);
// send the response back to the master
SPISlave.setData(response_data, 2);
});
// setup SPI Slave registers and pins
SPISlave.begin();
// saw on a forum that this command sets reading on the Falling edge
//SPI1C2 |= 1 << SPIC2MISODM_S;
}
void loop() {}
The problem is that I get constant and wrong values on the ESP. Constant because only if I reset the Jupyter Notebook and unload the resources, including the Overlay and then loading them again, I get a different number, but still wrong. I always try sending 1234. I tested the SPI communication using Scopy and a M2K (Sampling rate 100 Msps, word size 8, DIO 4-7: SCLK, MISO, MOSI, CS, all set to trigger to ANY-EDGE). The readings are okay, for example when executing send(1234), even though the bytes are reversed, but you can see them unchanged (1234 is 4D2, in Scopy appears as D2 04):
As for an output from the ESP8266:
Received data: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 98 05 0E CF 46 78 8C DD ED
Received number: 0
Response bytes: 01 00
Not sure why I can’t properly communicate between the FPGA and the ESP.