1use core::cell::Cell;
8use kernel::ErrorCode;
9
10use kernel::hil;
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::cells::TakeCell;
13use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
14use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
15use kernel::utilities::StaticRef;
16
17pub const UART0_BASE: StaticRef<UartRegisters> =
18 unsafe { StaticRef::new(0x6000_0000 as *const UartRegisters) };
19
20register_structs! {
21 pub UartRegisters {
22 (0x000 => fifo: ReadWrite<u32, FIFO::Register>),
23 (0x004 => int_raw: ReadWrite<u32, INT::Register>),
24 (0x008 => int_st: ReadWrite<u32, INT::Register>),
25 (0x00C => int_ena: ReadWrite<u32, INT::Register>),
26 (0x010 => int_clr: ReadWrite<u32, INT::Register>),
27 (0x014 => clkdiv: ReadWrite<u32, CLKDIV::Register>),
28 (0x018 => autobaud: ReadWrite<u32, AUTOBAUD::Register>),
29 (0x01C => status: ReadWrite<u32, STATUS::Register>),
30 (0x020 => conf0: ReadWrite<u32, CONF0::Register>),
31 (0x024 => conf1: ReadWrite<u32, CONF1::Register>),
32 (0x028 => lowpulse: ReadWrite<u32, LOWPULSE::Register>),
33 (0x02C => highpulse: ReadWrite<u32, HIGHPULSE::Register>),
34 (0x030 => rxd_cnt: ReadWrite<u32, RXD_CNT::Register>),
35 (0x034 => flow_config: ReadWrite<u32, FLOW_CONFIG::Register>),
36 (0x038 => sleep_conf: ReadWrite<u32, SLEEP_CONF::Register>),
37 (0x03C => swfc_conf: ReadWrite<u32, SWFC_CONF::Register>),
38 (0x040 => idle_conf: ReadWrite<u32, IDLE_CONF::Register>),
39 (0x044 => rs485_conf: ReadWrite<u32, RS485_CONF::Register>),
40 (0x048 => at_cmd_precnt: ReadWrite<u32, AT_CMD_PRECNT::Register>),
41 (0x04C => at_cmd_postcnt: ReadWrite<u32, AT_CMD_POSTCNT::Register>),
42 (0x050 => at_cmd_gaptout: ReadWrite<u32, AT_CMD_GAPTOUT::Register>),
43 (0x054 => at_cmd_char: ReadWrite<u32, AT_CMD_CHAR::Register>),
44 (0x058 => mem_conf: ReadWrite<u32, MEM_CONF::Register>),
45 (0x05C => _reserved0),
46 (0x064 => mem_cnt_status: ReadWrite<u32, MEM_CNT_STATUS::Register>),
47 (0x068 => pospulse: ReadWrite<u32, POSPULSE::Register>),
48 (0x06C => negpulse: ReadWrite<u32, NEGPULSE::Register>),
49 (0x070 => @END),
50 }
51}
52
53register_bitfields![u32,
54 FIFO [
55 RXFIFO_RD_BYTE OFFSET(0) NUMBITS(8) [],
56 ],
57 INT [
58 RXFIFO_FULL_INT OFFSET(0) NUMBITS(1) [],
59 TXFIFO_EMPTY_INT OFFSET(1) NUMBITS(1) [],
60 PARITY_ERR_INT OFFSET(2) NUMBITS(1) [],
61 FRM_ERR_INT OFFSET(3) NUMBITS(1) [],
62 RXFIFO_OVF_INT OFFSET(4) NUMBITS(1) [],
63 DSR_CHG_INT OFFSET(5) NUMBITS(1) [],
64 CTS_CHG_INT OFFSET(6) NUMBITS(1) [],
65 BRK_DET_INT OFFSET(7) NUMBITS(1) [],
66 RXFIFO_TOUT_INT OFFSET(8) NUMBITS(1) [],
67 SW_XON_INT OFFSET(9) NUMBITS(1) [],
68 SW_XOFF_INT OFFSET(10) NUMBITS(1) [],
69 GLITCH_DET_INT OFFSET(11) NUMBITS(1) [],
70 TX_BRK_DONE_INT OFFSET(12) NUMBITS(1) [],
71 TX_BRK_IDLE_DONE_INT OFFSET(13) NUMBITS(1) [],
72 TX_DONE_INT OFFSET(14) NUMBITS(1) [],
73 RS485_PARITY_ERR_INT OFFSET(15) NUMBITS(1) [],
74 RS485_FRM_ERR_INT OFFSET(16) NUMBITS(1) [],
75 RS485_CLASH_INT OFFSET(17) NUMBITS(1) [],
76 AT_CMD_CHAR_DET_INT OFFSET(18) NUMBITS(1) [],
77 ],
78 CLKDIV [
79 CLKDIV OFFSET(0) NUMBITS(20) [],
80 CLKDIV_FRAG OFFSET(20) NUMBITS(4) [],
81 ],
82 AUTOBAUD [
83 AUTOBAUD_EN OFFSET(0) NUMBITS(1) [],
84 GLITCH_FILT OFFSET(8) NUMBITS(8) [],
85 ],
86 STATUS [
87 RXFIFO_CNT OFFSET(0) NUMBITS(8) [],
88 ST_URX_OUT OFFSET(8) NUMBITS(4) [],
89 DSRN OFFSET(13) NUMBITS(1) [],
90 CTSN OFFSET(14) NUMBITS(1) [],
91 RXD OFFSET(15) NUMBITS(1) [],
92 TXFIFO_CNT OFFSET(16) NUMBITS(8) [],
93 ST_UTX_OUT OFFSET(24) NUMBITS(4) [],
94 DTRN OFFSET(29) NUMBITS(1) [],
95 RTSN OFFSET(30) NUMBITS(1) [],
96 TXD OFFSET(31) NUMBITS(1) [],
97 ],
98 CONF0 [
99 PARITY OFFSET(0) NUMBITS(1) [],
100 PARITY_EN OFFSET(1) NUMBITS(1) [],
101 BIT_NUM OFFSET(2) NUMBITS(2) [],
102 STOP_BIT_NUM OFFSET(4) NUMBITS(2) [],
103 SW_RTS OFFSET(6) NUMBITS(1) [],
104 SW_DTR OFFSET(7) NUMBITS(1) [],
105 TXD_BRK OFFSET(8) NUMBITS(1) [],
106 IRDA_DPLX OFFSET(9) NUMBITS(1) [],
107 IRDA_TX_EN OFFSET(10) NUMBITS(1) [],
108 IRDA_WCTL OFFSET(11) NUMBITS(1) [],
109 IRDA_TX_INV OFFSET(12) NUMBITS(1) [],
110 IRDA_RX_INV OFFSET(13) NUMBITS(1) [],
111 LOOPBACK OFFSET(14) NUMBITS(1) [],
112 TX_FLOW_EN OFFSET(15) NUMBITS(1) [],
113 IRDA_EN OFFSET(16) NUMBITS(1) [],
114 RXFIFO_RST OFFSET(17) NUMBITS(1) [],
115 TXFIFO_RST OFFSET(18) NUMBITS(1) [],
116 RXD_INV OFFSET(19) NUMBITS(1) [],
117 CTS_INV OFFSET(20) NUMBITS(1) [],
118 DSR_INV OFFSET(21) NUMBITS(1) [],
119 TXD_INV OFFSET(22) NUMBITS(1) [],
120 RTS_INV OFFSET(23) NUMBITS(1) [],
121 DTR_INV OFFSET(24) NUMBITS(1) [],
122 TICK_REF_ALWAYS_ON OFFSET(27) NUMBITS(1) [],
123 ],
124 CONF1 [
125 RXFIFO_FULL_THRHD OFFSET(0) NUMBITS(7) [],
126 TXFIFO_EMPTY_THRHD OFFSET(8) NUMBITS(6) [],
127 RX_FLOW_THRHD OFFSET(16) NUMBITS(6) [],
128 RX_FLOW_EN OFFSET(23) NUMBITS(1) [],
129 RX_TOUT_THRHD OFFSET(24) NUMBITS(7) [],
130 RX_TOUT_EN OFFSET(31) NUMBITS(1) [],
131 ],
132 LOWPULSE [
133 LOWPULSE_MIN_CNT OFFSET(0) NUMBITS(20) [],
134 ],
135 HIGHPULSE [
136 HIGHPULSE_MIN_CNT OFFSET(0) NUMBITS(20) []
137 ],
138 RXD_CNT [
139 RXD_EDGE_CNT OFFSET(0) NUMBITS(10) [],
140 ],
141 FLOW_CONFIG [
142 SW_FLOW_CON_EN OFFSET(0) NUMBITS(1) [],
143 XONOFF_DEL OFFSET(1) NUMBITS(1) [],
144 FORCE_XON OFFSET(2) NUMBITS(1) [],
145 FORCE_XOFF OFFSET(3) NUMBITS(1) [],
146 SEND_XON OFFSET(4) NUMBITS(1) [],
147 SEND_XOFF OFFSET(5) NUMBITS(1) [],
148 ],
149 SLEEP_CONF [
150 ACTIVE_THRESHOLD OFFSET(0) NUMBITS(10) [],
151 ],
152 SWFC_CONF [
153 XON_THRESHOLD OFFSET(0) NUMBITS(8) [],
154 XOFF_THRESHOLD OFFSET(8) NUMBITS(8) [],
155 XON_CHAR OFFSET(16) NUMBITS(8) [],
156 XOFF_CHAR OFFSET(24) NUMBITS(8) [],
157 ],
158 IDLE_CONF [
159 RX_IDLE_THRHD OFFSET(0) NUMBITS(10) [],
160 TX_IDLE_NUM OFFSET(10) NUMBITS(10) [],
161 TX_BRK_NUM OFFSET(20) NUMBITS(8) [],
162 ],
163 RS485_CONF [
164 RS485_EN OFFSET(0) NUMBITS(1) [],
165 DL0_EN OFFSET(1) NUMBITS(1) [],
166 DL1_EN OFFSET(2) NUMBITS(1) [],
167 RS485TX_RX_EN OFFSET(3) NUMBITS(1) [],
168 RS485RXBY_TX_EN OFFSET(4) NUMBITS(1) [],
169 RS485_RX_DLY_NUM OFFSET(5) NUMBITS(1) [],
170 RS485_TX_DLY_NUM OFFSET(6) NUMBITS(4) [],
171 ],
172 AT_CMD_PRECNT [
173 PRE_IDLE_NUM OFFSET(0) NUMBITS(24) [],
174 ],
175 AT_CMD_POSTCNT [
176 POST_IDLE_NUM OFFSET(0) NUMBITS(24) [],
177 ],
178 AT_CMD_GAPTOUT [
179 RX_GAP_TOUT OFFSET(0) NUMBITS(24) [],
180 ],
181 AT_CMD_CHAR [
182 AT_CMD_CHAR_REG OFFSET(0) NUMBITS(8) [],
183 CHAR_NUM OFFSET(8) NUMBITS(8) [],
184 ],
185 MEM_CONF [
186 MEM_PD OFFSET(0) NUMBITS(1) [],
187 RX_SIZE OFFSET(3) NUMBITS(4) [],
188 TX_SIZE OFFSET(7) NUMBITS(4) [],
189 RX_FLOW_THRHD_H3 OFFSET(15) NUMBITS(3) [],
190 RX_TOUT_THRHD_H3 OFFSET(18) NUMBITS(3) [],
191 XON_THRESHOLD_H2 OFFSET(21) NUMBITS(2) [],
192 XOFF_THRESHOLD_H2 OFFSET(23) NUMBITS(2) [],
193 RX_MEM_FULL_THRHD OFFSET(25) NUMBITS(3) [],
194 TX_MEM_EMPTY_THRHD OFFSET(28) NUMBITS(3) [],
195 ],
196 MEM_CNT_STATUS [
197 RX_MEM_CNT OFFSET(0) NUMBITS(3) [],
198 TX_MEM_CNT OFFSET(3) NUMBITS(3) [],
199 ],
200 POSPULSE [
201 POSEDGE_MIN_CNT OFFSET(0) NUMBITS(20) [],
202 ],
203 NEGPULSE [
204 NEGEDGE_MIN_CNT OFFSET(0) NUMBITS(20) [],
205 ],
206];
207
208pub struct Uart<'a> {
209 registers: StaticRef<UartRegisters>,
210 tx_client: OptionalCell<&'a dyn hil::uart::TransmitClient>,
211 rx_client: OptionalCell<&'a dyn hil::uart::ReceiveClient>,
212
213 tx_buffer: TakeCell<'static, [u8]>,
214 tx_len: Cell<usize>,
215 tx_index: Cell<usize>,
216
217 rx_buffer: TakeCell<'static, [u8]>,
218 rx_index: Cell<usize>,
219 rx_len: Cell<usize>,
220}
221
222#[derive(Copy, Clone)]
223pub struct UartParams {
224 pub baud_rate: u32,
225}
226
227impl<'a> Uart<'a> {
228 pub fn new(base: StaticRef<UartRegisters>) -> Uart<'a> {
229 Uart {
230 registers: base,
231 tx_client: OptionalCell::empty(),
232 rx_client: OptionalCell::empty(),
233 tx_buffer: TakeCell::empty(),
234 tx_len: Cell::new(0),
235 tx_index: Cell::new(0),
236 rx_buffer: TakeCell::empty(),
237 rx_index: Cell::new(0),
238 rx_len: Cell::new(0),
239 }
240 }
241
242 fn enable_tx_interrupt(&self) {
243 let regs = self.registers;
244
245 regs.int_ena.modify(
246 INT::TXFIFO_EMPTY_INT::SET
247 + INT::TX_BRK_DONE_INT::SET
248 + INT::TX_BRK_IDLE_DONE_INT::SET
249 + INT::TX_DONE_INT::SET,
250 );
251 }
252
253 pub fn clear_tx_interrupt(&self) {
254 let regs = self.registers;
255
256 regs.int_clr.modify(
257 INT::TXFIFO_EMPTY_INT::SET
258 + INT::TX_BRK_DONE_INT::SET
259 + INT::TX_BRK_IDLE_DONE_INT::SET
260 + INT::TX_DONE_INT::SET,
261 );
262 }
263
264 pub fn disable_tx_interrupt(&self) {
265 let regs = self.registers;
266 regs.int_ena.modify(
267 INT::TXFIFO_EMPTY_INT::CLEAR
268 + INT::TX_BRK_DONE_INT::CLEAR
269 + INT::TX_BRK_IDLE_DONE_INT::CLEAR
270 + INT::TX_DONE_INT::CLEAR,
271 );
272 }
273
274 fn enable_rx_interrupt(&self) {
275 let regs = self.registers;
276
277 regs.int_ena.modify(
278 INT::RXFIFO_FULL_INT::SET + INT::RXFIFO_OVF_INT::SET + INT::RXFIFO_TOUT_INT::SET,
279 );
280 }
281
282 pub fn clear_rx_interrupt(&self) {
283 let regs = self.registers;
284
285 regs.int_clr.modify(
286 INT::RXFIFO_FULL_INT::SET + INT::RXFIFO_OVF_INT::SET + INT::RXFIFO_TOUT_INT::SET,
287 );
288 }
289
290 pub fn disable_rx_interrupt(&self) {
291 let regs = self.registers;
292 regs.int_ena.modify(
293 INT::RXFIFO_FULL_INT::CLEAR + INT::RXFIFO_OVF_INT::CLEAR + INT::RXFIFO_TOUT_INT::CLEAR,
294 );
295 }
296
297 fn tx_progress(&self) {
298 let regs = self.registers;
299 let idx = self.tx_index.get();
300 let len = self.tx_len.get();
301
302 if idx < len {
303 self.tx_buffer.map(|tx_buf| {
306 let tx_len = len - idx;
307
308 for i in 0..tx_len {
309 if regs.status.read(STATUS::TXFIFO_CNT) >= 127 {
310 break;
311 }
312 let tx_idx = idx + i;
313 regs.fifo
314 .write(FIFO::RXFIFO_RD_BYTE.val(tx_buf[tx_idx] as u32));
315 self.tx_index.set(tx_idx + 1)
316 }
317 });
318 }
319 }
320
321 fn rx_progress(&self) {
322 let regs = self.registers;
323 let idx = self.rx_index.get();
324 let len = self.rx_len.get();
325
326 if idx < len {
327 self.rx_buffer.map(|rx_buf| {
330 let rx_len = len - idx;
331
332 for i in 0..rx_len {
333 if regs.status.read(STATUS::RXFIFO_CNT) == 0 {
334 break;
335 }
336 let rx_idx = idx + i;
337 rx_buf[rx_idx] = regs.fifo.read(FIFO::RXFIFO_RD_BYTE) as u8;
338 self.rx_index.set(rx_idx + 1)
339 }
340 });
341 }
342 }
343
344 pub fn handle_interrupt(&self) {
345 let regs = self.registers;
346 let intrs = regs.int_st.extract();
347
348 if intrs.is_set(INT::TXFIFO_EMPTY_INT) {
349 self.clear_tx_interrupt();
350 if self.tx_index.get() == self.tx_len.get() {
351 self.disable_tx_interrupt();
352 self.tx_client.map(|client| {
355 self.tx_buffer.take().map(|tx_buf| {
356 client.transmitted_buffer(tx_buf, self.tx_len.get(), Ok(()));
357 });
358 });
359 } else {
360 self.tx_progress();
362 }
363 }
364
365 if intrs.is_set(INT::RXFIFO_FULL_INT) || intrs.is_set(INT::RXFIFO_TOUT_INT) {
366 self.clear_rx_interrupt();
367 if self.rx_index.get() == self.rx_len.get() {
368 self.disable_rx_interrupt();
369 self.rx_client.map(|client| {
372 self.rx_buffer.take().map(|rx_buf| {
373 client.received_buffer(
374 rx_buf,
375 self.rx_len.get(),
376 Ok(()),
377 hil::uart::Error::None,
378 );
379 });
380 });
381 } else {
382 self.rx_progress();
384 }
385 }
386 }
387
388 pub fn transmit_sync(&self, bytes: &[u8]) {
389 let regs = self.registers;
390 for b in bytes.iter() {
391 while regs.status.read(STATUS::TXFIFO_CNT) > 8 {}
392 regs.fifo.write(FIFO::RXFIFO_RD_BYTE.val(*b as u32));
393 }
394 }
395}
396
397impl hil::uart::Configure for Uart<'_> {
398 fn configure(&self, _params: hil::uart::Parameters) -> Result<(), ErrorCode> {
399 self.disable_rx_interrupt();
401 self.disable_tx_interrupt();
402
403 Ok(())
404 }
405}
406
407impl<'a> hil::uart::Transmit<'a> for Uart<'a> {
408 fn set_transmit_client(&self, client: &'a dyn hil::uart::TransmitClient) {
409 self.tx_client.set(client);
410 }
411
412 fn transmit_buffer(
413 &self,
414 tx_data: &'static mut [u8],
415 tx_len: usize,
416 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
417 if tx_len == 0 || tx_len > tx_data.len() {
418 Err((ErrorCode::SIZE, tx_data))
419 } else if self.tx_buffer.is_some() {
420 Err((ErrorCode::BUSY, tx_data))
421 } else {
422 self.tx_buffer.replace(tx_data);
424 self.tx_len.set(tx_len);
425 self.tx_index.set(0);
426
427 self.enable_tx_interrupt();
428
429 self.tx_progress();
430 Ok(())
431 }
432 }
433
434 fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
435 Err(ErrorCode::FAIL)
436 }
437
438 fn transmit_abort(&self) -> Result<(), ErrorCode> {
439 Err(ErrorCode::FAIL)
440 }
441}
442
443impl<'a> hil::uart::Receive<'a> for Uart<'a> {
445 fn set_receive_client(&self, client: &'a dyn hil::uart::ReceiveClient) {
446 self.rx_client.set(client);
447 }
448
449 fn receive_buffer(
450 &self,
451 rx_buffer: &'static mut [u8],
452 rx_len: usize,
453 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
454 if rx_len == 0 || rx_len > rx_buffer.len() {
455 return Err((ErrorCode::SIZE, rx_buffer));
456 }
457
458 self.rx_buffer.replace(rx_buffer);
459 self.rx_index.set(0);
460 self.rx_len.set(rx_len);
461
462 self.enable_rx_interrupt();
463
464 self.rx_progress();
465
466 Ok(())
467 }
468
469 fn receive_word(&self) -> Result<(), ErrorCode> {
470 Err(ErrorCode::FAIL)
471 }
472
473 fn receive_abort(&self) -> Result<(), ErrorCode> {
474 Err(ErrorCode::FAIL)
475 }
476}