STM32F103RET6 bare metal SPI3 pins not configuring and not functional
This is a follow up to my previous post at:
https://community.st.com/t5/stm32-mcus-products/stm32f103ret6-bare-metal-spi3/m-p/819878#M282227
I got the boards built, and I'm starting testing. SPI3 is not functional, so I started stepping through and checking SFRs. One problem I'm having is that PB3 (SCK) and PB5 (MOSI) refuse to configure as alternate function push pull.
In lines 26-33 below, PA15 goes to output, alternate function push pull just fine. But PB3 and PB5 will only go to output, and open drain. In line 35, I even tried to force the mode bits to "10" (alternate function push pull), and when I observe the mode bits for PA3 and PA5, they get set to "11" (alternate function output open drain). My current attempt at SPI3 initialization is:
void init_spi3(void)
{
// Note on ref manual page 699: need to disable JTAG because SPI3 conflicts with JTAG pins
// Enable AFIO clock
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //(VERIFIED set properly by stepping through)
// Page 177 of ref manual, free up PA15 by setting SWJ_CFG[2:0] to 100
// -> Page 184 of ref manual, SWJ_CFG[2:0] is bits 26..24 of AFIO_MAPR
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; //(VERIFIED set properly by stepping through)
//SPI3, want master transmit-only:
//PA15 NSS
//PB3 SCK
//PB5 MOSI
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // enable GPIOA clock (VERIFIED set properly by stepping through)
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // enable GPIOB clock (VERIFIED set properly by stepping through)
RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; // Page 116 of ref manual set RCC_APB1ENR_SPI3EN to enable SPI3 (VERIFIED set properly by stepping through)
//Table 25 on page 167 of reference manual, for SPIx:
//PA15 SPI3 NSS -> Want alternate function push-pull
//PB3 SPI3 SCK -> Want alternate function push-pull
//PB5 SPI3 MOSI -> Want alternate function push-pull
// init PA15 NSS - Mode = 01 (10Mhz output), CNF = 10 = alternate function push-pull...ref manual pg 171
GPIOA->CRH |= (GPIO_CRH_MODE15_0 | GPIO_CRH_CNF15_1); //***(VERIFIED, MODE goes to 01 (output 10MHz), and CNF goes to 10 (alternate function push pull)
// init PB3 SCK - Mode = 01 (10Mhz output), CNF = 10 = alternate function push-pull...ref manual pg 171
///GPIOB->CRL |= (GPIO_CRL_MODE3_0 | GPIO_CRL_CNF3_1); //***(MODE goes to 01, but CNF goes to 11, which is alternate function open drain)
// init PB5 MOSI - Mode = 01 (10Mhz output), CNF = 10 = alternate function push-pull...ref manual pg 171
///GPIOB->CRL |= (GPIO_CRL_MODE5_0 | GPIO_CRL_CNF5_1); //***(MODE goes to 01, but CNF goes to 11, which is alternate function open drain)
GPIOB->CRL |= 0x00909000; //***Try forcing the bits manually, MODE still goes to 01, and CNF still goes to 11
GPIOA->BSRR = GPIO_BSRR_BS15; // set the NSS pin high
// initialize the SPI configuration register (sequence page 707, SPI_CR1 register on page 742)
SPI3->CR1 = SPI_CR1_DFF // 16-bit data frame
| SPI_CR1_SSM // software slave management enabled
| SPI_CR1_SSI // internal slave select
| SPI_CR1_MSTR // SPI master mode
| SPI_CR1_BR_2; // bit rate prescale /32 (72MHz/32 = 2.25MHz)
SPI3->CR1 |= SPI_CR1_SPE; // enable SPI
}There is also some strange behavior with line 37. After I step through and execute:
GPIOA->BSRR = GPIO_BSRR_BS15; // set the NSS pin high
...PA15 does not set high. I have combed through the reference manual and I am positive I am missing something big. Hopefully someone can help me please.
For reference, I'm trying to execute an SPI transmit by calling:
spi3_transmit_reg_byte(0x09,0xFF);
It gets through the function call, but nothing is happening on any of the pins. The code for that is here:
void spi3_transmit_reg_byte(uint8_t reg, uint8_t reg_byte) //16 bit data frame, register followed by byte
{
uint16_t data = ( (reg << 8) | reg_byte );
GPIOA->BSRR = GPIO_BSRR_BR15; // reset NSS pin
SPI3->DR = data; // send data out SPI
while( !(SPI3->SR & SPI_SR_TXE) ); // wait until transmit buffer empty
while( SPI3->SR & SPI_SR_BSY ); // wait until SPI not busy
GPIOA->BSRR = GPIO_BSRR_BS15; // set NSS pin
}
