1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "hardware/address_mapped.h"
8 #include "hardware/platform_defs.h"
9 #include "hardware/uart.h"
10 
11 #include "hardware/structs/uart.h"
12 #include "hardware/resets.h"
13 #include "hardware/clocks.h"
14 
uart_clock_get_hz(__unused uart_inst_t * inst)15 static inline uint32_t uart_clock_get_hz(__unused uart_inst_t *inst) {
16     return clock_get_hz(UART_CLOCK_NUM(inst));
17 }
18 
19 #include "hardware/timer.h"
20 
21 #include "pico/assert.h"
22 #include "pico.h"
23 
24 check_hw_layout(uart_hw_t, fr, UART_UARTFR_OFFSET);
25 check_hw_layout(uart_hw_t, dmacr, UART_UARTDMACR_OFFSET);
26 
27 #if PICO_UART_ENABLE_CRLF_SUPPORT
28 short uart_char_to_line_feed[NUM_UARTS];
29 #endif
30 
31 /// \tag::uart_reset[]
uart_reset(uart_inst_t * uart)32 static inline void uart_reset(uart_inst_t *uart) {
33     reset_block_num(uart_get_reset_num(uart));
34 }
35 
uart_unreset(uart_inst_t * uart)36 static inline void uart_unreset(uart_inst_t *uart) {
37     unreset_block_num_wait_blocking(uart_get_reset_num(uart));
38 }
39 /// \end::uart_reset[]
40 
41 /// \tag::uart_init[]
uart_init(uart_inst_t * uart,uint baudrate)42 uint uart_init(uart_inst_t *uart, uint baudrate) {
43     invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
44 
45     if (uart_clock_get_hz(uart) == 0) {
46         return 0;
47     }
48 
49     uart_reset(uart);
50     uart_unreset(uart);
51 
52 #if PICO_UART_ENABLE_CRLF_SUPPORT
53     uart_set_translate_crlf(uart, PICO_UART_DEFAULT_CRLF);
54 #endif
55 
56     // Any LCR writes need to take place before enabling the UART
57     uint baud = uart_set_baudrate(uart, baudrate);
58 
59     // inline the uart_set_format() call, as we don't need the CR disable/re-enable
60     // protection, and also many people will never call it again, so having
61     // the generic function is not useful, and much bigger than this inlined
62     // code which is only a handful of instructions.
63     //
64     // The UART_UARTLCR_H_FEN_BITS setting is combined as well as it is the same register
65 #if 0
66     uart_set_format(uart, 8, 1, UART_PARITY_NONE);
67     // Enable FIFOs (must be before setting UARTEN, as this is an LCR access)
68     hw_set_bits(&uart_get_hw(uart)->lcr_h, UART_UARTLCR_H_FEN_BITS);
69 #else
70     uint data_bits = 8;
71     uint stop_bits = 1;
72     uint parity = UART_PARITY_NONE;
73     hw_write_masked(&uart_get_hw(uart)->lcr_h,
74         ((data_bits - 5u) << UART_UARTLCR_H_WLEN_LSB) |
75             ((stop_bits - 1u) << UART_UARTLCR_H_STP2_LSB) |
76             (bool_to_bit(parity != UART_PARITY_NONE) << UART_UARTLCR_H_PEN_LSB) |
77             (bool_to_bit(parity == UART_PARITY_EVEN) << UART_UARTLCR_H_EPS_LSB) |
78             UART_UARTLCR_H_FEN_BITS,
79         UART_UARTLCR_H_WLEN_BITS | UART_UARTLCR_H_STP2_BITS |
80             UART_UARTLCR_H_PEN_BITS | UART_UARTLCR_H_EPS_BITS |
81             UART_UARTLCR_H_FEN_BITS);
82 #endif
83 
84     // Enable the UART, both TX and RX
85     uart_get_hw(uart)->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS;
86 #if !PICO_UART_NO_DMACR_ENABLE
87     // Always enable DREQ signals -- no harm in this if DMA is not listening
88     uart_get_hw(uart)->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS;
89 #endif
90 
91     return baud;
92 }
93 /// \end::uart_init[]
94 
uart_deinit(uart_inst_t * uart)95 void uart_deinit(uart_inst_t *uart) {
96     invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
97     uart_reset(uart);
98 }
99 
uart_disable_before_lcr_write(uart_inst_t * uart)100 static uint32_t uart_disable_before_lcr_write(uart_inst_t *uart) {
101     // Notes from PL011 reference manual:
102     //
103     // - Before writing the LCR, if the UART is enabled it needs to be
104     //   disabled and any current TX + RX activity has to be completed
105     //
106     // - There is a BUSY flag which waits for the current TX char, but this is
107     //   OR'd with TX FIFO !FULL, so not usable when FIFOs are enabled and
108     //   potentially nonempty
109     //
110     // - FIFOs can't be set to disabled whilst a character is in progress
111     //   (else "FIFO integrity is not guaranteed")
112     //
113     // Combination of these means there is no general way to halt and poll for
114     // end of TX character, if FIFOs may be enabled. Either way, there is no
115     // way to poll for end of RX character.
116     //
117     // So, insert a 15 Baud period delay before changing the settings.
118     // 15 Baud is comfortably higher than start + max data + parity + stop.
119     // Anything else would require API changes to permit a non-enabled UART
120     // state after init() where settings can be changed safely.
121     uint32_t cr_save = uart_get_hw(uart)->cr;
122 
123     if (cr_save & UART_UARTCR_UARTEN_BITS) {
124         hw_clear_bits(&uart_get_hw(uart)->cr,
125             UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS);
126 
127         uint32_t current_ibrd = uart_get_hw(uart)->ibrd;
128         uint32_t current_fbrd = uart_get_hw(uart)->fbrd;
129 
130         // Note: Maximise precision here. Show working, the compiler will mop this up.
131         // Create a 16.6 fixed-point fractional division ratio; then scale to 32-bits.
132         uint32_t brdiv_ratio = 64u * current_ibrd + current_fbrd;
133         brdiv_ratio <<= 10;
134         // 3662 is ~(15 * 244.14) where 244.14 is 16e6 / 2^16
135         uint32_t scaled_freq = uart_clock_get_hz(uart) / 3662ul;
136         uint32_t wait_time_us = brdiv_ratio / scaled_freq;
137         busy_wait_us(wait_time_us);
138     }
139 
140     return cr_save;
141 }
142 
uart_write_lcr_bits_masked(uart_inst_t * uart,uint32_t values,uint32_t write_mask)143 static void uart_write_lcr_bits_masked(uart_inst_t *uart, uint32_t values, uint32_t write_mask) {
144     invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
145 
146     // (Potentially) Cleanly handle disabling the UART before touching LCR
147     uint32_t cr_save = uart_disable_before_lcr_write(uart);
148 
149     hw_write_masked(&uart_get_hw(uart)->lcr_h, values, write_mask);
150 
151     uart_get_hw(uart)->cr = cr_save;
152 }
153 
154 /// \tag::uart_set_baudrate[]
uart_set_baudrate(uart_inst_t * uart,uint baudrate)155 uint uart_set_baudrate(uart_inst_t *uart, uint baudrate) {
156     invalid_params_if(HARDWARE_UART, baudrate == 0);
157     uint32_t baud_rate_div = (8 * uart_clock_get_hz(uart) / baudrate) + 1;
158     uint32_t baud_ibrd = baud_rate_div >> 7;
159     uint32_t baud_fbrd;
160 
161     if (baud_ibrd == 0) {
162         baud_ibrd = 1;
163         baud_fbrd = 0;
164     } else if (baud_ibrd >= 65535) {
165         baud_ibrd = 65535;
166         baud_fbrd = 0;
167     }  else {
168         baud_fbrd = (baud_rate_div & 0x7f) >> 1;
169     }
170 
171     uart_get_hw(uart)->ibrd = baud_ibrd;
172     uart_get_hw(uart)->fbrd = baud_fbrd;
173 
174     // PL011 needs a (dummy) LCR_H write to latch in the divisors.
175     // We don't want to actually change LCR_H contents here.
176     uart_write_lcr_bits_masked(uart, 0, 0);
177 
178     // See datasheet
179     return (4 * uart_clock_get_hz(uart)) / (64 * baud_ibrd + baud_fbrd);
180 }
181 /// \end::uart_set_baudrate[]
182 
uart_set_format(uart_inst_t * uart,uint data_bits,uint stop_bits,uart_parity_t parity)183 void uart_set_format(uart_inst_t *uart, uint data_bits, uint stop_bits, uart_parity_t parity) {
184     invalid_params_if(HARDWARE_UART, data_bits < 5 || data_bits > 8);
185     invalid_params_if(HARDWARE_UART, stop_bits != 1 && stop_bits != 2);
186     invalid_params_if(HARDWARE_UART, parity != UART_PARITY_NONE && parity != UART_PARITY_EVEN && parity != UART_PARITY_ODD);
187 
188     uart_write_lcr_bits_masked(uart,
189         ((data_bits - 5u) << UART_UARTLCR_H_WLEN_LSB) |
190         ((stop_bits - 1u) << UART_UARTLCR_H_STP2_LSB) |
191         (bool_to_bit(parity != UART_PARITY_NONE) << UART_UARTLCR_H_PEN_LSB) |
192         (bool_to_bit(parity == UART_PARITY_EVEN) << UART_UARTLCR_H_EPS_LSB),
193         UART_UARTLCR_H_WLEN_BITS |
194         UART_UARTLCR_H_STP2_BITS |
195         UART_UARTLCR_H_PEN_BITS |
196         UART_UARTLCR_H_EPS_BITS);
197 }
198 
uart_set_fifo_enabled(uart_inst_t * uart,bool enabled)199 void uart_set_fifo_enabled(uart_inst_t *uart, bool enabled) {
200 
201     uint32_t lcr_h_fen_bits = 0;
202 
203     if (enabled) {
204         lcr_h_fen_bits = UART_UARTLCR_H_FEN_BITS;
205     }
206 
207     uart_write_lcr_bits_masked(uart, lcr_h_fen_bits, UART_UARTLCR_H_FEN_BITS);
208 }
209 
uart_set_break(uart_inst_t * uart,bool en)210 void uart_set_break(uart_inst_t *uart, bool en) {
211 
212     uint32_t lcr_h_brk_bits = 0;
213 
214     if (en) {
215         lcr_h_brk_bits = UART_UARTLCR_H_BRK_BITS;
216     }
217 
218     uart_write_lcr_bits_masked(uart, lcr_h_brk_bits, UART_UARTLCR_H_BRK_BITS);
219 }
220 
uart_set_translate_crlf(uart_inst_t * uart,bool crlf)221 void uart_set_translate_crlf(uart_inst_t *uart, bool crlf) {
222 #if PICO_UART_ENABLE_CRLF_SUPPORT
223     uart_char_to_line_feed[uart_get_index(uart)] = crlf ? '\n' : 0x100;
224 #else
225     panic_unsupported();
226 #endif
227 }
228 
uart_is_readable_within_us(uart_inst_t * uart,uint32_t us)229 bool uart_is_readable_within_us(uart_inst_t *uart, uint32_t us) {
230     uint32_t t = time_us_32();
231     do {
232         if (uart_is_readable(uart)) {
233              return true;
234         }
235     } while ((time_us_32() - t) <= us);
236     return false;
237 }
238