GPS Device
Loading...
Searching...
No Matches
stm32f401re_usart.c
Go to the documentation of this file.
1
11
12#include "stm32f401re_usart.h"
13#include "common.h"
14#include "arm_cortex_m4_nvic.h"
15#include "stm32f401re.h"
16#include "stm32f401re_rcc.h"
17
18/* ---- Forward declarations for internal helpers ---- */
19static void usart_set_pclk(USART_REGDEF_ts const *instance, EN_STATUS_te en_status);
20static void usart_set_baud_rate(USART_CFG_ts *usart_cfg);
21
26
28void usart_init(USART_CFG_ts *usart_cfg) {
29 // Enable peripheral clock
30 usart_set_pclk(usart_cfg->instance, ENABLE);
31
32 // Configure data word length (8 or 9 bit)
33 usart_cfg->instance->USART_CR1 &= ~(0x1 << USART_CR1_M);
34 usart_cfg->instance->USART_CR1 |= (usart_cfg->frame_data_bits << USART_CR1_M);
35
36 // Configure stop bit count
37 usart_cfg->instance->USART_CR2 &= ~(0x3 << USART_CR2_STOP);
38 usart_cfg->instance->USART_CR2 |= (usart_cfg->frame_stop_bits << USART_CR2_STOP);
39
40 // Compute and write BRR from peripheral clock and baud rate
41 usart_set_baud_rate(usart_cfg);
42
43 // Configure oversampling ratio
44 usart_cfg->instance->USART_CR1 &= ~(0x1 << USART_CR1_OVER8);
45 usart_cfg->instance->USART_CR1 |= (usart_cfg->oversampling << USART_CR1_OVER8);
46
47 // Configure parity
48 if(usart_cfg->parity != USART_PARITY_DISABLED) {
49 usart_cfg->instance->USART_CR1 |= (0x1 << USART_CR1_PCE);
50
51 if(usart_cfg->parity == USART_PARITY_EVEN) {
52 usart_cfg->instance->USART_CR1 &= ~(0x1 << USART_CR1_PS);
53 }
54 else if(usart_cfg->parity == USART_PARITY_ODD) {
55 usart_cfg->instance->USART_CR1 |= (0x1 << USART_CR1_PS);
56 }
57 }
58
59 // Configure hardware flow control (RTS + CTS)
61 usart_cfg->instance->USART_CR3 |= (0x1 << USART_CR3_CTSE);
62 usart_cfg->instance->USART_CR3 |= (0x1 << USART_CR3_RTSE);
63 }
64
65 // Configure sample bit method
66 usart_cfg->instance->USART_CR3 &= ~(0x1 << USART_CR3_ONEBIT);
67 usart_cfg->instance->USART_CR3 |= (usart_cfg->sample_bit << USART_CR3_ONEBIT);
68
69 if(usart_cfg->mode == USART_MODE_SYNC) {
70 // LBCL, CPHA, CPOL, CLKEN — not yet implemented
71 }
72
73 // Enable RXNE interrupt and NVIC line if requested
74 if(usart_cfg->interrupt_en == USART_INTERRUPT_EN_TRUE) {
75 usart_cfg->instance->USART_CR1 |= (0x1 << USART_CR1_RXNEIE);
76
77 if(usart_cfg->instance == USART1) {
79 }
80 else if(usart_cfg->instance == USART2) {
82 }
83 else if(usart_cfg->instance == USART6) {
85 }
86 }
87
88 // Enable the USART peripheral
89 usart_cfg->instance->USART_CR1 |= (0x1 << USART_CR1_UE);
90}
91
109
111void usart_send(USART_REGDEF_ts *instance, uint8_t *tx_buffer, uint32_t len) {
112 while(len != 0) {
113 while(!((instance->USART_SR >> USART_SR_TXE) & 0x1));
114 instance->USART_DR = *tx_buffer;
115 tx_buffer++;
116 len--;
117 }
118 // Wait for TC to confirm the last byte has fully shifted out
119 while(!((instance->USART_SR >> USART_SR_TC) & 0x1));
120}
121
123void usart_receive(USART_REGDEF_ts const *instance, uint8_t *rx_buffer, uint32_t len) {
124 while(len != 0) {
125 while(!((instance->USART_SR >> USART_SR_RXNE) & 0x1));
126 *rx_buffer = instance->USART_DR;
127 rx_buffer++;
128 len--;
129 }
130}
131
134 instance->USART_CR1 &= ~(0x1 << USART_CR1_TE);
135 instance->USART_CR1 |= (en_status << USART_CR1_TE);
136}
137
140 instance->USART_CR1 &= ~(0x1 << USART_CR1_RE);
141 instance->USART_CR1 |= (en_status << USART_CR1_RE);
142}
143
145void usart_get_name(USART_REGDEF_ts const *instance, char *name) {
146 const char usart[] = "USART";
147 uint8_t usart_len = get_str_len(usart);
148 uint8_t pos_counter = 0;
149
150 while(pos_counter != usart_len) {
151 name[pos_counter] = usart[pos_counter];
152 pos_counter++;
153 }
154
155 if(instance == USART1) name[pos_counter] = '1';
156 else if(instance == USART2) name[pos_counter] = '2';
157 else if(instance == USART6) name[pos_counter] = '6';
158 pos_counter++;
159
160 name[pos_counter] = '\0';
161}
162
164
169
183static void usart_set_pclk(USART_REGDEF_ts const *instance, EN_STATUS_te en_status) {
184 if(instance == USART1) {
186 }
187 else if(instance == USART2) {
189 }
190 else if(instance == USART6) {
192 }
193}
194
209static void usart_set_baud_rate(USART_CFG_ts *usart_cfg) {
210 usart_cfg->instance->USART_BRR &= ~(0xFFFF);
211 uint32_t usart_pclk = 0;
212 uint32_t temp_reg = 0;
213 uint32_t usartdiv = 0;
214 uint32_t usartdiv_mantissa;
215 uint32_t usartdiv_fraction;
216
217 if(usart_cfg->instance == USART1 || usart_cfg->instance == USART6) {
218 usart_pclk = rcc_get_apb2_clk();
219 }
220 else if(usart_cfg->instance == USART2) {
221 usart_pclk = rcc_get_apb1_clk();
222 }
223
224 if(usart_cfg->oversampling == USART_OVERSAMPLING_8) {
225 usartdiv = ((25 * usart_pclk) / (2 * usart_cfg->baud_rate));
226 }
227 else if(usart_cfg->oversampling == USART_OVERSAMPLING_16) {
228 usartdiv = ((25 * usart_pclk) / (4 * usart_cfg->baud_rate));
229 }
230
231 usartdiv_mantissa = usartdiv / 100;
232 temp_reg |= usartdiv_mantissa << 4;
233
234 usartdiv_fraction = (usartdiv - (usartdiv_mantissa * 100));
235
236 if(usart_cfg->oversampling == USART_OVERSAMPLING_8) {
237 // Round fraction to 3 bits for OVER8
238 usartdiv_fraction = (((usartdiv_fraction * 8) + 50) / 100) & ((uint8_t)0x07);
239 }
240 else if(usart_cfg->oversampling == USART_OVERSAMPLING_16) {
241 // Round fraction to 4 bits for OVER16
242 usartdiv_fraction = (((usartdiv_fraction * 16) + 50) / 100) & ((uint8_t)0x0F);
243 }
244
245 temp_reg |= usartdiv_fraction;
246 usart_cfg->instance->USART_BRR = temp_reg;
247}
248
250
260 if((USART1->USART_SR >> USART_SR_RXNE) & 0x1) {
261 uint8_t data = USART1->USART_DR;
263 }
264}
265
270}
271
280 if((USART6->USART_SR >> USART_SR_RXNE) & 0x1) {
281 uint8_t data = USART6->USART_DR;
283 }
284}
285
293void usart1_irq_data_recv_callback(uint8_t data) __attribute__((weak, alias("usart_irq_callback")));
294
302void usart6_irq_data_recv_callback(uint8_t data) __attribute__((weak, alias("usart_irq_callback")));
303
312void usart_irq_callback(uint8_t data) {
313 while(1);
314}
Arm Cortex-M4 NVIC driver public API.
Common utility module public API.
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
Definition common.c:22
EN_STATUS_te
Represents an enabled or disabled state.
Definition common.h:95
@ ENABLE
Definition common.h:100
@ DISABLE
Definition common.h:97
void nvic_set_interrupt(IRQn_te interrupt_line, EN_STATUS_te en_status)
Enables or disables an interrupt line in the NVIC.
void rcc_set_pclk_apb2(RCC_APB2ENR_te periph_position, EN_STATUS_te en_status)
Enables or disables the peripheral clock for an APB2 peripheral.
void rcc_reset_periph_apb2(RCC_APB2RSTR_te periph_position)
Resets an APB2 peripheral via RCC_APB2RSTR.
uint32_t rcc_get_apb2_clk(void)
Returns the current APB2 (high-speed) peripheral bus clock frequency in Hz.
void rcc_set_pclk_apb1(RCC_APB1ENR_te periph_position, EN_STATUS_te en_status)
Enables or disables the peripheral clock for an APB1 peripheral.
void rcc_reset_periph_apb1(RCC_APB1RSTR_te periph_position)
Resets an APB1 peripheral via RCC_APB1RSTR.
uint32_t rcc_get_apb1_clk(void)
Returns the current APB1 (low-speed) peripheral bus clock frequency in Hz.
void usart6_irq_data_recv_callback(uint8_t data) __attribute__((weak
Default weak implementation of usart6_irq_data_recv_callback.
void usart1_irq_data_recv_callback(uint8_t data) __attribute__((weak
Default weak implementation of usart1_irq_data_recv_callback.
static void usart_set_baud_rate(USART_CFG_ts *usart_cfg)
Computes and writes the BRR register for the configured baud rate.
static void usart_set_pclk(USART_REGDEF_ts const *instance, EN_STATUS_te en_status)
Enables or disables the peripheral clock for a USART instance.
void usart_send(USART_REGDEF_ts *instance, uint8_t *tx_buffer, uint32_t len)
Blocking USART transmit.
void usart_deinit(USART_REGDEF_ts const *instance)
Deinitializes the USART peripheral, disables its NVIC interrupt, and disables its clock.
void usart_receive(USART_REGDEF_ts const *instance, uint8_t *rx_buffer, uint32_t len)
Blocking USART receive.
void usart_init(USART_CFG_ts *usart_cfg)
Initializes the USART peripheral with the given configuration.
void usart_set_transmission(USART_REGDEF_ts *instance, EN_STATUS_te en_status)
Enables or disables the USART transmitter.
void usart_set_reception(USART_REGDEF_ts *instance, EN_STATUS_te en_status)
Enables or disables the USART receiver.
void usart_get_name(USART_REGDEF_ts const *instance, char *name)
Returns the name string of a USART peripheral instance.
@ USART_MODE_SYNC
@ USART_OVERSAMPLING_16
@ USART_OVERSAMPLING_8
@ USART_HW_FLOW_CONTROL_ENABLED
@ USART_PARITY_ODD
@ USART_PARITY_DISABLED
@ USART_PARITY_EVEN
@ USART_INTERRUPT_EN_TRUE
#define USART6
#define USART1
#define USART2
@ USART_SR_TC
@ USART_SR_RXNE
@ USART_SR_TXE
@ USART_CR2_STOP
@ USART_CR3_ONEBIT
@ USART_CR3_CTSE
@ USART_CR3_RTSE
@ RCC_APB2ENR_USART1EN
@ RCC_APB2ENR_USART6EN
@ USART_CR1_PCE
@ USART_CR1_RE
@ USART_CR1_PS
@ USART_CR1_OVER8
@ USART_CR1_UE
@ USART_CR1_M
@ USART_CR1_TE
@ USART_CR1_RXNEIE
@ RCC_APB2RSTR_USART1RST
@ RCC_APB2RSTR_USART6RST
@ RCC_APB1ENR_USART2EN
@ RCC_APB1RSTR_USART2RST
@ USART2_IRQn
@ USART6_IRQn
@ USART1_IRQn
STM32F401RE MCU-specific peripheral register definitions and bit position enumerations.
STM32F401RE RCC driver public API.
void USART2_IRQHandler(void)
USART2 interrupt handler. Currently empty — no interrupt sources configured.
void USART6_IRQHandler(void)
USART6 interrupt handler. Dispatches RXNE events to usart6_irq_data_recv_callback.
void USART1_IRQHandler(void)
USART1 interrupt handler. Dispatches RXNE events to usart1_irq_data_recv_callback.
void usart_irq_callback(uint8_t data)
Default fallback handler for unimplemented USART receive callbacks.
STM32F401RE USART driver public API.
Configuration structure for initializing a USART peripheral.
USART_OVERSAMPLING_te oversampling
USART_BAUD_RATE_te baud_rate
USART_SAMPLE_BIT_te sample_bit
USART_REGDEF_ts * instance
USART_FRAME_STOP_BITS_te frame_stop_bits
USART_HW_FLOW_CONTROL_te hw_flow_control
USART_FRAME_DATA_BITS_te frame_data_bits
USART_INTERRUPT_EN_te interrupt_en
USART_MODE_te mode
USART_PARITY_te parity
USART peripheral register map.
uint32_t volatile USART_BRR
uint32_t volatile USART_DR
uint32_t volatile USART_CR3
uint32_t volatile USART_CR1
uint32_t volatile USART_SR
uint32_t volatile USART_CR2