Blocking UART Receiver Implementation Saving Only One Character, Overrun flag
STM32F746 Disco, UART1 connected to integrated ST-Link, Windows 10, STM32CubeIDE 1.7.0, Putty on PC
I'm writing my own implementation of UART on registers in C, have datasheet and reference manual right here. I have no problem sending one character or an array of characters, I have no problem receiving one character (which means I've set it up OK). But I can't receive an array of characters, and I don't see why, because algorithmically I think I'm doing it right (as it always seems until someone points out an error). Been reading the reference manual for hours.
It's a most basic driver, no interrupts, no noise flags, overrun flags used, just learning stuff. Basic send-receive. Baudrate 9600.
Now, the features of my receiver method are the following:
- The method receives an array pointer and array length as two parameters
- On call, it enables the receiver.
- It waits indefinitely for the start of transmission to be received
- It fills up (supposed to) the buffer array as new values come in.
- If transmission ends before the buffer array is full, detect it and not wait for more data, disable receiver and return.
- If buffer array is full, but the transmission keeps going, just wait until the transmission is over and only then disable receiver and return.
Code:
void uart1_receiveArray(uint8_t *arraypointer, uint32_t length) {
USART1->CR1 |= USART_CR1_RE; //USART Receiver enabled, line idle
uint32_t pointer = 0;
while ((((USART1->ISR) >> USART_ISR_RXNE_Pos) & 1U) == 0); //wait while first data comes from shift register
arraypointer[pointer] = USART1->RDR;
pointer++;
while ((((USART1->ISR >> USART_ISR_IDLE_Pos) & 1U) == 0) && (pointer < length)) { //if line not idle and buffer array not full
while ((((USART1->ISR) >> USART_ISR_RXNE_Pos) & 1U) == 0); //wait while data comes from shift register
arraypointer[pointer] = USART1->RDR;
pointer++;
}
while (((USART1->ISR >> USART_ISR_IDLE_Pos) & 1U) == 0); //if buffer is full, but transmission is still going, wait for it to end
USART1->CR1 &= ~USART_CR1_RE; //Receiver disabled
}I enter stuff to send in Putty. Array buffer is of length 8, I enter something shorter.
In debugging, I've set a breakpoint on Line 13 of the presented code and looked at UART1 ISR. The contents of it are:
10000000000000011111000So of all interesting bits related to reception. it signals Overrun Error, Idle Line (ok this makes sense) and Read Data Register (RDR) not empty. At the same time, my "pointer" variable has a value of 1. As if the transmission sent all 4 (2 3 5 6) bytes before the "While Line Not Idle" loop.
Can anyone suggest a solution? How can I receive UP TO buffer length?
