|
1 | 1 | use core::ops::Deref;
|
| 2 | +use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; |
2 | 3 |
|
3 | 4 | use crate::stm32::i2c1;
|
4 | 5 |
|
@@ -42,8 +43,6 @@ use crate::stm32::I2C3;
|
42 | 43 | ))]
|
43 | 44 | use crate::stm32::{I2C1, I2C2, RCC};
|
44 | 45 |
|
45 |
| -use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; |
46 |
| - |
47 | 46 | #[cfg(any(
|
48 | 47 | feature = "stm32f401",
|
49 | 48 | feature = "stm32f405",
|
@@ -197,6 +196,13 @@ pub struct I2c<I2C, PINS> {
|
197 | 196 | pins: PINS,
|
198 | 197 | }
|
199 | 198 |
|
| 199 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 200 | +/// I2C FastMode+ abstraction |
| 201 | +pub struct FMPI2c<I2C, PINS> { |
| 202 | + i2c: I2C, |
| 203 | + pins: PINS, |
| 204 | +} |
| 205 | + |
200 | 206 | pub trait Pins<I2c> {}
|
201 | 207 | pub trait PinScl<I2c> {}
|
202 | 208 | pub trait PinSda<I2c> {}
|
@@ -492,6 +498,54 @@ impl PinScl<I2C3> for PH7<AlternateOD<AF4>> {}
|
492 | 498 | ))]
|
493 | 499 | impl PinSda<I2C3> for PH8<AlternateOD<AF4>> {}
|
494 | 500 |
|
| 501 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 502 | +use crate::{ |
| 503 | + gpio::{ |
| 504 | + gpiob::{PB13, PB14, PB15}, |
| 505 | + gpioc::{PC6, PC7}, |
| 506 | + gpiod::{PD12, PD14, PD15}, |
| 507 | + gpiof::{PF14, PF15}, |
| 508 | + }, |
| 509 | + pac::fmpi2c, |
| 510 | + pac::FMPI2C, |
| 511 | +}; |
| 512 | + |
| 513 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 514 | +impl PinScl<FMPI2C> for PC6<AlternateOD<AF4>> {} |
| 515 | + |
| 516 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 517 | +impl PinSda<FMPI2C> for PC7<AlternateOD<AF4>> {} |
| 518 | + |
| 519 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 520 | +impl PinSda<FMPI2C> for PB3<AlternateOD<AF4>> {} |
| 521 | + |
| 522 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 523 | +impl PinScl<FMPI2C> for PB10<AlternateOD<AF9>> {} |
| 524 | + |
| 525 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 526 | +impl PinSda<FMPI2C> for PB14<AlternateOD<AF4>> {} |
| 527 | + |
| 528 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 529 | +impl PinScl<FMPI2C> for PB15<AlternateOD<AF4>> {} |
| 530 | + |
| 531 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 532 | +impl PinScl<FMPI2C> for PD12<AlternateOD<AF4>> {} |
| 533 | + |
| 534 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 535 | +impl PinScl<FMPI2C> for PB13<AlternateOD<AF4>> {} |
| 536 | + |
| 537 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 538 | +impl PinScl<FMPI2C> for PD14<AlternateOD<AF4>> {} |
| 539 | + |
| 540 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 541 | +impl PinScl<FMPI2C> for PD15<AlternateOD<AF4>> {} |
| 542 | + |
| 543 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 544 | +impl PinScl<FMPI2C> for PF14<AlternateOD<AF4>> {} |
| 545 | + |
| 546 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 547 | +impl PinScl<FMPI2C> for PF15<AlternateOD<AF4>> {} |
| 548 | + |
495 | 549 | #[derive(Debug)]
|
496 | 550 | pub enum Error {
|
497 | 551 | OVERRUN,
|
@@ -617,6 +671,30 @@ impl<PINS> I2c<I2C3, PINS> {
|
617 | 671 | }
|
618 | 672 | }
|
619 | 673 |
|
| 674 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 675 | +impl<PINS> FMPI2c<FMPI2C, PINS> { |
| 676 | + pub fn fmpi2c(i2c: FMPI2C, pins: PINS, speed: KiloHertz) -> Self |
| 677 | + where |
| 678 | + PINS: Pins<FMPI2C>, |
| 679 | + { |
| 680 | + // NOTE(unsafe) This executes only during initialisation |
| 681 | + let rcc = unsafe { &(*RCC::ptr()) }; |
| 682 | + |
| 683 | + // Enable clock for FMPI2C |
| 684 | + rcc.apb1enr.modify(|_, w| w.i2c4en().set_bit()); |
| 685 | + |
| 686 | + // Reset FMPI2C |
| 687 | + rcc.apb1rstr.modify(|_, w| w.i2c4rst().set_bit()); |
| 688 | + rcc.apb1rstr.modify(|_, w| w.i2c4rst().clear_bit()); |
| 689 | + |
| 690 | + rcc.dckcfgr2.modify(|_, w| w.i2cfmp1sel().hsi()); |
| 691 | + |
| 692 | + let i2c = FMPI2c { i2c, pins }; |
| 693 | + i2c.i2c_init(speed); |
| 694 | + i2c |
| 695 | + } |
| 696 | +} |
| 697 | + |
620 | 698 | impl<I2C, PINS> I2c<I2C, PINS>
|
621 | 699 | where
|
622 | 700 | I2C: Deref<Target = i2c1::RegisterBlock>,
|
@@ -852,3 +930,248 @@ where
|
852 | 930 | }
|
853 | 931 | }
|
854 | 932 | }
|
| 933 | + |
| 934 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 935 | +impl<I2C, PINS> FMPI2c<I2C, PINS> |
| 936 | +where |
| 937 | + I2C: Deref<Target = fmpi2c::RegisterBlock>, |
| 938 | +{ |
| 939 | + fn i2c_init(&self, speed: KiloHertz) { |
| 940 | + use core::cmp; |
| 941 | + |
| 942 | + // Make sure the I2C unit is disabled so we can configure it |
| 943 | + self.i2c.cr1.modify(|_, w| w.pe().clear_bit()); |
| 944 | + |
| 945 | + // Calculate settings for I2C speed modes |
| 946 | + let presc; |
| 947 | + let scldel; |
| 948 | + let sdadel; |
| 949 | + let sclh; |
| 950 | + let scll; |
| 951 | + |
| 952 | + // We're using the HSI clock to keep things simple so this is going to be always 16 MHz |
| 953 | + const FREQ: u32 = 16_000_000; |
| 954 | + |
| 955 | + // Normal I2C speeds use a different scaling than fast mode below and fast mode+ even more |
| 956 | + // below |
| 957 | + if speed <= 100.khz() { |
| 958 | + presc = 3; |
| 959 | + scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8; |
| 960 | + sclh = scll - 4; |
| 961 | + sdadel = 2; |
| 962 | + scldel = 4; |
| 963 | + } else if speed <= 400.khz() { |
| 964 | + presc = 1; |
| 965 | + scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8; |
| 966 | + sclh = scll - 6; |
| 967 | + sdadel = 2; |
| 968 | + scldel = 3; |
| 969 | + } else { |
| 970 | + presc = 0; |
| 971 | + scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 4, 255) as u8; |
| 972 | + sclh = scll - 2; |
| 973 | + sdadel = 0; |
| 974 | + scldel = 2; |
| 975 | + } |
| 976 | + |
| 977 | + // Enable I2C signal generator, and configure I2C for configured speed |
| 978 | + self.i2c.timingr.write(|w| unsafe { |
| 979 | + w.presc() |
| 980 | + .bits(presc) |
| 981 | + .scldel() |
| 982 | + .bits(scldel) |
| 983 | + .sdadel() |
| 984 | + .bits(sdadel) |
| 985 | + .sclh() |
| 986 | + .bits(sclh) |
| 987 | + .scll() |
| 988 | + .bits(scll) |
| 989 | + }); |
| 990 | + |
| 991 | + // Enable the I2C processing |
| 992 | + self.i2c.cr1.modify(|_, w| w.pe().set_bit()); |
| 993 | + } |
| 994 | + |
| 995 | + pub fn release(self) -> (I2C, PINS) { |
| 996 | + (self.i2c, self.pins) |
| 997 | + } |
| 998 | + |
| 999 | + fn check_and_clear_error_flags(&self, isr: &fmpi2c::isr::R) -> Result<(), Error> { |
| 1000 | + // If we received a NACK, then this is an error |
| 1001 | + if isr.nackf().bit_is_set() { |
| 1002 | + self.i2c |
| 1003 | + .icr |
| 1004 | + .write(|w| w.stopcf().set_bit().nackcf().set_bit()); |
| 1005 | + return Err(Error::NACK); |
| 1006 | + } |
| 1007 | + |
| 1008 | + Ok(()) |
| 1009 | + } |
| 1010 | + |
| 1011 | + fn send_byte(&self, byte: u8) -> Result<(), Error> { |
| 1012 | + // Wait until we're ready for sending |
| 1013 | + while { |
| 1014 | + let isr = self.i2c.isr.read(); |
| 1015 | + self.check_and_clear_error_flags(&isr)?; |
| 1016 | + isr.txis().bit_is_clear() |
| 1017 | + } {} |
| 1018 | + |
| 1019 | + // Push out a byte of data |
| 1020 | + self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) }); |
| 1021 | + |
| 1022 | + self.check_and_clear_error_flags(&self.i2c.isr.read())?; |
| 1023 | + Ok(()) |
| 1024 | + } |
| 1025 | + |
| 1026 | + fn recv_byte(&self) -> Result<u8, Error> { |
| 1027 | + while { |
| 1028 | + let isr = self.i2c.isr.read(); |
| 1029 | + self.check_and_clear_error_flags(&isr)?; |
| 1030 | + isr.rxne().bit_is_clear() |
| 1031 | + } {} |
| 1032 | + |
| 1033 | + let value = self.i2c.rxdr.read().bits() as u8; |
| 1034 | + Ok(value) |
| 1035 | + } |
| 1036 | +} |
| 1037 | + |
| 1038 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 1039 | +impl<I2C, PINS> WriteRead for FMPI2c<I2C, PINS> |
| 1040 | +where |
| 1041 | + I2C: Deref<Target = fmpi2c::RegisterBlock>, |
| 1042 | +{ |
| 1043 | + type Error = Error; |
| 1044 | + |
| 1045 | + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { |
| 1046 | + // Set up current slave address for writing and disable autoending |
| 1047 | + self.i2c.cr2.modify(|_, w| unsafe { |
| 1048 | + w.sadd1_7() |
| 1049 | + .bits(addr) |
| 1050 | + .nbytes() |
| 1051 | + .bits(bytes.len() as u8) |
| 1052 | + .rd_wrn() |
| 1053 | + .clear_bit() |
| 1054 | + .autoend() |
| 1055 | + .clear_bit() |
| 1056 | + }); |
| 1057 | + |
| 1058 | + // Send a START condition |
| 1059 | + self.i2c.cr2.modify(|_, w| w.start().set_bit()); |
| 1060 | + |
| 1061 | + // Wait until the transmit buffer is empty and there hasn't been any error condition |
| 1062 | + while { |
| 1063 | + let isr = self.i2c.isr.read(); |
| 1064 | + self.check_and_clear_error_flags(&isr)?; |
| 1065 | + isr.txis().bit_is_clear() && isr.tc().bit_is_clear() |
| 1066 | + } {} |
| 1067 | + |
| 1068 | + // Send out all individual bytes |
| 1069 | + for c in bytes { |
| 1070 | + self.send_byte(*c)?; |
| 1071 | + } |
| 1072 | + |
| 1073 | + // Wait until data was sent |
| 1074 | + while { |
| 1075 | + let isr = self.i2c.isr.read(); |
| 1076 | + self.check_and_clear_error_flags(&isr)?; |
| 1077 | + isr.tc().bit_is_clear() |
| 1078 | + } {} |
| 1079 | + |
| 1080 | + // Set up current address for reading |
| 1081 | + self.i2c.cr2.modify(|_, w| unsafe { |
| 1082 | + w.sadd1_7() |
| 1083 | + .bits(addr) |
| 1084 | + .nbytes() |
| 1085 | + .bits(buffer.len() as u8) |
| 1086 | + .rd_wrn() |
| 1087 | + .set_bit() |
| 1088 | + }); |
| 1089 | + |
| 1090 | + // Send another START condition |
| 1091 | + self.i2c.cr2.modify(|_, w| w.start().set_bit()); |
| 1092 | + |
| 1093 | + // Send the autoend after setting the start to get a restart |
| 1094 | + self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); |
| 1095 | + |
| 1096 | + // Now read in all bytes |
| 1097 | + for c in buffer.iter_mut() { |
| 1098 | + *c = self.recv_byte()?; |
| 1099 | + } |
| 1100 | + |
| 1101 | + // Check and clear flags if they somehow ended up set |
| 1102 | + self.check_and_clear_error_flags(&self.i2c.isr.read())?; |
| 1103 | + |
| 1104 | + Ok(()) |
| 1105 | + } |
| 1106 | +} |
| 1107 | + |
| 1108 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 1109 | +impl<I2C, PINS> Read for FMPI2c<I2C, PINS> |
| 1110 | +where |
| 1111 | + I2C: Deref<Target = fmpi2c::RegisterBlock>, |
| 1112 | +{ |
| 1113 | + type Error = Error; |
| 1114 | + |
| 1115 | + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { |
| 1116 | + // Set up current address for reading |
| 1117 | + self.i2c.cr2.modify(|_, w| unsafe { |
| 1118 | + w.sadd1_7() |
| 1119 | + .bits(addr) |
| 1120 | + .nbytes() |
| 1121 | + .bits(buffer.len() as u8) |
| 1122 | + .rd_wrn() |
| 1123 | + .set_bit() |
| 1124 | + }); |
| 1125 | + |
| 1126 | + // Send a START condition |
| 1127 | + self.i2c.cr2.modify(|_, w| w.start().set_bit()); |
| 1128 | + |
| 1129 | + // Send the autoend after setting the start to get a restart |
| 1130 | + self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); |
| 1131 | + |
| 1132 | + // Now read in all bytes |
| 1133 | + for c in buffer.iter_mut() { |
| 1134 | + *c = self.recv_byte()?; |
| 1135 | + } |
| 1136 | + |
| 1137 | + // Check and clear flags if they somehow ended up set |
| 1138 | + self.check_and_clear_error_flags(&self.i2c.isr.read())?; |
| 1139 | + |
| 1140 | + Ok(()) |
| 1141 | + } |
| 1142 | +} |
| 1143 | + |
| 1144 | +#[cfg(any(feature = "stm32f413", feature = "stm32f423",))] |
| 1145 | +impl<I2C, PINS> Write for FMPI2c<I2C, PINS> |
| 1146 | +where |
| 1147 | + I2C: Deref<Target = fmpi2c::RegisterBlock>, |
| 1148 | +{ |
| 1149 | + type Error = Error; |
| 1150 | + |
| 1151 | + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { |
| 1152 | + // Set up current slave address for writing and enable autoending |
| 1153 | + self.i2c.cr2.modify(|_, w| unsafe { |
| 1154 | + w.sadd1_7() |
| 1155 | + .bits(addr) |
| 1156 | + .nbytes() |
| 1157 | + .bits(bytes.len() as u8) |
| 1158 | + .rd_wrn() |
| 1159 | + .clear_bit() |
| 1160 | + .autoend() |
| 1161 | + .set_bit() |
| 1162 | + }); |
| 1163 | + |
| 1164 | + // Send a START condition |
| 1165 | + self.i2c.cr2.modify(|_, w| w.start().set_bit()); |
| 1166 | + |
| 1167 | + // Send out all individual bytes |
| 1168 | + for c in bytes { |
| 1169 | + self.send_byte(*c)?; |
| 1170 | + } |
| 1171 | + |
| 1172 | + // Check and clear flags if they somehow ended up set |
| 1173 | + self.check_and_clear_error_flags(&self.i2c.isr.read())?; |
| 1174 | + |
| 1175 | + Ok(()) |
| 1176 | + } |
| 1177 | +} |
0 commit comments