Loading...
Searching...
No Matches
uart.c
1/***********************************************************************************
2 * @file uart.c *
3 * @author Matt Ricci *
4 * @addtogroup UART *
5 * @brief Brief description of the file's purpose. *
6 * *
7 * @todo Implement printf *
8 ***********************************************************************************/
9
10#include "uart.h"
11#include "stddef.h"
12#include "config.h"
13
14static void _UART_init(UART_t *uart, uint32_t baud, UART_Config *config);
15
16/* =============================================================================== */
27UART_t UART_init(USART_TypeDef *interface, uint32_t baud, UART_Config *config) {
28 // Early return error struct if peripheral is NULL
29 if (interface == NULL)
30 return (UART_t){.interface = NULL};
31
32 // Initialise uart struct with interface
33 UART_t uart = {.interface = interface};
34
35 uart.setBaud = UART_setBaud;
36 uart.send = UART_send;
37 uart.sendBytes = UART_sendBytes;
38 uart.print = UART_print;
39 uart.println = UART_println;
40 uart.receive = UART_receive;
41 uart.interface = interface;
42 uart.baud = baud;
43
44 // Update config and enable peripheral
45 UART_updateConfig(&uart, config);
46
47 return uart;
48}
49
50// ALLOW FORMATTING
51#ifndef __DOXYGEN__
52
53/* =============================================================================== */
66static void _UART_init(UART_t *uart, uint32_t baud, UART_Config *config) {
67 USART_TypeDef *interface = uart->interface;
68
69 // Disable peripheral and update config
70 config->UE = false; // Make sure UE is disabled in config
71 interface->CR1 &= *(uint16_t *)config & ~UART_CR1_RESERVED; // Update CR1 with configured values
72 interface->CR1 |= *(uint16_t *)config & ~UART_CR1_RESERVED; // Update CR1 with configured values
73
74 // Update baud rate
75 UART_setBaud(uart, baud);
76}
77
78#endif
79
80/********************************** INTERFACE METHODS ********************************/
81
82void UART_setBaud(UART_t *uart, uint32_t baud) {
83 USART_TypeDef *interface = uart->interface;
84
85 // Wait for interface to be freed
86 while ((interface->SR & USART_SR_TXE) == 0 && !(interface->SR & USART_SR_TC));
87 interface->CR1 &= ~USART_CR1_UE;
88 while ((interface->SR & USART_SR_RXNE) == 1) {
89 (void)(interface->DR & 0xFF);
90 }
91
92 // Calculate relevant APBx clock for peripheral
93 uint32_t sysclk = HSE_USED ? SYSCLK_HSE : SYSCLK_HSI;
94 uint8_t hpre = AHBPresc[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
95
96 uint8_t ppre;
97 // Set prescale value according to peripheral bus
98 if (interface == USART1 || interface == USART6) {
99 ppre = APBPresc[((RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos)];
100 } else {
101 ppre = APBPresc[((RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos)];
102 }
103
104 // Calculate peripheral bus clock from prescalers
105 uint32_t pclk = sysclk / hpre / ppre;
106
107 uint16_t usartDiv = ((pclk / baud) * (1 + uart->config.OVER8));
108 if (uart->config.OVER8 && (usartDiv & 0x08)) {
109 usartDiv &= ~0x0F;
110 usartDiv |= 0x07;
111 }
112 interface->BRR &= 0xFFFF0000; // Clear mantissa and div in baud rate reg
113 interface->BRR |= usartDiv; // Set baud rate
114
115 interface->CR1 |= USART_CR1_UE;
116}
117
118/* =============================================================================== */
127void UART_send(UART_t *uart, uint8_t data) {
128 USART_TypeDef *interface = uart->interface;
129 while ((interface->SR & USART_SR_TXE) == 0);
130 interface->DR = data;
131 while ((interface->SR & USART_SR_TC) == 0);
132}
133
134/* =============================================================================== */
144void UART_sendBytes(UART_t *uart, uint8_t *data, int length) {
145 for (int i = 0; i < length; i++)
146 UART_send(uart, data[i]);
147}
148
149/* =============================================================================== */
158
159void UART_print(UART_t *uart, char *data) {
160 int i = 0;
161 while (data[i] != '\0')
162 UART_send(uart, data[i++]);
163}
164
165/* =============================================================================== */
175
176void UART_println(UART_t *uart, char *data) {
177 UART_print(uart, data);
178 UART_print(uart, "\r\n");
179}
180
181/* =============================================================================== */
189uint8_t UART_receive(UART_t *uart) {
190 USART_TypeDef *interface = uart->interface;
191 while ((interface->SR & USART_SR_RXNE) == 0);
192 return (uint8_t)(interface->DR & 0xFF);
193}
194
195/* =============================================================================== */
208 // Initialise config with default values if passed NULL.
209 if (config == NULL) {
210 config = &UART_CONFIG_DEFAULT;
211 }
212
213 // Update peripheral with new config
214 uart->config = *config;
215
216 // Initialise SPI registers and enable peripheral
217 _UART_init(uart, uart->baud, config);
218}
bool UE
| (default )
Definition uart.h:124
void UART_send(UART_t *, uint8_t data)
Sends a single byte of data over the UART interface.
Definition uart.c:127
void UART_updateConfig(UART_t *uart, UART_Config *config)
Update UART peripheral configuration.
Definition uart.c:207
void UART_sendBytes(UART_t *, uint8_t *data, int length)
Sends an array of bytes over the UART interface.
Definition uart.c:144
uint8_t UART_receive(UART_t *)
Receives a single byte of data from the UART interface.
Definition uart.c:189
UART_t UART_init(USART_TypeDef *interface, uint32_t baud, UART_Config *config)
Initialiser for a UART device interface.
Definition uart.c:27
void UART_print(UART_t *, char *data)
Sends a null terminated string over the UART interface.
Definition uart.c:159
void UART_println(UART_t *, char *data)
Sends a null terminated string over the UART interface. Terminates with a line feed control character...
Definition uart.c:176
Struct definition for UART interface.
Definition uart.h:132