summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-09-29 01:20:46 -0400
committerDeterminant <ted.sybil@gmail.com>2017-09-29 01:20:46 -0400
commitb27ebb9f07d7ee0b60abe84738db712c8fbcb3f1 (patch)
tree873029656d269b492b21b370ca99bd60e93c5106
parent54449bb4bd610e3a9673722a098abf73159667db (diff)
support arbitrary write for EEPROM
-rw-r--r--src/at24c.rs28
-rw-r--r--src/i2c.rs48
-rw-r--r--src/main.rs16
3 files changed, 72 insertions, 20 deletions
diff --git a/src/at24c.rs b/src/at24c.rs
index 534f736..569f04a 100644
--- a/src/at24c.rs
+++ b/src/at24c.rs
@@ -14,7 +14,9 @@ impl<'a, 'b> AT24C<'a, 'b> {
let &AT24C(ref i2c) = self;
i2c.conf_ack(true); /* enable ack */
i2c.start(true, true); /* start condition (for writing addr) */
- i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true);
+ while !i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true) {
+ i2c.start(true, true);
+ }
i2c.send(((start >> 8) & 0x0f) as u8, true); /* first word addr */
i2c.send((start & 0xff) as u8, true); /* second word addr */
i2c.start(true, true); /* restart to read */
@@ -31,7 +33,9 @@ impl<'a, 'b> AT24C<'a, 'b> {
let &AT24C(ref i2c) = self;
i2c.conf_ack(true); /* enable ack */
i2c.start(true, true); /* start condition (for writing addr) */
- i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true);
+ while !i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true) {
+ i2c.start(true, true);
+ }
i2c.send(((start >> 8) & 0x0f) as u8, true); /* first word addr */
i2c.send((start & 0xff) as u8, true); /* second word addr */
for i in 0..size {
@@ -39,4 +43,24 @@ impl<'a, 'b> AT24C<'a, 'b> {
}
i2c.stop(true);
}
+
+ pub fn write(&self, start: u16, size: usize, buf: &[u8]) {
+ let end = start + size as u16 - 1;
+ let pg_s_off = start & 0x1f;
+ let pg_e_off = end & 0x1f;
+ let pg_s = start >> 5;
+ let pg_e = end >> 5;
+ if pg_s == pg_e {
+ self.page_write(start, size, buf);
+ } else {
+ let mut buf = buf;
+ self.page_write(start, (0x20 - pg_s_off) as usize, buf);
+ buf = &buf[0x20 - pg_s_off as usize..];
+ for i in (pg_s + 1)..pg_e {
+ self.page_write(i << 5, 0x20, buf);
+ buf = &buf[0x20..];
+ }
+ self.page_write(pg_e << 5, (pg_e_off + 1) as usize, buf);
+ }
+ }
}
diff --git a/src/i2c.rs b/src/i2c.rs
index 89e2072..1f8a57f 100644
--- a/src/i2c.rs
+++ b/src/i2c.rs
@@ -30,6 +30,7 @@ pub enum DutyType {
}
impl<'a, 'b> I2C<'a, 'b> {
+ #[inline(always)]
pub fn new(i2c: &'a stm32f103xx::i2c1::RegisterBlock,
rcc: &'b stm32f103xx::rcc::RegisterBlock) -> I2C<'a, 'b> {
I2C{i2c, rcc}
@@ -69,20 +70,28 @@ impl<'a, 'b> I2C<'a, 'b> {
pub fn init(&self,
addr: u8,
scl_freq: u32,
- duty_type: DutyType) {
+ duty_type: DutyType,
+ fast_mode: bool) {
let i2c = &self.i2c;
unsafe {
let pclk1 = self.get_pclk1();
let freq_range: u16 = (pclk1 / 1_000_000) as u16;
self.pe(false);
/* TRISE configuration (in Fm mode, max rise interval is 300) */
- i2c.trise.write(|w| w.bits(((freq_range * 300) / 1000 + 1) as u32));
+ i2c.trise.write(|w| w.bits(if fast_mode {(freq_range * 300) / 1000 + 1}
+ else {freq_range + 1} as u32));
/* CCR configuration */
- i2c.ccr.write(|w| match duty_type {
- DutyType::DUTY0 => w.ccr().bits(max(pclk1 / (scl_freq * (2 + 1)), 0x1) as u16),
- DutyType::DUTY1 => w.ccr().bits(max(pclk1 / (scl_freq * (16 + 9)), 0x1) as u16)
- .duty().set_bit(),
- }.f_s().set_bit());
+ i2c.ccr.write(|w|
+ if fast_mode {
+ match duty_type {
+ DutyType::DUTY0 => w.ccr().bits(max(pclk1 / (scl_freq * (2 + 1)), 0x1) as u16),
+ DutyType::DUTY1 => w.ccr().bits(max(pclk1 / (scl_freq * (16 + 9)), 0x1) as u16)
+ .duty().set_bit(),
+ }.f_s().set_bit()
+ } else {
+ w.ccr().bits(max(pclk1 / (scl_freq * (1 + 1)), 0x4) as u16)
+ .f_s().clear_bit()
+ });
self.pe(true); /* PE = 1, enable I2C */
/* CR1 configuration */
i2c.cr1.modify(|r, w| w.bits(r.bits())
@@ -107,6 +116,10 @@ impl<'a, 'b> I2C<'a, 'b> {
}
}
+ pub fn is_ack_fail(&self) -> bool {
+ self.i2c.sr1.read().af().bit_is_set()
+ }
+
pub fn start(&self, enable: bool, synced: bool) {
let i2c = &self.i2c;
unsafe {
@@ -116,7 +129,10 @@ impl<'a, 'b> I2C<'a, 'b> {
}
}
if synced {
- while !self.check_event(EVENT_MASTER_STARTED) {}
+ match enable {
+ true => while !self.check_event(EVENT_MASTER_STARTED) {},
+ false => while self.check_event(EVENT_MASTER_STARTED) {}
+ }
}
}
@@ -140,22 +156,32 @@ impl<'a, 'b> I2C<'a, 'b> {
}
}
- pub fn send_addr(&self, addr: u8, d: TransDir, synced: bool) {
+ pub fn send_addr(&self, addr: u8, d: TransDir, synced: bool) -> bool {
let addr = (addr << 1) | match d {
TransDir::TRANSMITTER => 0,
TransDir::RECEIVER => 1
};
unsafe {
+ self.i2c.sr1.write(|w| w.af().clear_bit());
self.i2c.dr.write(|w| w.dr().bits(addr));
}
if synced {
match d {
TransDir::TRANSMITTER =>
- while !self.check_event(EVENT_MASTER_TRANSMITTER_MODE_SELECTED) {},
+ while !self.check_event(EVENT_MASTER_TRANSMITTER_MODE_SELECTED) {
+ if self.is_ack_fail() {
+ return false
+ }
+ },
TransDir::RECEIVER =>
- while !self.check_event(EVENT_MASTER_RECEIVER_MODE_SELECTED) {}
+ while !self.check_event(EVENT_MASTER_RECEIVER_MODE_SELECTED) {
+ if self.is_ack_fail() {
+ return false
+ }
+ }
}
}
+ true
}
pub fn send(&self, data: u8, synced: bool) {
diff --git a/src/main.rs b/src/main.rs
index 2b3c97c..d5fdef9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -51,6 +51,7 @@ fn digits_countup() {
fn update_clock() {
unsafe {
+ if RTC.is_none() {return}
if !TIME.tick() {
let ds3231::Date{second: sec,
minute: min,
@@ -164,14 +165,14 @@ fn main() {
unsafe {
I2C = Some(i2c::I2C::new(i2c, rcc));
let i2c = I2C.as_mut().unwrap();
- RTC = Some(ds3231::DS3231::new(i2c));
+ let rtc = ds3231::DS3231::new(i2c);
ROM = Some(at24c::AT24C::new(i2c));
SR = Some(ShiftRegister::new(gpioa, 24));
- i2c.init(0x01, 400_000, i2c::DutyType::DUTY1);
+ i2c.init(0x01, 400_000, i2c::DutyType::DUTY1, true);
+ //i2c.init(0x01, 100_000, i2c::DutyType::DUTY1, false);
SR.as_mut().unwrap().output_bits(0);
- let rtc = RTC.as_mut().unwrap();
/* initialize the ds3231 */
/*
rtc.write_fulldate(&ds3231::Date{second: 30,
@@ -186,11 +187,12 @@ fn main() {
*/
/*
let rom = ROM.as_mut().unwrap();
- let mut buf: [u8; 16] = [0; 16];
- rom.read(0, 16, &mut buf);
- let mut buf2: [u8; 4] = [0, 1, 2, 3];
- rom.page_write(0, 4, &buf2);
+ let mut buf: [u8; 64] = [23; 64];
+ rom.write(23, 64, &buf);
+ let mut buf2: [u8; 80] = [0; 80];
+ rom.read(20, 80, &mut buf2);
*/
+ RTC = Some(rtc);
}
update_clock();