SPI2.transfer(tx_buffer, rx_buffer, sizeof(rx_buffer), NULL); gives me hardware error

Hi. I am using electron as slave and P1 as master to receive data in electron from P1. Using the function SPI2.transfer(tx_buffer, rx_buffer, sizeof(rx_buffer), NULL); Electron’s LED starts flashing red. and my SPI doesnt receive anything. I am sending one byte at a time, so after reading on community forums, I am using :
SPI.transfer(result | 0x80);
result = SPI.transfer(0x00);
But I am always getting 255 in result even when P1 is not sending anything. Any suggestions on how can i make SPI starts working are appreciated. Thanks

Hello,

Let me ping someone that be able to help, @tylercpeacock are you able to assist?

Kyle

Thanks,
I also tried with electron as master, I checked with oscilloscope. It’s giving out proper data from mosi, sck and ss pins. but nothing is received on the P1 side. I can share the code if required.

I’ll be investigating this today. To make sure I’m testing the same thing, could you also list how you’ve wired it up? The code you’ve used might be helpful as well.

1 Like

I think you’re getting a hard fault on the SPI slave device because you have a Particle.publish in your onSelect handler. The onSelect is an interrupt handler and you can’t call Particle.publish in it. I wouldn’t even recommend calling Serial.print. You should only set the select_state flag.

As far as I can tell, you can’t use a single byte SPI transfer in SPI slave mode. I never get valid data doing that. You need to use the multi-byte DMA transfer mode.

I prefer to structure my code differently than the slave example in the docs. If you do the slave read from loop, it’s quite possible that you’ll miss the first few bytes of data, because the master device will start sending data very quickly after taking SS low. The caveat is that you have to be careful about reentrancy if you call SPI.transfer from an ISR. It does work if you use it carefully, however.

Here’s my master code:

#include "Particle.h"

SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler;

const unsigned long SEND_PERIOD_MS = 1000;
const int SS_PIN = A2;
const size_t NUM_VALUES = 2;

unsigned long lastSend = 0;
uint32_t rcvdValues[NUM_VALUES];
uint32_t sendValues[NUM_VALUES];


void setup() {
	Serial.begin(9600);

	SPI.begin(SPI_MODE_MASTER, SS_PIN);
}

void loop() {
	if (millis() - lastSend >= SEND_PERIOD_MS) {
		lastSend = millis();

		digitalWrite(SS_PIN, LOW);

		for(size_t ii = 0; ii < NUM_VALUES; ii++) {
			sendValues[ii] = rand() % 256;
		}
		Log.info("sendValues[0]=0x%lx sendValues[1]=0x%lx", sendValues[0], sendValues[1]);

		SPI.transfer(sendValues, rcvdValues, NUM_VALUES * sizeof(uint32_t), 0);

		Log.info("rcvdValues[0]=0x%lx rcvdValues[1]=0x%lx", rcvdValues[0], rcvdValues[1]);

		digitalWrite(SS_PIN, HIGH);
	}
}

And slave code:

#include "Particle.h"

SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler;

void slaveSelect(uint8_t state);
void slaveCallback();

const int SS_PIN = A2;
const size_t NUM_VALUES = 2;

bool gotValue = false;

uint32_t rcvdValues[NUM_VALUES];
uint32_t sendValues[NUM_VALUES];

void setup() {
	Serial.begin(9600);

	for(size_t ii = 0; ii < NUM_VALUES; ii++) {
		sendValues[ii] = 0;
	}

	SPI.onSelect(slaveSelect);
	SPI.begin(SPI_MODE_SLAVE, SS_PIN);
}

void loop() {
	if (gotValue) {
		gotValue = false;

		Log.info("rcvdValues[0]=0x%lx rcvdValues[1]=0x%lx", rcvdValues[0], rcvdValues[1]);

		for(size_t ii = 0; ii < NUM_VALUES; ii++) {
			sendValues[ii] = rcvdValues[ii];
		}

	}
}

void slaveSelect(uint8_t state) {
	if (state) {
		SPI.transfer(sendValues, rcvdValues, NUM_VALUES * sizeof(uint32_t), slaveCallback);
	}
}

void slaveCallback() {
	gotValue = true;
}

3 Likes

thank you so much @rickkas7. I understand what you meant. I would try your code and would let you know if it works for me.

1 Like

Hi @rickkas7,
I tired your code, with electron as slave and P1 as master. Electron’s SPI2 is connected to P1’s SPI. So electron gives me hard fault, it’s LED start blinking red when I flash this code in it. I know it doesnt make any sense, but just to check I changed SPI2 to SPI1 and SPI in electron’s code(hardware connection are still same) one at a time, it stopped giving me hard fault in case of SPI. So is there any problem with SPI2 and SPI1?