STM32: SPI master data register reads zero - Page 1
Forum section: electronics / general

author: Siwastaja
author_rank: Super Contributor
timestamp: March 24, 2017, 09:36:06 am
content: Hi, I'm semi experienced with STM32, have been doing a lot of things, hate the broken documentation, but have been living with that.This is totally new to me:I'm trying the simplest thing ever, basic SPI, set as master, chip select managed by myself. Transmit works, clocking works, RXNE interrupt comes as supposed, but data register always reads as zero!Done a lot of debugging, and reduced the issue to the minimal, super simple code:CPU: STM32F205VFT6Clock config: SYSCLK at 120MHz, SPIs running at 30 MHz, but potential issues related to clock ruled out by running from 8MHz HSI divided down to 4MHz for SPI.GPIO, clock enable init:Code:RCC->AHB1ENR |= 0b111111111 /* PORTA to PORTI */;RCC->APB1ENR |= 1UL<<18 /*USART3*/ | 1UL<<14 /*SPI2*/;RCC->APB2ENR |= 1UL<<12 /*SPI1*/;GPIOA->AFR |= 5UL<<20 | 5UL<<24 | 5UL<<28; // SPI1 alternate functions.GPIOB->AFR |= 5UL<<20 | 5UL<<24 | 5UL<<28; // SPI2 alternate functions.// SPI1 and SPI2 MOSI, MISO, SCK as Alternate Functions:// 15141312111009080706050403020100// | | | | | | | | | | | | | | | |GPIOA->MODER = 0b01000000000000001010100100000000;GPIOB->MODER = 0b10101000000000000000000000000000;SPI2 (works PERFECTLY):Code:SPI2->CR1 = 1UL<<9 /*Software slave management*/ | 1UL<<8 /*SSI must be high*/ | 0b010UL<<3 /*div 8*/ | 1UL<<2 /*master*/;SPI2->CR1 |= 1UL<<6; // Enable SPIwhile(1){SPI2->DR = 123; // Send 123while(!(SPI2->SR & 1)) ; // Wait for RXNEbuf = o_str_append(buf, " data read=");buf = o_utoa32(SPI2->DR, buf);buf = o_str_append(buf, "\r\n");usart_print(buffer);}Short MISO&MOSI: prints "123". Short MISO to Vcc: prints 255. Short MISO to GND: prints 0. As expected!Then, SPI1, which should be identical. Replace SPI2 registers with SPI1, exact same code. Always prints 0, regardless of the actual input pin state!I have debugged the IO pin structure by configuring the MISO pin as general purpose input instead of alternate function, and copy its value (in a while(1) loop) to a random output pin, which I scope. The input pin works just fine, the output pin follows the input pin logic level.There is not much left I can do, so I'm at loss here. Next I'm going to assume that the chip is broken in a very interesting way, and going to desolder it for replacement. But I'm experienced enough to know that sometimes it just happens that a clear "hardware issue" is, after all, some random configuration bit in a wrong way, something that some other experienced person can catch in a few seconds.

author: Jeroen3
author_rank: Super Contributor
timestamp: March 24, 2017, 01:09:02 pm
content: Code:GPIOA->AFR |= 5UL<<20 | 5UL<<24 | 5UL<<28; // SPI1 alternate functions.GPIOB->AFR |= 5UL<<20 | 5UL<<24 | 5UL<<28; // SPI2 alternate functions.These lines are identical.Yet, SPI1 on PA is on 5/6/7 and PB they are at 3/4/5. (clk/in/out)The alternative on PB is shared with SWD.

author: Siwastaja
author_rank: Super Contributor
timestamp: March 24, 2017, 01:44:45 pm
content: Quote from: Jeroen3 on March 24, 2017, 01:09:02 pmNope!QuoteI fail to see any issue here. SPI1 is on PA5,6,7, exactly like configured (GPIOA -> AFRL bits 31 downto 20).Alternative for SPI1 in PB indeed is shared with SWD, but since I don't use the PB alternative for SPI1, it shouldn't matter. Or maybe it does, even when not connected!? This is one thing more to consider.

author: Jeroen3
author_rank: Super Contributor
timestamp: March 24, 2017, 02:55:39 pm
content: Oeps, I missed that. So you're setting SPI2 for PB13/14/15 then and SPI1 for PA5/6/7, ok.Looks like your code matches the readable spi basic version I posted on this forum earlier.Code:SPI2->CR1 |= (4<<SPI_CR1_BR_Pos); // Prescaler APB1 (36 Mhz) / 32SPI2->CR1 |= SPI_CR1_SSM; // Software chip selectSPI2->CR1 |= SPI_CR1_SSI;SPI2->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE;However, I do not set MISO to AF. But a 103 has a slightly different gpio system than a 205.Did you try to force reset before inializing?Code:__HAL_RCC_SPI2_FORCE_RESET();__NOP();__HAL_RCC_SPI2_RELEASE_RESET();__NOP();Otherwise I can only suggest you try to replace the chip.

author: Siwastaja
author_rank: Super Contributor
timestamp: March 24, 2017, 04:38:52 pm
content: Thanks for ideas,Quote from: Jeroen3 on March 24, 2017, 02:55:39 pmThis is really weird. On all STM32's I've used, IO pin is set to AF mode all digital peripherals, also for inputs. I verified this from the F205 reference manual, but I tested this just in case, but nope.QuoteJust tried. Not helping.As a third thing, I tested moving the configuration of MSTR and SPE bits in the same read-modify-write, as you have in your code. No effect.Either the chip is toasted in a very interesting way (not affecting the first IO structure, but inner logic), or there is some subtle difference between SPI1 and SPI2, or their routing to the IO using the AF mux. I don't suspect a clocking issue, because SPI1 emits the SCLK just right, and the slaves connected work just as expected - also, the RX complete interrupt comes as expected, only the data is null, so I am suspecting:A) data signal somewhere between the IO cell, the AF mux, and then the SPI shift register, is broken.B) Transfer operation from the shift register to the DR is brokenC) DR read operation to the CPU bus is brokenD) There is some very interesting issue that goes and resets the DR just before I read it. I even tested this out by running a while(1) loop quickly comparing DR if it is nonzero and setting a LED - the LED never came up, so this explanation is unlikely.Thanks anyways, those were genuinely good ideas to try out. I have been trying random things for more than 10 hours of work time now. This is not the first time some trivial thing in STM32 is costing a huge amount of development time. Even in cases where it has been due to a bug caused by myself, the time spent has escalated due to broken documentation (too much trial and error everywhere). And, too many of the issues have been, after all, clear errors either on silicon or in documentation - not even covered in errata. I don't like that - I can accept myself making mistakes and banging my head on the wall, but repeated chip documentation / silicon mistakes are not ok.

author: Jeroen3
author_rank: Super Contributor
timestamp: March 24, 2017, 07:30:35 pm
content: Spi1 has i2s capability. Does this work?

author: Siwastaja
author_rank: Super Contributor
timestamp: March 26, 2017, 06:10:15 pm
content: I had missed an obvious thing to try out:So I changed SPI1 mapping to PB3,4,5, and yes, it does work there!So this test verified that the issue is not within the SPI1 peripheral, but near the PA6 AF mux, since the PB4 -> AFmux -> SPI1 chain works, and since PA6 works as standard input, but PA6 -> AFmux -> SPI1 only gives zero.So, I changed the chip. Problem solved. So it was broken, after all... Should have done it in the first place! OTOH, often when I think I have a case of internally broken chip, it is due to some code bug from myself, that's why I'm not eager to spend my time in changing the chip since it seldom helps. But this case was different!I have seen broken IO cell structures, but haven't seen a broken internal signal just like this before! This is slightly disturbing, because I took at least basic ESD precautions, etc, soldering profile was OK, there hasn't been overvoltage kind of incidents during the development. So I really hope it's something I did, instead of a quality problem at ST...

author: Jeroen3
author_rank: Super Contributor
timestamp: March 26, 2017, 07:54:58 pm
content: Well, electronics can break. It's a just bad timing it breaks on your development platform. Which causes you to question yourself even more.Quote from: Siwastaja on March 26, 2017, 06:10:15 pmOne broken chipon a dev boardis not a quality problem.Ten broken chips in production batch is a quality problem.