Skip to main content
Nickelgrass
Senior
June 8, 2020
Solved

A nother STM32G071 bare metal question on SPI

  • June 8, 2020
  • 5 replies
  • 1384 views

Hello,

here is another bare metal question on STM32G071. I am trying to get the SPI to work. But it is not generating any clock signal or MOSI signal.

Here is my init code trying to get it to work on GPIOB 6 to 8:

void init_spi(SPI_TypeDef* SPI)
{
	if(SPI == SPI2)
	{
		RCC->APBENR1 |= RCC_APBENR1_SPI2EN;													// enable SPI2
		RCC->IOPENR |= RCC_IOPENR_GPIOBEN;													// enable GPIOB
		GPIOB->MODER &= ~(GPIO_MODER_MODE6_Msk|GPIO_MODER_MODE7_Msk|GPIO_MODER_MODE8_Msk);	// clear alternate functions PB6, PB7, PB8
		GPIOB->MODER |= (GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1|GPIO_MODER_MODE8_1);			// alternate functions PB6, PB7, PB8
		GPIOB->OSPEEDR |= 0b111111<<14;														// PB6, PB7, PB8 very high speed
		GPIOB->AFRL |= (GPIO_AFRL_AFSEL6_2|GPIO_AFRL_AFSEL7_0);								// PB6, PB7 SPI2
		GPIOB->AFRH |= GPIO_AFRH_AFSEL8_0;													// PB8 SPI2
	}else{
		return;
	}
	SPI->CR1 = (SPI_CR1_MSTR|SPI_CR1_SSM);													// SPI master, enable, soft select
	SPI->CR1 |= 0b111<<3;																	// 1 MHz baudrate
	SPI->CR2 |= 0b111<<8;																	// SPI 8bit mode
	SPI->CR1 |= SPI_CR1_SPE;																// enable SPI
}

I can see in a logic analyzer that the pins shortly go low. So I guess my error is in the transmit code. I simply write to the SPI_DR to transmit.

void spi_wbyte(SPI_TypeDef* SPI, uint8_t val)
{
	SPI->DR = val;
	
}

Also, how do I read a byte? I could not find any examples. Is there anything wrong in my init?

Thanks

Kind regards.

This topic has been closed for replies.
Best answer by waclawek.jan

That's because you selected internal "soft" NSS, but you left its level as 0.

JW

5 replies

waclawek.jan
Super User
June 8, 2020

> GPIOB->OSPEEDR |= 0b111111<<14; // PB6, PB7, PB8 very high speed

PB7, PB8 and PB9

Not that it matters much.

Also, "very high speed" is often a bad idea with SPI SCK, although maybe in 'G0 it is not that prominent.

Read out the registers and check/compare. My guess is, that you find that SPI is switched to slave.

JW

TDK
June 8, 2020

> Also, "very high speed" is often a bad idea with SPI SCK, although maybe in 'G0 it is not that prominent.

@Community member​ Why do you say that? Just because it creates a sharper edge which makes more noise?

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
June 8, 2020

Yes.

Moore Noyce in SPI SCK may mean false clock edges to be seen by the slave.

JW

TDK
June 8, 2020

> Also, how do I read a byte?

To read a byte from MISO, you just read from SPIx->DR. Check the RXNE flag first.

To write a bit to MOSI, you write to SPIx->DR. Check the TXE flag first.

The register serves a double purpose. Not sure if it matters for the G0 (I don't think it does), but the HAL and LL libraries perform these as byte instructions, as opposed to word instructions.

> __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR);

> *spidr = TxData;

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
June 8, 2020

> The register serves a double purpose.

Aren't there separate TDR/RDR in G0? I don't have the RM at hand now (or is it only in the newer UARTs?)

> Not sure if it matters for the G0 (I don't think it does

It probably does, all newer STM32 SPIs have so called data packing (see RM, can be a nasty surprise to the unaware).

JW

Nickelgrass
Senior
June 9, 2020

Thanks for the replies.

So I changed the speed to only high and inserted the code from TDK. It turns out it switched back to slave mode.

waclawek.jan
waclawek.janBest answer
Super User
June 9, 2020

That's because you selected internal "soft" NSS, but you left its level as 0.

JW

Nickelgrass
Senior
June 9, 2020

Thanks, this was it.