1use crate::dma;
8use crate::usci::{self, UsciARegisters};
9use core::cell::Cell;
10use kernel::hil;
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16const DEFAULT_CLOCK_FREQ_HZ: u32 = crate::cs::SMCLK_HZ;
17
18struct BaudFraction {
19 frac: f32,
20 reg_val: u8,
21}
22
23#[rustfmt::skip]
24const BAUD_FRACTIONS: &[BaudFraction; 36] = &[
26 BaudFraction { frac: 0.0000, reg_val: 0x00 },
27 BaudFraction { frac: 0.0529, reg_val: 0x01 },
28 BaudFraction { frac: 0.0715, reg_val: 0x02 },
29 BaudFraction { frac: 0.0835, reg_val: 0x04 },
30 BaudFraction { frac: 0.1001, reg_val: 0x08 },
31 BaudFraction { frac: 0.1252, reg_val: 0x10 },
32 BaudFraction { frac: 0.1430, reg_val: 0x20 },
33 BaudFraction { frac: 0.1670, reg_val: 0x11 },
34 BaudFraction { frac: 0.2147, reg_val: 0x21 },
35 BaudFraction { frac: 0.2224, reg_val: 0x22 },
36 BaudFraction { frac: 0.2503, reg_val: 0x44 },
37 BaudFraction { frac: 0.3000, reg_val: 0x25 },
38 BaudFraction { frac: 0.3335, reg_val: 0x49 },
39 BaudFraction { frac: 0.3575, reg_val: 0x4A },
40 BaudFraction { frac: 0.3753, reg_val: 0x52 },
41 BaudFraction { frac: 0.4003, reg_val: 0x92 },
42 BaudFraction { frac: 0.4286, reg_val: 0x53 },
43 BaudFraction { frac: 0.4378, reg_val: 0x55 },
44 BaudFraction { frac: 0.5002, reg_val: 0xAA },
45 BaudFraction { frac: 0.5715, reg_val: 0x6B },
46 BaudFraction { frac: 0.6003, reg_val: 0xAD },
47 BaudFraction { frac: 0.6254, reg_val: 0xB5 },
48 BaudFraction { frac: 0.6432, reg_val: 0xB6 },
49 BaudFraction { frac: 0.6667, reg_val: 0xD6 },
50 BaudFraction { frac: 0.7001, reg_val: 0xB7 },
51 BaudFraction { frac: 0.7147, reg_val: 0xBB },
52 BaudFraction { frac: 0.7503, reg_val: 0xDD },
53 BaudFraction { frac: 0.7861, reg_val: 0xED },
54 BaudFraction { frac: 0.8004, reg_val: 0xEE },
55 BaudFraction { frac: 0.8333, reg_val: 0xBF },
56 BaudFraction { frac: 0.8464, reg_val: 0xDF },
57 BaudFraction { frac: 0.8572, reg_val: 0xEF },
58 BaudFraction { frac: 0.8751, reg_val: 0xF7 },
59 BaudFraction { frac: 0.9004, reg_val: 0xFB },
60 BaudFraction { frac: 0.9170, reg_val: 0xFD },
61 BaudFraction { frac: 0.9288, reg_val: 0xFE },
62];
63
64pub struct Uart<'a> {
65 registers: StaticRef<UsciARegisters>,
66 clock_frequency: u32,
67
68 tx_client: OptionalCell<&'a dyn hil::uart::TransmitClient>,
69 tx_busy: Cell<bool>,
70 tx_dma: OptionalCell<&'a dma::DmaChannel<'a>>,
71 pub(crate) tx_dma_chan: usize,
72 tx_dma_src: u8,
73
74 rx_client: OptionalCell<&'a dyn hil::uart::ReceiveClient>,
75 rx_busy: Cell<bool>,
76 rx_dma: OptionalCell<&'a dma::DmaChannel<'a>>,
77 pub(crate) rx_dma_chan: usize,
78 rx_dma_src: u8,
79}
80
81impl<'a> Uart<'a> {
82 pub const fn new(
83 registers: StaticRef<UsciARegisters>,
84 tx_dma_chan: usize,
85 rx_dma_chan: usize,
86 tx_dma_src: u8,
87 rx_dma_src: u8,
88 ) -> Self {
89 Self {
90 registers,
91 clock_frequency: DEFAULT_CLOCK_FREQ_HZ,
92
93 tx_client: OptionalCell::empty(),
94 tx_dma: OptionalCell::empty(),
95 tx_dma_chan,
96 tx_dma_src,
97 tx_busy: Cell::new(false),
98
99 rx_client: OptionalCell::empty(),
100 rx_dma: OptionalCell::empty(),
101 rx_dma_chan,
102 rx_dma_src,
103 rx_busy: Cell::new(false),
104 }
105 }
106
107 pub fn set_dma(&self, tx_dma: &'a dma::DmaChannel<'a>, rx_dma: &'a dma::DmaChannel<'a>) {
108 self.tx_dma.replace(tx_dma);
109 self.rx_dma.replace(rx_dma);
110 }
111
112 pub fn transmit_sync(&self, data: &[u8]) {
113 for b in data.iter() {
114 while self.registers.statw.is_set(usci::UCAxSTATW::UCBUSY) {}
115 self.registers.txbuf.set(*b as u16);
116 }
117 }
118}
119
120impl dma::DmaClient for Uart<'_> {
121 fn transfer_done(
122 &self,
123 tx_buf: Option<&'static mut [u8]>,
124 rx_buf: Option<&'static mut [u8]>,
125 transmitted_bytes: usize,
126 ) {
127 if let Some(rxbuf) = rx_buf {
128 self.rx_busy.set(false);
130 self.rx_client.map(|client| {
131 client.received_buffer(rxbuf, transmitted_bytes, Ok(()), hil::uart::Error::None)
132 });
133 } else if let Some(txbuf) = tx_buf {
134 self.tx_busy.set(false);
136 self.tx_client
137 .map(|client| client.transmitted_buffer(txbuf, transmitted_bytes, Ok(())));
138 }
139 }
140}
141
142impl hil::uart::Configure for Uart<'_> {
143 fn configure(&self, params: hil::uart::Parameters) -> Result<(), ErrorCode> {
144 let regs = self.registers;
146 regs.ctlw0.modify(usci::UCAxCTLW0::UCSWRST::SET);
147
148 regs.ctlw0.modify(usci::UCAxCTLW0::UCMODE::UARTMode);
150
151 regs.ctlw0.modify(usci::UCAxCTLW0::UCSSEL::SMCLK);
153
154 match params.width {
156 hil::uart::Width::Eight => regs.ctlw0.modify(usci::UCAxCTLW0::UC7BIT::CLEAR),
157 hil::uart::Width::Seven => regs.ctlw0.modify(usci::UCAxCTLW0::UC7BIT::SET),
158 hil::uart::Width::Six => {
159 panic!("UART: width of 6 bit is not supported by this hardware!")
160 }
161 }
162
163 if params.stop_bits == hil::uart::StopBits::One {
165 regs.ctlw0.modify(usci::UCAxCTLW0::UCSPB::CLEAR);
166 } else {
167 regs.ctlw0.modify(usci::UCAxCTLW0::UCSPB::SET);
168 }
169
170 if params.parity == hil::uart::Parity::None {
172 regs.ctlw0.modify(usci::UCAxCTLW0::UCPEN::CLEAR);
173 } else {
174 regs.ctlw0.modify(usci::UCAxCTLW0::UCPEN::SET);
175 if params.parity == hil::uart::Parity::Even {
176 regs.ctlw0.modify(usci::UCAxCTLW0::UCPAR::SET);
177 } else {
178 regs.ctlw0.modify(usci::UCAxCTLW0::UCPAR::CLEAR);
179 }
180 }
181
182 let n = (self.clock_frequency / params.baud_rate) as u16;
184 let n_float = (self.clock_frequency as f32) / (params.baud_rate as f32);
185 let frac_part = n_float - (n as f32);
186 if n > 16 {
187 regs.brw.set(n >> 4); let ucbrf = (((n_float / 16.0f32) - ((n >> 4) as f32)) * 16.0f32) as u16;
190 regs.mctlw
191 .modify(usci::UCAxMCTLW::UCBRF.val(ucbrf) + usci::UCAxMCTLW::UCOS16::SET);
192 } else {
193 regs.brw.set(n);
195 regs.mctlw.modify(usci::UCAxMCTLW::UCOS16::CLEAR);
196 }
197
198 let mut ucbrs = BAUD_FRACTIONS[0].reg_val;
201 for val in BAUD_FRACTIONS.iter() {
202 if val.frac > frac_part {
203 break;
204 }
205 ucbrs = val.reg_val;
206 }
207 regs.mctlw.modify(usci::UCAxMCTLW::UCBRS.val(ucbrs as u16));
208
209 regs.ctlw0.modify(usci::UCAxCTLW0::UCSWRST::CLEAR);
211
212 let tx_conf = dma::DmaConfig {
214 src_chan: self.tx_dma_src,
215 mode: dma::DmaMode::Basic,
216 width: dma::DmaDataWidth::Width8Bit,
217 src_incr: dma::DmaPtrIncrement::Incr8Bit,
218 dst_incr: dma::DmaPtrIncrement::NoIncr,
219 };
220
221 let rx_conf = dma::DmaConfig {
222 src_chan: self.rx_dma_src,
223 mode: dma::DmaMode::Basic,
224 width: dma::DmaDataWidth::Width8Bit,
225 src_incr: dma::DmaPtrIncrement::NoIncr,
226 dst_incr: dma::DmaPtrIncrement::Incr8Bit,
227 };
228
229 self.tx_dma.map(|dma| dma.initialize(&tx_conf));
230 self.rx_dma.map(|dma| dma.initialize(&rx_conf));
231
232 Ok(())
233 }
234}
235
236impl<'a> hil::uart::Transmit<'a> for Uart<'a> {
237 fn set_transmit_client(&self, client: &'a dyn hil::uart::TransmitClient) {
238 self.tx_client.set(client);
239 }
240
241 fn transmit_buffer(
242 &self,
243 tx_buffer: &'static mut [u8],
244 tx_len: usize,
245 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
246 if (tx_len == 0) || (tx_len > tx_buffer.len()) {
247 return Err((ErrorCode::SIZE, tx_buffer));
248 }
249 if self.tx_busy.get() {
250 Err((ErrorCode::BUSY, tx_buffer))
251 } else {
252 self.tx_busy.set(true);
253 let tx_reg = core::ptr::addr_of!(self.registers.txbuf).cast::<()>();
254 self.tx_dma
255 .map(move |dma| dma.transfer_mem_to_periph(tx_reg, tx_buffer, tx_len));
256 Ok(())
257 }
258 }
259
260 fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
261 Err(ErrorCode::FAIL)
262 }
263
264 fn transmit_abort(&self) -> Result<(), ErrorCode> {
265 if !self.tx_busy.get() {
266 return Ok(());
267 }
268
269 self.tx_dma.map(|dma| {
270 let (nr_bytes, tx1, _rx1, _tx2, _rx2) = dma.stop();
271
272 self.tx_client.map(move |cl| {
273 if let Some(tx1_buf) = tx1 {
274 cl.transmitted_buffer(tx1_buf, nr_bytes, Err(ErrorCode::CANCEL));
275 }
276 });
277 });
278
279 Err(ErrorCode::BUSY)
280 }
281}
282
283impl<'a> hil::uart::Receive<'a> for Uart<'a> {
284 fn set_receive_client(&self, client: &'a dyn hil::uart::ReceiveClient) {
285 self.rx_client.set(client);
286 }
287
288 fn receive_buffer(
289 &self,
290 rx_buffer: &'static mut [u8],
291 rx_len: usize,
292 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
293 if (rx_len == 0) || (rx_len > rx_buffer.len()) {
294 return Err((ErrorCode::SIZE, rx_buffer));
295 }
296
297 if self.rx_busy.get() {
298 Err((ErrorCode::BUSY, rx_buffer))
299 } else {
300 self.rx_busy.set(true);
301 let rx_reg = core::ptr::addr_of!(self.registers.rxbuf).cast::<()>();
302 self.rx_dma
303 .map(move |dma| dma.transfer_periph_to_mem(rx_reg, rx_buffer, rx_len));
304 Ok(())
305 }
306 }
307
308 fn receive_word(&self) -> Result<(), ErrorCode> {
309 Err(ErrorCode::FAIL)
310 }
311
312 fn receive_abort(&self) -> Result<(), ErrorCode> {
313 if !self.rx_busy.get() {
314 return Ok(());
315 }
316
317 self.rx_dma.map(|dma| {
318 let (nr_bytes, _tx1, rx1, _tx2, _rx2) = dma.stop();
319
320 self.rx_client.map(move |cl| {
321 if let Some(rx1_buf) = rx1 {
322 cl.received_buffer(
323 rx1_buf,
324 nr_bytes,
325 Err(ErrorCode::CANCEL),
326 hil::uart::Error::Aborted,
327 );
328 }
329 });
330 });
331
332 Err(ErrorCode::BUSY)
333 }
334}