Skip to content

Commit c2c183a

Browse files
committed
Implement hardware interface for ast1060.
1 parent 4a0027b commit c2c183a

File tree

4 files changed

+206
-44
lines changed

4 files changed

+206
-44
lines changed

src/common.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use core::ops::{Index, IndexMut};
2+
use crate::uart::UartController;
3+
use embedded_io::Write;
14

25
pub struct DummyDelay;
36

@@ -40,8 +43,6 @@ impl<const N: usize> DmaBuffer<N> {
4043
}
4144
}
4245

43-
use core::ops::{Index, IndexMut};
44-
4546
impl<const N: usize> Index<usize> for DmaBuffer<N> {
4647
type Output = u8;
4748
fn index(&self, idx: usize) -> &Self::Output {
@@ -53,4 +54,30 @@ impl<const N: usize> IndexMut<usize> for DmaBuffer<N> {
5354
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
5455
&mut self.buf[idx]
5556
}
57+
}
58+
59+
pub trait Logger {
60+
fn debug(&mut self, msg: &str);
61+
fn error(&mut self, msg: &str);
62+
}
63+
64+
// No-op implementation for production builds
65+
pub struct NoOpLogger;
66+
impl Logger for NoOpLogger {
67+
fn debug(&mut self, _msg: &str) {}
68+
fn error(&mut self, _msg: &str) {}
69+
}
70+
71+
// UART logger adapter (separate concern)
72+
pub struct UartLogger<'a> {
73+
uart: &'a mut UartController<'a>,
74+
}
75+
76+
impl<'a> Logger for UartLogger<'a> {
77+
fn debug(&mut self, msg: &str) {
78+
writeln!(self.uart, "{}", msg).ok();
79+
}
80+
fn error(&mut self, msg: &str) {
81+
writeln!(self.uart, "ERROR: {}", msg).ok();
82+
}
5683
}

src/i2c/ast1060_i2c.rs

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::common::{DmaBuffer, DummyDelay};
22
use crate::i2c::common::{I2cConfig, I2cSEvent, I2cXferMode};
3+
use crate::i2c::i2c::HardwareInterface;
34
use crate::uart::UartController;
45
use ast1060_pac::{I2cbuff, I2cglobal, Scu};
56
use core::cmp::min;
@@ -298,10 +299,12 @@ impl<I2C: Instance, I2CT: I2CTarget> Drop for I2cController<'_, I2C, I2CT> {
298299
// Disable i2c controller
299300
self.i2c.i2cc00().write(|w| unsafe {w.bits(0)});
300301
// Disable interrupt and clear interrupt status
301-
self.i2c.i2cm10().write(|w| unsafe {w.bits(0)});
302-
self.i2c.i2cm14().write(|w| unsafe {w.bits(0xffff_ffff)});
303-
self.i2c.i2cs20().write(|w| unsafe {w.bits(0)});
304-
self.i2c.i2cs24().write(|w| unsafe {w.bits(0xffff_ffff)});
302+
self.enable_interrupts(0);
303+
self.clear_interrupts(0xffff_ffff);
304+
#[cfg(feature = "i2c_target")]
305+
self.enable_slave_interrupts(0);
306+
#[cfg(feature = "i2c_target")]
307+
self.clear_slave_interrupts(0xffff_ffff);
305308
}
306309
}
307310
macro_rules! dbg {
@@ -312,6 +315,154 @@ macro_rules! dbg {
312315
}
313316
};
314317
}
318+
319+
impl<'a, I2C: Instance, I2CT: I2CTarget> HardwareInterface for I2cController<'a, I2C, I2CT> {
320+
type Error = Error;
321+
322+
fn init(&mut self) {
323+
self.init();
324+
}
325+
fn configure_timing(&mut self, config: &mut I2cConfig) -> Result<(), Self::Error> {
326+
let scu = unsafe { &*Scu::ptr() };
327+
config.timing_config.clk_src =
328+
HPLL_FREQ / ((scu.scu310().read().apbbus_pclkdivider_sel().bits() as u32 + 1) * 2);
329+
330+
let p = unsafe { &*I2cglobal::ptr() };
331+
let mut div: u32;
332+
let mut divider_ratio: u32;
333+
334+
if p.i2cg0c().read().clk_divider_mode_sel().bit_is_set() {
335+
let base_clk = config.timing_config.clk_src;
336+
let base_clk1 = (config.timing_config.clk_src * 10)
337+
/ ((p.i2cg10().read().base_clk1divisor_basedivider1().bits() as u32 + 2) * 10 / 2);
338+
let base_clk2 = (config.timing_config.clk_src * 10)
339+
/ ((p.i2cg10().read().base_clk2divisor_basedivider2().bits() as u32 + 2) * 10 / 2);
340+
let base_clk3 = (config.timing_config.clk_src * 10)
341+
/ ((p.i2cg10().read().base_clk3divisor_basedivider3().bits() as u32 + 2) * 10 / 2);
342+
let base_clk4 = (config.timing_config.clk_src * 10)
343+
/ ((p.i2cg10().read().base_clk4divisor_basedivider4().bits() as u32 + 2) * 10 / 2);
344+
345+
// rounding
346+
if config.timing_config.clk_src / (config.speed as u32) <= 32 {
347+
div = 0;
348+
divider_ratio = base_clk / config.speed as u32;
349+
if base_clk / divider_ratio > config.speed as u32 {
350+
divider_ratio += 1;
351+
}
352+
} else if base_clk1 / (config.speed as u32) <= 32 {
353+
div = 1;
354+
divider_ratio = base_clk1 / config.speed as u32;
355+
if base_clk1 / divider_ratio > config.speed as u32 {
356+
divider_ratio += 1;
357+
}
358+
} else if base_clk2 / (config.speed as u32) <= 32 {
359+
div = 2;
360+
divider_ratio = base_clk2 / config.speed as u32;
361+
if base_clk2 / divider_ratio > config.speed as u32 {
362+
divider_ratio += 1;
363+
}
364+
} else if base_clk3 / (config.speed as u32) <= 32 {
365+
div = 3;
366+
divider_ratio = base_clk3 / config.speed as u32;
367+
if base_clk3 / divider_ratio > config.speed as u32 {
368+
divider_ratio += 1;
369+
}
370+
} else {
371+
div = 4;
372+
divider_ratio = base_clk4 / config.speed as u32;
373+
let mut inc = 0;
374+
while divider_ratio + inc > 32 {
375+
inc |= divider_ratio & 1u32;
376+
divider_ratio >>= 1;
377+
div += 1;
378+
}
379+
divider_ratio += inc;
380+
if base_clk4 / divider_ratio > config.speed as u32 {
381+
divider_ratio += 1;
382+
}
383+
divider_ratio = min(divider_ratio, 32);
384+
div &= 0xf;
385+
}
386+
387+
let mut scl_low: u8;
388+
let mut scl_high: u8;
389+
if (config.timing_config.manual_scl_low & config.timing_config.manual_scl_high) != 0 {
390+
scl_low = config.timing_config.manual_scl_low;
391+
scl_high = config.timing_config.manual_scl_high;
392+
} else if (config.timing_config.manual_scl_low | config.timing_config.manual_scl_high) != 0 {
393+
if config.timing_config.manual_scl_low != 0 {
394+
scl_low = config.timing_config.manual_scl_low;
395+
scl_high = divider_ratio as u8 - scl_low - 2;
396+
} else {
397+
scl_high = config.timing_config.manual_scl_high;
398+
scl_low = divider_ratio as u8 - scl_high - 2;
399+
}
400+
} else {
401+
scl_low = (divider_ratio * 9 / 16 - 1) as u8;
402+
scl_high = divider_ratio as u8 - scl_low - 2;
403+
}
404+
scl_low = min(scl_low, 0xf);
405+
scl_high = min(scl_high, 0xf);
406+
407+
/*Divisor : Base Clock : tCKHighMin : tCK High : tCK Low*/
408+
self.i2c
409+
.i2cc04()
410+
.write(|w| unsafe { w.base_clk_divisor_tbase_clk().bits(div as u8) });
411+
self.i2c.i2cc04().write(|w| unsafe {
412+
w.cycles_of_master_sclclklow_pulse_width_tcklow()
413+
.bits(scl_low)
414+
});
415+
self.i2c.i2cc04().write(|w| unsafe {
416+
w.cycles_of_master_sclclkhigh_pulse_width_tckhigh()
417+
.bits(scl_high)
418+
});
419+
self.i2c.i2cc04().write(|w| unsafe {
420+
w.cycles_of_master_sclclkhigh_minimum_pulse_width_tckhigh_min()
421+
.bits(scl_high - 1)
422+
});
423+
424+
if config.smbus_timeout {
425+
self.i2c.i2cc04().write(|w| unsafe {
426+
w.timeout_base_clk_divisor_tout_base_clk()
427+
.bits(2)
428+
.timeout_timer()
429+
.bits(8)
430+
});
431+
}
432+
if config.timing_config.manual_sda_hold < 4 {
433+
self.i2c.i2cc04().write(|w| unsafe {
434+
w.hold_time_of_masterslave_data_thddat()
435+
.bits(config.timing_config.manual_sda_hold)
436+
});
437+
}
438+
}
439+
Ok(())
440+
}
441+
fn enable_interrupts(&mut self, mask: u32) {
442+
self.i2c.i2cm10().write(|w| unsafe { w.bits(mask) });
443+
}
444+
fn clear_interrupts(&mut self, mask: u32) {
445+
self.i2c.i2cm14().write(|w| unsafe { w.bits(mask) });
446+
}
447+
#[cfg(feature = "i2c_target")]
448+
fn enable_slave_interrupts(&mut self, mask: u32) {
449+
self.i2c.i2cs20().write(|w| unsafe { w.bits(mask) });
450+
}
451+
#[cfg(feature = "i2c_target")]
452+
fn clear_slave_interrupts(&mut self, mask: u32) {
453+
self.i2c.i2cs24().write(|w| unsafe { w.bits(mask) });
454+
}
455+
fn handle_interrupt(&mut self) {
456+
//check slave mode first
457+
if self.i2c.i2cc00().read().enbl_slave_fn().bit() {
458+
if self.aspeed_i2c_slave_irq() != 0 {
459+
return;
460+
}
461+
}
462+
self.aspeed_i2c_master_irq();
463+
}
464+
}
465+
315466
impl<'a, I2C: Instance, I2CT: I2CTarget> I2cController<'a, I2C, I2CT> {
316467
pub fn new(i2c: I2C, config: I2cConfig, uart: Option<&'a mut UartController<'a>>) -> Self {
317468
let i2c = unsafe { &*I2C::ptr() };

src/i2c/i2c.rs

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,32 @@
1-
use crate::uart::UartController;
1+
use crate::common::{Logger, NoOpLogger};
22
use crate::i2c::common::I2cConfig;
33
use embedded_hal::i2c::{Operation, SevenBitAddress};
4-
use embedded_io::Write;
54

6-
trait HardwareInterface {
5+
6+
pub trait HardwareInterface {
77
type Error: embedded_hal::i2c::Error + core::fmt::Debug;
88

99
// Methods return hardware-specific errors
10-
fn reset(&mut self);
11-
fn configure_timing(&mut self, config: &I2cConfig) -> Result<(), Self::Error>;
10+
fn init(&mut self);
11+
fn configure_timing(&mut self, config: &mut I2cConfig) -> Result<(), Self::Error>;
1212
fn enable_interrupts(&mut self, mask: u32);
1313
fn clear_interrupts(&mut self, mask: u32);
14+
#[cfg(feature = "i2c_target")]
15+
fn enable_slave_interrupts(&mut self, mask: u32);
16+
#[cfg(feature = "i2c_target")]
17+
fn clear_slave_interrupts(&mut self, mask: u32);
1418
//fn start_transfer(&mut self, state: &TransferState, mode: TransferMode) -> Result<(), Self::Error>;
15-
//fn handle_interrupt(&mut self) -> InterruptStatus;
16-
fn is_bus_busy(&self) -> bool;
17-
fn recover_bus(&mut self) -> Result<(), Self::Error>;
19+
fn handle_interrupt(&mut self);
20+
//fn is_bus_busy(&self) -> bool;
21+
//fn recover_bus(&mut self) -> Result<(), Self::Error>;
1822

1923

2024

2125
}
2226

23-
trait Logger {
24-
fn debug(&mut self, msg: &str);
25-
fn error(&mut self, msg: &str);
26-
}
27-
28-
// No-op implementation for production builds
29-
struct NoOpLogger;
30-
impl Logger for NoOpLogger {
31-
fn debug(&mut self, _msg: &str) {}
32-
fn error(&mut self, _msg: &str) {}
33-
}
34-
35-
// UART logger adapter (separate concern)
36-
struct UartLogger<'a> {
37-
uart: &'a mut UartController<'a>,
38-
}
39-
40-
impl<'a> Logger for UartLogger<'a> {
41-
fn debug(&mut self, msg: &str) {
42-
writeln!(self.uart, "{}", msg).ok();
43-
}
44-
fn error(&mut self, msg: &str) {
45-
writeln!(self.uart, "ERROR: {}", msg).ok();
46-
}
47-
}
4827
pub struct I2cController<H: HardwareInterface, L: Logger = NoOpLogger> {
4928
hardware: H,
29+
config: I2cConfig,
5030
logger: L,
5131
}
5232

@@ -55,11 +35,13 @@ impl<H: HardwareInterface, L: Logger> embedded_hal::i2c::ErrorType for I2cContro
5535
}
5636
impl<H: HardwareInterface, L: Logger> embedded_hal::i2c::I2c for I2cController<H, L> {
5737
fn read(&mut self, addr: SevenBitAddress, buffer: &mut [u8]) -> Result<(), Self::Error> {
58-
self.hardware.read(addr, buffer)
38+
//self.hardware.read(addr, buffer)
39+
Ok(())
5940
}
6041

6142
fn write(&mut self, addr: SevenBitAddress, bytes: &[u8]) -> Result<(), Self::Error> {
62-
self.hardware.write(addr, bytes)
43+
//self.hardware.write(addr, bytes)
44+
Ok(())
6345
}
6446

6547
fn write_read(
@@ -68,14 +50,16 @@ impl<H: HardwareInterface, L: Logger> embedded_hal::i2c::I2c for I2cController<H
6850
bytes: &[u8],
6951
buffer: &mut [u8],
7052
) -> Result<(), Self::Error> {
71-
self.hardware.write_read(addr, bytes, buffer)
53+
//self.hardware.write_read(addr, bytes, buffer)
54+
Ok(())
7255
}
7356

7457
fn transaction(
7558
&mut self,
7659
addr: SevenBitAddress,
7760
operations: &mut [Operation<'_>],
7861
) -> Result<(), Self::Error> {
79-
self.hardware.transaction_slice(addr, operations)
62+
//self.hardware.transaction_slice(addr, operations)
63+
Ok(())
8064
}
8165
}

src/i2c/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
pub mod common;
22
pub mod ast1060_i2c;
3-
//pub mod i2c;
3+
pub mod i2c;

0 commit comments

Comments
 (0)