cancel
Showing results for 
Search instead for 
Did you mean: 

USART2 SR register issue

AHass.1
Associate II

Dear community,

I plan to use the USART2 of my STM32F407VE board for an IrDA communication (8N1, 115200 Baud @ 8 MHz fPCLK). I started with initializing my USART2 periphery on the register level (I don't use STM32CubeIDE). This seems to work fine. However, I have several issues that I try to distinguish by the following numbers:

1.First issue is that when I try to write to the data register DR for transmission, my debugger tells me that no value is written to it:

if ((write_data_ptr != transmit_data_ptr) && ((USART2->SR & (1 << USART_SR_TXE_Pos)) == USART_SR_TXE))
  {
    USART2->CR1 |= (1 << USART_CR1_TE_Pos);        // send an idle frame
    USART2->DR = tx_buffer[transmit_data_ptr];
    transmit_data_ptr = (transmit_data_ptr + 1) & (BUFFER_SIZE - 1);
    while((USART2->SR & USART_SR_TC_Msk) == USART_SR_TC) {};    // wait for transmission to finish
    toggle_LED(LED_D3);
  }

First I thought it is due to the fact that the DR register actually consists of two registers on the hardware - one for transmission and one for receiving. I thought that my debugging software/my debugger can't distinguish between those two because it shows only one register anyway. But I would expect at least that the TXE flag (transmit data register empty) in the status register SR is reset, because I just wrote something to the register. However this doesn't happen. But why?

2.When I debug the above code, row number 67 is executed and does what I expect (incrementing the pointer that indicates which data is already transmitted). After that, I planned to wait for the transmission to be complete. If I resume the program after row 67, the code waits but immediately jumps back to row 67, instead of holding at line 69 (which I purposelly inserted for this problem). After this happened, the code gets completely stuck at line 68 and waiting forever, despite that the status register of USART2 did not change.0693W000003Rq70QAC.png

3.My interrupt for the USART2 never gets called. I am not sure if that is the case because I used the wrong name (because I did something similar for a timer interrupt in another question I asked recently in this forum). I use the interrupt

void USART2_IRQHandler(void) {
    // do something
}

And just as in my previously asked question, it doesn't get called even though the compiler does not return an error or warning. Where can I generally look up what those interrupt vectors are called? Just for completion, here is my init code for the USART2:

void initIrda(void)
{
  if (!isIrdaInitialized())
  {
    write_data_ptr = 0;
    transmit_data_ptr = 0;
    received_data_ptr = 0;
    read_data_ptr = 0;
 
    GPIOA->AFR[0] |= (0b0111 << GPIO_AFRL_AFSEL2_Pos);  // Alternate function AF7 for PA2 and PA3
    GPIOA->AFR[0] |= (0b0111 << GPIO_AFRL_AFSEL3_Pos);
    startIrda();
    USART2->CR1  |= (1 << USART_CR1_TXEIE_Pos)      // Enable TX-Interrupts
           |  (1 << USART_CR1_TCIE_Pos)      // Enable Transmission Complete Interrupts
           |  (1 << USART_CR1_PEIE_Pos)       // Enable Interrupts for parity errors
           |  (1 << USART_CR1_IDLEIE_Pos)      // Enable Interrupt when idle line is detected
           |  (1 << USART_CR1_RXNEIE_Pos)      // Enable RX-Interrupts
           |  (1 << USART_CR1_TE_Pos)        // Enable Transmitter
           |  (1 << USART_CR1_RE_Pos);      // Enable Receiver
    USART2->CR1 |= (1 << USART_CR1_UE_Pos);        // enable UART
    USART2->CR1 &= ~(1 << USART_CR1_M_Pos);        // 1 Start bit, 8 Data bits, n Stop bit
    USART2->CR2 &= ~(0b11 << USART_CR2_STOP_Pos);    // 1 Stop bit
    USART2->BRR = 0x045;                // Baudrate 115200 (see documentation how this value was calculated)
    irda_status.initialized = 1;
  }
}
 
void startIrda(void)
{
  RCC->APB1ENR |= (1 << RCC_APB1ENR_USART2EN_Pos);  // turn clock on for usart2 periphery
  irda_status.running = 1;
}

Thank you in advance!

5 REPLIES 5

>>First issue is that when I try to write to the data register DR for transmission, my debugger tells me that no value is written to it:

You can't inspect it in the debugger, the DR read looks into a different register than the DR write went too.

Viewing the USART registers in the debugger is invasive. Reading DR changes what's in SR, for example.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

You have to enable the interrupt in NVIC.

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru

Also your loop waits until the transmission is not complete. You want the opposite.

If you feel a post has answered your question, please click "Accept as Solution".

Yeah, that makes sense. The controller can't distinguish between a read from the debugger and a read from the software. Is there any way I can test my code, like a simulator tool for the STM32 series? I know that Atmel integrates simulators in their IDE.

But: I still would expect that after my code writes something to the data register, that the TXE (transmit register empty) flag in the status register should be reset. Instead, it stays at 1.