Page 1 of 2

SPI3 for thermocouple works ONE time on stm32f4 discovery!?!

Posted: Tue Mar 11, 2014 1:39 pm
by ljfischer
Using the stm32f4 discovery board, Im enabling all three SPI xfaces: SPI1=mems, SPI2&3 are connected to offboard max31855 thermocouple chips. I initially used SPI2 for one chip and got it working perfectly from sample code. Configure and start spi2 at init time. Never stop it. Just select and unselect it to read. I tried to do the same thing for SPI3, but found it only worked ONCE, and then would return 0s on the receive. I have found that it works consistently if I start/stop it every time I try to read it (I no longer start it at init time). The code to read both SPIs is the same. Obviously, the pins are different.

One clue(?): I found that I had to change the palmode for the SPI3 NSS pin - I had to remove the pushpull bit setting or I was getting bad data back.

Im trying to figure out how to debug this - stepping thru the spi_receive code didnt give me anything obvious. Any ideas? Init code is below.
Ugly debug oriented read code is below that (no flames about reading in single bytes - Im debugging :) )

static const SPIConfig spi2cfg = { NULL,
/* HW dependent part.*/
SPI_GPIO2, 12, 0 };

static const SPIConfig spi3cfg = { NULL,
/* HW dependent part.
* Slave select is on pin 15 of GPIOA
*/
SPI3_CS_GPIO, SPI3_CS_PIN, 0 };

spiStart(&SPID2, &spi2cfg);
palSetPad(SPI_GPIO2, SPI2_CS_PIN);
palSetPadMode(SPI_GPIO2, SPI2_CS_PIN, PAL_MODE_OUTPUT_PUSHPULL |
PAL_STM32_OSPEED_HIGHEST); /* NSS. */
palSetPadMode(SPI_GPIO2, SPI2_SCK_PIN, PAL_MODE_ALTERNATE(5) |
PAL_STM32_OSPEED_HIGHEST); /* SCK. */
palSetPadMode(SPI_GPIO2, SPI2_MISO_PIN, PAL_MODE_ALTERNATE(5)); /* MISO. */
palSetPadMode(SPI_GPIO2, SPI2_MOSI_PIN, PAL_MODE_ALTERNATE(5) |
PAL_STM32_OSPEED_HIGHEST); /* MOSI. */

// init the thermocouple SPI driver. this is a max31855 chip
/*
* Initializes the SPI driver 3. The SPI3 signals are routed as follow:
* P - NSS. to pin 6 of 31855
* P - SCK. to pin 5 of 31855
* P - MISO. Master In Slave Out to pin 7 of 31855
* P - MOSI. - not connected to 31855
* red lead of thermocouple to pin 3 of 31855
* blue lead of thermocouple to pin 2 of 31855
*
*/
palSetPadMode(SPI3_CS_GPIO, SPI3_CS_PIN,
PAL_STM32_OSPEED_HIGHEST | PAL_MODE_ALTERNATE(6) ); /* NSS. */
palSetPad(SPI3_CS_GPIO, SPI3_CS_PIN);
palSetPadMode(SPI_GPIO3, SPI3_SCK_PIN, PAL_MODE_ALTERNATE(6) |
PAL_STM32_OSPEED_HIGHEST); /* SCK. */
palSetPadMode(SPI_GPIO3, SPI3_MISO_PIN, PAL_MODE_ALTERNATE(6)); /* MISO. */
palSetPadMode(SPI_GPIO3, SPI3_MOSI_PIN, PAL_MODE_ALTERNATE(6) |
PAL_STM32_OSPEED_HIGHEST); /* MOSI. */

// spiStart(&SPID3, &spi3cfg);

void readThermoCouple3(void)
{
static int8_t buf[4];
char c;
/* Read thermocouple data over SPI3.*/
spiStart(&SPID3, &spi3cfg);

spiSelect(&SPID3);


spiReceive(&SPID3, 1, buf); // 4th byte
c=buf[0];
headTemp=c; // 3rd byte of temp
headTemp=headTemp<<4;
// chprintf(chp,"%02X ",buf[0]); //delay


spiReceive(&SPID3, 1, buf); // 3rd byte
c=buf[0];
// chprintf(chp,"%02X ",buf[0]); //delay
spiFault=c;
spiFault&=1; // only want the low bit;
c=c>>4;
headTemp+=c;

spiReceive(&SPID3, 1, buf); // 2nd byte
c=buf[0];
spiIntTemp=c;
// chprintf(chp,"%02X ",buf[0]); //delay

spiReceive(&SPID3, 1, buf); // low byte
c=buf[0];
spiData=c;
spiData&=7;
// chprintf(chp,"%02X\r\n",buf[0]); //delay

spiUnselect(&SPID3);
spiStop(&SPID3);

}

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Tue Mar 11, 2014 2:00 pm
by fred
Hi,

it would appear that you're running SPI3 at full clock (last value in spi3cfg is 0). Just glanced the MAX31855 datasheet and it seems to state max clock of 5MHz.

If I remember correctly, SPI3 runs on a half-clock compared to SPI1 & SPI2, so take that into account.

Edit:
check out viewtopic.php?f=2&t=933
You'd need
#define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018)

and add that as your spi3cfg value:

static const SPIConfig spi3cfg = { NULL,
/* HW dependent part.
* Slave select is on pin 15 of GPIOA
*/
SPI3_CS_GPIO, SPI3_CS_PIN, SPI_BaudRatePrescaler_16 };

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Tue Mar 11, 2014 2:45 pm
by Giovanni
Hi,

Note that the SPI driver uses the CS pin in GPIO mode so you have to program it as an output GPIO defaulted to state 1. It is possible this is related to your problem.

Giovanni

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Tue Mar 11, 2014 5:29 pm
by ljfischer
Thanks for the fast replies. I tried adjusting the speed:
SPI3_CS_GPIO, SPI3_CS_PIN, SPI_BaudRatePrescaler_16};

and tried both output types - No good.
Any recommendations on *how* to debug this?

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Tue Mar 11, 2014 8:51 pm
by Giovanni
Hi,

Usually a logic analyzer, even a cheap one, can help in those cases. The SPI driver itself has been used countless times, problems there are not very likely.

Giovanni

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Wed Mar 12, 2014 4:31 am
by ljfischer
Oh - I dont doubt the driver. Just trying to figure out how to attack this. I will single step with a scope - no LA...

Thanks

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Wed Mar 12, 2014 9:22 am
by Giovanni
The scope is not useful like a LA, consider getting a cheap one like the ZeroPlus I have at home.

Giovanni

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Thu Mar 13, 2014 2:11 am
by ljfischer
I dont *need* to solve this, as I have a workaround hack. But I dont like hacks, so Im thinking hard about the LA.

I want to make sure I didnt misinterpret your comment about programming the cs pin as GPIO. I tried programming the PALMODE for CS on SPI3 as both PAL_MODE_OUTPUT_PUSHPULL, and PAL_MODE_OUTPUT_OPENDRAIN. Is that what you meant?

Again - this works if I do an spistart/stop every time before/after I select/unselect (my hack). I also have the identical HW on SPI2, which works reliably. And I have swapped HW just to make sure. I also tried a few other, slower clk speeds for the SPI3. No Joy. So there is something silly Im missing.

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Thu Mar 13, 2014 8:56 am
by Giovanni
The appropriate mode is PAL_MODE_OUTPUT_PUSHPULL.

Your hack should not be necessary, you are probably just hiding the real problem there.

Giovanni

Re: SPI3 for thermocouple works ONE time on stm32f4 discover

Posted: Thu Mar 13, 2014 10:16 am
by fred
Did you remap the SCK pin for SPI3?

From the ref manual page 856:

Since some SPI1 and SPI3/I2S3 pins may be mapped onto some pins used by the JTAG interface (SPI1_NSS onto JTDI, SPI3_NSS/I2S3_WS onto JTDI and SPI3_SCK/I2S3_CK onto JTDO), you may either:
– map SPI/I2S onto other pins
– disable the JTAG and use the SWD interface prior to configuring the pins listed as SPI I/Os (when debugging the application) or
– disable both JTAG/SWD interfaces (for standalone applications).
For more information on the configuration of the JTAG/SWD interface pins, please refer to Section 8.3.2: I/O pin multiplexer and mapping .


My solution is posted here, it's an AFIO remap, but you need to check the STM32F4 Ref to verify whether it's the same.