diff --git a/0x0001_hello-world/include/usart.h b/0x0001_hello-world/include/usart.h index 83b44cd..f9a26a7 100644 --- a/0x0001_hello-world/include/usart.h +++ b/0x0001_hello-world/include/usart.h @@ -33,28 +33,55 @@ extern int __io_putchar(int ch) __attribute__((weak)); static void set_baud_rate(USART_TypeDef *USARTx, uint32_t periph_clk, uint32_t baud_rate); /** - * @brief Initializes USART2 for transmission on PA2 pin. + * @brief Initializes USART2 for transmission on PA2 pin and receive on PA3 pin. * * This function configures the necessary settings for USART2 to enable - * transmission on pin PA2. It includes configuring GPIO, setting - * alternate function mode, configuring the USART clock, setting the + * transmission on pin PA2 and receive on PA3 pin. It includes configuring + * GPIO, setting alternate function mode, configuring the USART clock, setting the * baud rate, and enabling the transmitter. * * @param None * @retval None */ -void usart2_tx_init(void); +void usart2_init(void); /** * @brief Writes a single byte to USART2 for transmission. * - * This function writes a single byte to the USART2 transmit data - * register for transmission. It ensures that the transmit data register + * This function writes a single byte to the USART2 data + * register for transmission. It ensures that the data register * is empty before writing the byte. * - * @param ch: The byte to be transmitted. + * @param char_: The byte to be transmitted. * @retval None */ -void usart2_write(uint8_t ch); +void usart2_write_char(uint8_t char_); + +/** + * @brief Reads a single byte from USART2. + * + * This function reads a single byte from the USART2 data + * register. It ensures that the data register is not empty + * before reading the byte. + * + * @param None + * @retval The byte read from the data register. + */ +char usart2_read_char(void); + +/** + * @brief Reads a string of characters from input and stores it in the buffer. + * + * This function reads characters from input and stores them in the + * provided buffer until either the buffer is full (reaching + * buffer_size - 1 characters) or a newline character is encountered. + * The input is null-terminated, ensuring proper string termination in + * the buffer. + * + * @param buffer: Pointer to the buffer where the input characters are stored. + * @param buffer_size: The size of the buffer, including space for the null-terminator. + * @retval None + */ +void input(char *buffer, size_t buffer_size); #endif // USART_H diff --git a/0x0001_hello-world/src/main.c b/0x0001_hello-world/src/main.c index 331797b..123bfb3 100644 --- a/0x0001_hello-world/src/main.c +++ b/0x0001_hello-world/src/main.c @@ -13,7 +13,7 @@ int main(void) { - usart2_tx_init(); + usart2_init(); while (1) { diff --git a/0x0001_hello-world/src/usart.c b/0x0001_hello-world/src/usart.c index 5a08ac7..6ae0062 100644 --- a/0x0001_hello-world/src/usart.c +++ b/0x0001_hello-world/src/usart.c @@ -22,12 +22,12 @@ __attribute__((weak)) int _write(int file, char *ptr, int len) return len; } -int __io_putchar(int ch) +int __io_putchar(int char_) { // write a single char - usart2_write(ch); + usart2_write_char(char_); - return ch; + return char_; } static void set_baud_rate(USART_TypeDef *USARTx, uint32_t periph_clk, uint32_t baud_rate) @@ -36,7 +36,7 @@ static void set_baud_rate(USART_TypeDef *USARTx, uint32_t periph_clk, uint32_t USARTx->BRR = ((periph_clk + (baud_rate / 2)) / baud_rate); } -void usart2_tx_init(void) +void usart2_init(void) { // enable GPIOA clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; @@ -51,6 +51,16 @@ void usart2_tx_init(void) GPIOA->AFR[0] |= GPIO_AFRL_AFRL2_1; GPIOA->AFR[0] |= GPIO_AFRL_AFRL2_0; + // set PA3 to output alternate function mode + GPIOA->MODER |= GPIO_MODER_MODE3_1; + GPIOA->MODER &= ~GPIO_MODER_MODE3_0; + + // set PA3 alternate function type to UART_RX (AF07) + GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL3_3; + GPIOA->AFR[0] |= GPIO_AFRL_AFRL3_2; + GPIOA->AFR[0] |= GPIO_AFRL_AFRL3_1; + GPIOA->AFR[0] |= GPIO_AFRL_AFRL3_0; + // enable USART2 clock RCC->APB1ENR |= RCC_APB1ENR_USART2EN; @@ -60,15 +70,57 @@ void usart2_tx_init(void) // configure TX transmitter enable USART2->CR1 |= USART_CR1_TE; + // configure RX receiver enable + USART2->CR1 |= USART_CR1_RE; + // enable UART2 USART2->CR1 |= USART_CR1_UE; } -void usart2_write(uint8_t ch) +void usart2_write_char(uint8_t char_) { // verify transmit data register is empty, will return true if the bit is set while(!(USART2->SR & USART_SR_TXE)) {}; - // write a single char to the transmit data register - USART2->DR = (ch & 0xFF); + // write a single char to the data register + USART2->DR = (char_ & 0xFF); +} + +char usart2_read_char(void) +{ + // verify receive data register is empty, will return true if the bit is set + while(!(USART2->SR & USART_SR_RXNE)) {}; + + // return a single char from the data register + return USART2->DR; +} + +void input(char *buffer, size_t buffer_size) +{ + char input; + size_t i = 0; + + while (1) + { + input = usart2_read_char(); + + // check for newline or carriage return + if (input == '\n' || input == '\r') + { + // null-terminate the string + buffer[i] = '\0'; + break; + } + + // append new char from usart into buffer + buffer[i++] = input; + + // ensure we don't overflow the buffer + if (i >= buffer_size - 1) + { + // null-terminate the string + buffer[i] = '\0'; + break; + } + } }