cancel
Showing results for 
Search instead for 
Did you mean: 

A nother STM32G071 bare metal question on SPI

Nickelgrass
Senior

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.

1 ACCEPTED SOLUTION

Accepted Solutions

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

JW

View solution in original post

9 REPLIES 9

> 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

> 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".
TDK
Guru

> 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".

Yes.

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

JW

> 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

@Community member​ true, it is switched to slave. But why?

Nickelgrass
Senior

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.

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

JW

Thanks, this was it.