Reputation: 1
I'm using the stm32f767zi, and I'm trying to send test data over the USART peripheral. I've done the same configuration as I always do on any device, but this time it does not output anything... I cannot find the mistake, can someone help ?
The clock setup
// Enables TIM8 (Delay), USART1 (STDOUT)
RCC->APB2ENR |= (RCC_APB2ENR_TIM8EN
| RCC_APB2ENR_USART1EN);
// Enables GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, DMA1
RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN
| RCC_AHB1ENR_GPIOBEN
| RCC_AHB1ENR_GPIOCEN
| RCC_AHB1ENR_GPIODEN
| RCC_AHB1ENR_GPIOEEN
| RCC_AHB1ENR_GPIOFEN
| RCC_AHB1ENR_DMA1EN);
The initialization code
// Makes A8 (TX) and A9 (RX) Alternative Function
GPIOA->MODER &= ~(GPIO_MODER_MODER8_Msk
| GPIO_MODER_MODER9_Msk);
GPIOA->MODER |= ((0x2 << GPIO_MODER_MODER8_Pos)
| (0x2 << GPIO_MODER_MODER9_Pos));
// Selects AF7 for both A8 (TX) and A9 (RX).
GPIOA->AFR[1] &= ~(GPIO_AFRH_AFRH0_Msk
| GPIO_AFRH_AFRH1_Msk);
GPIOA->AFR[1] |= ((7 << GPIO_AFRH_AFRH0_Pos)
| (7 << GPIO_AFRH_AFRH1_Pos));
// Selects very high speed for A8 (TX) and A9 (RX)
GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDR8_Msk
| GPIO_OSPEEDR_OSPEEDR9_Msk);
GPIOA->OSPEEDR |= ((0x3 << GPIO_OSPEEDR_OSPEEDR8_Pos)
| (0x3 << GPIO_OSPEEDR_OSPEEDR9_Pos));
// Calculates and sets the baud rate.
m_USART->BRR = (((2 * clk) + baud) / (2 * baud));
// Configures the USART peripheral further.
m_USART->CR1 = USART_CR1_TE // Transmit Enable
| USART_CR1_RE // Receive Enable
| USART_CR1_UE; // USART Enable (EN)
and the write function:
*reinterpret_cast<uint8_t *>(m_USART->TDR) = c;
while (!(m_USART->ISR & USART_ISR_TC));
Upvotes: 0
Views: 614
Reputation: 67855
The problem you have is that you set the wrong pins. It should be PA9 & PA10
your write is also wrong
it should be :
*reinterpret_cast<volatile uint8_t *>(&m_USART->TDR) = c;
or C
style:
*(volatile uint8_t *)(&m_USART->TDR) = c;
you are also checking the wrong flag.
TC is important if you want to disable the peripheral after the transition. In normal conditions use TXE
flag instead.
while (!(m_USART->ISR & USART_ISR_TXE));
Upvotes: 2
Reputation: 5510
Your reinterpret_cast
is unnecessary and incorrect.
I assume you actually wrote *reinterpret_cast<uint8_t *>(&m_USART->TDR) = c;
but that is still wrong.
The person who wrote the standard device header has taken great care to make sure that USARTx->TDR already has the correct type, I strongly advise you to trust them and not cast it! In this particular case they will have made it volatile, and you have not, so it is possible that the compiler thinks it can make an optimization by not bothering to perform a write to something that you never read back.
The reason you probably got away with this on other STM32 parts is that their UARTs have just DR for both transmit and receive so reading DR for reception made the compiler think it couldn't eliminate the write.
Also, I don't know about this part, but many STM32 need an extra cycle between writing to RCC->xxxENR and using the respective peripheral, this is usually done with a read of the same register, eg:
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
(void)RCC->AHB1ENR;
// now safe to access GPIOA registers
Upvotes: -1