1use kernel::hil;
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::cells::TakeCell;
13use kernel::utilities::cells::VolatileCell;
14use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
15use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
16use kernel::utilities::StaticRef;
17use nrf5x::pinmux::Pinmux;
18
19const INSTANCES: [StaticRef<TwiRegisters>; 2] = unsafe {
21 [
22 StaticRef::new(0x40003000 as *const TwiRegisters),
23 StaticRef::new(0x40004000 as *const TwiRegisters),
24 ]
25};
26
27pub struct TWI<'a> {
32 registers: StaticRef<TwiRegisters>,
33 client: OptionalCell<&'a dyn hil::i2c::I2CHwMasterClient>,
34 slave_client: OptionalCell<&'a dyn hil::i2c::I2CHwSlaveClient>,
35 buf: TakeCell<'static, [u8]>,
36 slave_read_buf: TakeCell<'static, [u8]>,
37}
38
39#[repr(u32)]
41pub enum Speed {
42 K100 = 0x01980000,
43 K250 = 0x04000000,
44 K400 = 0x06400000,
45}
46
47impl TWI<'_> {
48 const fn new(registers: StaticRef<TwiRegisters>) -> Self {
49 Self {
50 registers,
51 client: OptionalCell::empty(),
52 slave_client: OptionalCell::empty(),
53 buf: TakeCell::empty(),
54 slave_read_buf: TakeCell::empty(),
55 }
56 }
57
58 pub const fn new_twi0() -> Self {
59 TWI::new(INSTANCES[0])
60 }
61
62 pub const fn new_twi1() -> Self {
63 TWI::new(INSTANCES[1])
64 }
65
66 pub fn configure(&self, scl: Pinmux, sda: Pinmux) {
68 self.registers.psel_scl.set(scl);
69 self.registers.psel_sda.set(sda);
70 }
71
72 pub fn set_speed(&self, speed: Speed) {
75 self.registers.frequency.set(speed as u32);
76 }
77
78 pub fn clear_events(&self) {
82 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
83 self.registers.events_error.write(EVENT::EVENT::CLEAR);
84 self.registers.events_rxstarted.write(EVENT::EVENT::CLEAR);
85 self.registers.events_txstarted.write(EVENT::EVENT::CLEAR);
86 self.registers.events_write.write(EVENT::EVENT::CLEAR);
87 self.registers.events_read.write(EVENT::EVENT::CLEAR);
88 self.registers.events_suspended.write(EVENT::EVENT::CLEAR);
89 self.registers.events_lastrx.write(EVENT::EVENT::CLEAR);
90 self.registers.events_lasttx.write(EVENT::EVENT::CLEAR);
91 }
92
93 pub fn disable_interrupts(&self) {
94 self.registers.inten.set(0x00);
96 self.registers.intenclr.set(0xFFFF_FFFF);
97 }
98
99 fn enable_master(&self) {
101 self.clear_events();
102 self.registers.enable.write(ENABLE::ENABLE::EnableMaster);
103 }
104
105 fn enable_slave(&self) {
107 self.clear_events();
108 self.registers.enable.write(ENABLE::ENABLE::EnableSlave);
109 }
110
111 fn disable(&self) {
113 self.clear_events();
114 self.disable_interrupts();
115 self.registers.enable.write(ENABLE::ENABLE::Disable);
116 }
117
118 pub fn handle_interrupt(&self) {
119 if self.is_master_enabled() {
120 if self.registers.events_stopped.is_set(EVENT::EVENT) {
121 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
122
123 self.client.map(|client| match self.buf.take() {
124 None => (),
125 Some(buf) => {
126 self.clear_events();
127 client.command_complete(buf, Ok(()));
128 }
129 });
130 }
131
132 if self.registers.events_error.is_set(EVENT::EVENT) {
133 self.registers.events_error.write(EVENT::EVENT::CLEAR);
134 let errorsrc = self.registers.errorsrc_master.extract();
135 self.registers
136 .errorsrc_master
137 .write(ERRORSRC::ANACK::ErrorDidNotOccur + ERRORSRC::DNACK::ErrorDidNotOccur);
138 self.client.map(|client| match self.buf.take() {
139 None => (),
140 Some(buf) => {
141 let status = if errorsrc.is_set(ERRORSRC::ANACK) {
142 Err(hil::i2c::Error::AddressNak)
143 } else if errorsrc.is_set(ERRORSRC::DNACK) {
144 Err(hil::i2c::Error::DataNak)
145 } else {
146 Ok(())
147 };
148 self.clear_events();
149 client.command_complete(buf, status);
150 }
151 });
152 }
153 } else {
154 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
155
156 if self.registers.events_rxstarted.is_set(EVENT::EVENT) {
159 self.registers.events_rxstarted.write(EVENT::EVENT::CLEAR);
160 self.slave_client.map(|client| {
161 if self.buf.is_none() {
162 client.write_expected();
163 }
164 });
165 }
166
167 if self.registers.events_txstarted.is_set(EVENT::EVENT) {
170 self.registers.events_txstarted.write(EVENT::EVENT::CLEAR);
171 self.slave_client.map(|client| {
172 if self.slave_read_buf.is_none() {
173 client.read_expected();
174 }
175 });
176 }
177
178 if self.registers.events_write.is_set(EVENT::EVENT) {
180 self.registers.events_write.write(EVENT::EVENT::CLEAR);
181 let length = self.registers.rxd_amount.read(AMOUNT::AMOUNT) as usize;
182 self.slave_client.map(|client| match self.buf.take() {
183 None => (),
184 Some(buf) => {
185 self.clear_events();
186 client.command_complete(
187 buf,
188 length,
189 hil::i2c::SlaveTransmissionType::Write,
190 );
191 }
192 });
193 }
194
195 if self.registers.events_read.is_set(EVENT::EVENT) {
196 self.registers.events_read.write(EVENT::EVENT::CLEAR);
197 let length = self.registers.txd_amount.read(AMOUNT::AMOUNT) as usize;
198 self.slave_client
199 .map(|client| match self.slave_read_buf.take() {
200 None => (),
201 Some(buf) => {
202 self.clear_events();
203 client.command_complete(
204 buf,
205 length,
206 hil::i2c::SlaveTransmissionType::Read,
207 );
208 }
209 });
210 }
211 }
212
213 self.registers.events_suspended.write(EVENT::EVENT::CLEAR);
215 self.registers.events_lastrx.write(EVENT::EVENT::CLEAR);
216 self.registers.events_lasttx.write(EVENT::EVENT::CLEAR);
217 }
218
219 pub fn is_enabled(&self) -> bool {
220 self.is_master_enabled() || self.is_slave_enabled()
221 }
222
223 fn is_master_enabled(&self) -> bool {
224 self.registers
225 .enable
226 .matches_all(ENABLE::ENABLE::EnableMaster)
227 }
228
229 fn is_slave_enabled(&self) -> bool {
230 self.registers
231 .enable
232 .matches_all(ENABLE::ENABLE::EnableSlave)
233 }
234}
235
236impl<'a> hil::i2c::I2CMaster<'a> for TWI<'a> {
237 fn set_master_client(&self, client: &'a dyn hil::i2c::I2CHwMasterClient) {
238 self.client.set(client);
239 }
240
241 fn enable(&self) {
242 self.enable_master();
243 }
244
245 fn disable(&self) {
246 self.disable();
247 }
248
249 fn write_read(
250 &self,
251 addr: u8,
252 data: &'static mut [u8],
253 write_len: usize,
254 read_len: usize,
255 ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
256 self.registers
257 .address_0
258 .write(ADDRESS::ADDRESS.val(addr as u32));
259 self.registers.txd_ptr.set(data.as_mut_ptr() as u32);
260 self.registers
261 .txd_maxcnt
262 .write(MAXCNT::MAXCNT.val(write_len as u32));
263 self.registers.rxd_ptr.set(data.as_mut_ptr() as u32);
264 self.registers
265 .rxd_maxcnt
266 .write(MAXCNT::MAXCNT.val(read_len as u32));
267 self.registers
272 .shorts
273 .write(SHORTS::LASTTX_STARTRX::EnableShortcut + SHORTS::LASTRX_STOP::EnableShortcut);
274 self.registers
275 .intenset
276 .write(INTE::STOPPED::Enable + INTE::ERROR::Enable);
277 self.registers.tasks_starttx.write(TASK::TASK::SET);
279 self.buf.replace(data);
280 Ok(())
281 }
282
283 fn write(
284 &self,
285 addr: u8,
286 data: &'static mut [u8],
287 len: usize,
288 ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
289 self.registers
290 .address_0
291 .write(ADDRESS::ADDRESS.val(addr as u32));
292 self.registers.txd_ptr.set(data.as_mut_ptr() as u32);
293 self.registers
294 .txd_maxcnt
295 .write(MAXCNT::MAXCNT.val(len as u32));
296 self.registers
299 .shorts
300 .write(SHORTS::LASTTX_STOP::EnableShortcut);
301 self.registers
302 .intenset
303 .write(INTE::STOPPED::Enable + INTE::ERROR::Enable);
304 self.registers.tasks_starttx.write(TASK::TASK::SET);
306 self.buf.replace(data);
307 Ok(())
308 }
309
310 fn read(
311 &self,
312 addr: u8,
313 buffer: &'static mut [u8],
314 len: usize,
315 ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
316 self.registers
317 .address_0
318 .write(ADDRESS::ADDRESS.val(addr as u32));
319 self.registers.rxd_ptr.set(buffer.as_mut_ptr() as u32);
320 self.registers
321 .rxd_maxcnt
322 .write(MAXCNT::MAXCNT.val(len as u32));
323 self.registers
326 .shorts
327 .write(SHORTS::LASTRX_STOP::EnableShortcut);
328 self.registers
329 .intenset
330 .write(INTE::STOPPED::Enable + INTE::ERROR::Enable);
331 self.registers.tasks_startrx.write(TASK::TASK::SET);
333 self.buf.replace(buffer);
334 Ok(())
335 }
336}
337
338impl<'a> hil::i2c::I2CSlave<'a> for TWI<'a> {
339 fn set_slave_client(&self, client: &'a dyn hil::i2c::I2CHwSlaveClient) {
340 self.slave_client.set(client);
341 }
342
343 fn enable(&self) {
344 self.enable_slave();
345 }
346
347 fn disable(&self) {
348 self.disable();
349 }
350
351 fn set_address(&self, addr: u8) -> Result<(), hil::i2c::Error> {
352 self.registers
353 .address_0
354 .write(ADDRESS::ADDRESS.val(addr as u32));
355 self.registers.config.modify(CONFIG::ADDRESS0::Enable);
356 Ok(())
357 }
358
359 fn write_receive(
360 &self,
361 data: &'static mut [u8],
362 max_len: usize,
363 ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
364 self.registers.rxd_ptr.set(data.as_mut_ptr() as u32);
365 self.registers
366 .rxd_maxcnt
367 .write(MAXCNT::MAXCNT.val(max_len as u32));
368
369 self.registers
370 .intenset
371 .modify(INTE::STOPPED::Enable + INTE::ERROR::Enable);
372
373 self.buf.replace(data);
374
375 self.registers.tasks_preparerx.write(TASK::TASK::SET);
376
377 Ok(())
378 }
379
380 fn read_send(
381 &self,
382 data: &'static mut [u8],
383 max_len: usize,
384 ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
385 self.registers.txd_ptr.set(data.as_mut_ptr() as u32);
386 self.registers
387 .txd_maxcnt
388 .write(MAXCNT::MAXCNT.val(max_len as u32));
389
390 self.registers
391 .intenset
392 .modify(INTE::STOPPED::Enable + INTE::ERROR::Enable + INTE::READ::Enable);
393
394 self.slave_read_buf.replace(data);
395
396 self.registers.tasks_preparetx.write(TASK::TASK::SET);
397
398 Ok(())
399 }
400
401 fn listen(&self) {
402 self.registers.tasks_preparerx.write(TASK::TASK::SET);
403 }
404}
405
406impl<'a> hil::i2c::I2CMasterSlave<'a> for TWI<'a> {}
407
408register_structs! {
413 pub TwiRegisters {
414 (0x00 => tasks_startrx: WriteOnly<u32, TASK::Register>),
416 (0x04 => _reserved0),
417 (0x08 => tasks_starttx: WriteOnly<u32, TASK::Register>),
419 (0x0C => _reserved1),
420 (0x14 => tasks_stop: WriteOnly<u32, TASK::Register>),
422 (0x18 => _reserved2),
423 (0x1C => tasks_suspend: WriteOnly<u32, TASK::Register>),
425 (0x20 => tasks_resume: WriteOnly<u32, TASK::Register>),
427 (0x24 => _reserved3),
428 (0x30 => tasks_preparerx: WriteOnly<u32, TASK::Register>),
429 (0x34 => tasks_preparetx: WriteOnly<u32, TASK::Register>),
430 (0x38 => _reserved4),
431 (0x104 => events_stopped: ReadWrite<u32, EVENT::Register>),
433 (0x108 => _reserved5),
434 (0x124 => events_error: ReadWrite<u32, EVENT::Register>),
436 (0x128 => _reserved6),
437 (0x148 => events_suspended: ReadWrite<u32, EVENT::Register>),
440 (0x14C => events_rxstarted: ReadWrite<u32, EVENT::Register>),
442 (0x150 => events_txstarted: ReadWrite<u32, EVENT::Register>),
444 (0x154 => _reserved7),
445 (0x15C => events_lastrx: ReadWrite<u32, EVENT::Register>),
447 (0x160 => events_lasttx: ReadWrite<u32, EVENT::Register>),
449 (0x164 => events_write: ReadWrite<u32, EVENT::Register>),
450 (0x168 => events_read: ReadWrite<u32, EVENT::Register>),
451 (0x16C => _reserved8),
452 (0x200 => shorts: ReadWrite<u32, SHORTS::Register>),
454 (0x204 => _reserved9),
455 (0x300 => inten: ReadWrite<u32, INTE::Register>),
457 (0x304 => intenset: ReadWrite<u32, INTE::Register>),
459 (0x308 => intenclr: ReadWrite<u32, INTE::Register>),
461 (0x30C => _reserved10),
462 (0x4C4 => errorsrc_master: ReadWrite<u32, ERRORSRC::Register>),
464 (0x4C8 => _reserved11),
465 (0x4D0 => errorsrc_slave: ReadWrite<u32, ERRORSRC::Register>),
466 (0x4D4 => match_reg: ReadWrite<u32>),
467 (0x4D8 => _reserved12),
468 (0x500 => enable: ReadWrite<u32, ENABLE::Register>),
470 (0x504 => _reserved13),
471 (0x508 => psel_scl: VolatileCell<Pinmux>),
473 (0x50C => psel_sda: VolatileCell<Pinmux>),
475 (0x510 => _reserved_14),
476 (0x524 => frequency: ReadWrite<u32>),
478 (0x528 => _reserved15),
479 (0x534 => rxd_ptr: ReadWrite<u32>),
481 (0x538 => rxd_maxcnt: ReadWrite<u32, MAXCNT::Register>),
483 (0x53C => rxd_amount: ReadWrite<u32, AMOUNT::Register>),
485 (0x540 => rxd_list: ReadWrite<u32>),
487 (0x544 => txd_ptr: ReadWrite<u32>),
489 (0x548 => txd_maxcnt: ReadWrite<u32, MAXCNT::Register>),
491 (0x54C => txd_amount: ReadWrite<u32, AMOUNT::Register>),
493 (0x550 => txd_list: ReadWrite<u32>),
495 (0x554 => _reserved_16),
496 (0x588 => address_0: ReadWrite<u32, ADDRESS::Register>),
498 (0x58C => address_1: ReadWrite<u32, ADDRESS::Register>),
499 (0x590 => _reserved_17),
500 (0x594 => config: ReadWrite<u32, CONFIG::Register>),
501 (0x598 => _reserved_18),
502 (0x5C0 => orc: ReadWrite<u32>),
503 (0x5C4 => @END),
504 }
505}
506
507register_bitfields![u32,
508 SHORTS [
509 LASTTX_STARTRX OFFSET(7) NUMBITS(1) [
511 DisableShortcut = 0,
513 EnableShortcut = 1
515 ],
516 LASTTX_SUSPEND OFFSET(8) NUMBITS(1) [
518 DisableShortcut = 0,
520 EnableShortcut = 1
522 ],
523 LASTTX_STOP OFFSET(9) NUMBITS(1) [
525 DisableShortcut = 0,
527 EnableShortcut = 1
529 ],
530 LASTRX_STARTTX OFFSET(10) NUMBITS(1) [
532 DisableShortcut = 0,
534 EnableShortcut = 1
536 ],
537 LASTRX_STOP OFFSET(12) NUMBITS(1) [
539 DisableShortcut = 0,
541 EnableShortcut = 1
543 ]
544 ],
545 INTE [
546 STOPPED OFFSET(1) NUMBITS(1) [
548 Disable = 0,
550 Enable = 1
552 ],
553 ERROR OFFSET(9) NUMBITS(1) [
555 Disable = 0,
557 Enable = 1
559 ],
560 RXSTARTED OFFSET(19) NUMBITS(1) [
562 Disable = 0,
564 Enable = 1
566 ],
567 TXSTARTED OFFSET(20) NUMBITS(1) [
569 Disable = 0,
571 Enable = 1
573 ],
574 LASTRX OFFSET(23) NUMBITS(1) [
576 Disable = 0,
578 Enable = 1
580 ],
581 LASTTX OFFSET(24) NUMBITS(1) [
583 Disable = 0,
585 Enable = 1
587 ],
588 WRITE OFFSET(25) NUMBITS(1) [
589 Disable = 0,
590 Enable = 1
591 ],
592 READ OFFSET(26) NUMBITS(1) [
593 Disable = 0,
594 Enable = 1
595 ],
596 ],
597 ERRORSRC [
598 ANACK OFFSET(1) NUMBITS(1) [
600 ErrorDidNotOccur = 0,
602 ErrorOccurred = 1
604 ],
605 DNACK OFFSET(2) NUMBITS(1) [
607 ErrorDidNotOccur = 0,
609 ErrorOccurred = 1
611 ]
612 ],
613 EVENT [
614 EVENT 0
615 ],
616 TASK [
617 TASK 0
618 ],
619 ENABLE [
620 ENABLE OFFSET(0) NUMBITS(4) [
622 Disable = 0,
623 EnableMaster = 6,
624 EnableSlave = 9,
625 ]
626 ],
627 MAXCNT [
628 MAXCNT OFFSET(0) NUMBITS(16)
630 ],
631 AMOUNT [
632 AMOUNT OFFSET(0) NUMBITS(16),
633 ],
634 ADDRESS [
635 ADDRESS OFFSET(0) NUMBITS(7)
637 ],
638 CONFIG [
639 ADDRESS0 OFFSET(0) NUMBITS(1) [
641 Disable = 0,
642 Enable = 1,
643 ],
644 ADDRESS1 OFFSET(1) NUMBITS(1) [
645 Disable = 0,
646 Enable = 1,
647 ]
648 ],
649];