aboutsummaryrefslogtreecommitdiff
path: root/embassy-mspm0
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mspm0')
-rw-r--r--embassy-mspm0/src/i2c.rs120
1 files changed, 81 insertions, 39 deletions
diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs
index f99e02c59..d093a7e21 100644
--- a/embassy-mspm0/src/i2c.rs
+++ b/embassy-mspm0/src/i2c.rs
@@ -25,7 +25,7 @@ use crate::Peri;
25pub enum ClockSel { 25pub enum ClockSel {
26 /// Use the bus clock. 26 /// Use the bus clock.
27 /// 27 ///
28 /// By default the BusClk runs at 32 MHz. 28 /// Configurable clock.
29 BusClk, 29 BusClk,
30 30
31 /// Use the middle frequency clock. 31 /// Use the middle frequency clock.
@@ -127,8 +127,15 @@ impl BusSpeed {
127#[cfg_attr(feature = "defmt", derive(defmt::Format))] 127#[cfg_attr(feature = "defmt", derive(defmt::Format))]
128/// Config Error 128/// Config Error
129pub enum ConfigError { 129pub enum ConfigError {
130 /// Invalid clock rate.
131 ///
130 /// The clock rate could not be configured with the given conifguratoin. 132 /// The clock rate could not be configured with the given conifguratoin.
131 InvalidClockRate, 133 InvalidClockRate,
134
135 /// Clock source not enabled.
136 ///
137 /// The clock soure is not enabled is SYSCTL.
138 ClockSourceNotEnabled,
132} 139}
133 140
134#[non_exhaustive] 141#[non_exhaustive]
@@ -136,7 +143,7 @@ pub enum ConfigError {
136/// Config 143/// Config
137pub struct Config { 144pub struct Config {
138 /// I2C clock source. 145 /// I2C clock source.
139 pub clock_source: ClockSel, 146 clock_source: ClockSel,
140 147
141 /// I2C clock divider. 148 /// I2C clock divider.
142 pub clock_div: ClockDiv, 149 pub clock_div: ClockDiv,
@@ -160,7 +167,7 @@ pub struct Config {
160impl Default for Config { 167impl Default for Config {
161 fn default() -> Self { 168 fn default() -> Self {
162 Self { 169 Self {
163 clock_source: ClockSel::BusClk, 170 clock_source: ClockSel::MfClk,
164 clock_div: ClockDiv::DivBy1, 171 clock_div: ClockDiv::DivBy1,
165 invert_sda: false, 172 invert_sda: false,
166 invert_scl: false, 173 invert_scl: false,
@@ -178,7 +185,7 @@ impl Config {
178 pub fn scl_pf(&self) -> PfType { 185 pub fn scl_pf(&self) -> PfType {
179 PfType::input(self.scl_pull, self.invert_scl) 186 PfType::input(self.scl_pull, self.invert_scl)
180 } 187 }
181 fn timer_period(&self) -> u8 { 188 fn calculate_timer_period(&self) -> u8 {
182 // Sets the timer period to bring the clock frequency to the selected I2C speed 189 // Sets the timer period to bring the clock frequency to the selected I2C speed
183 // From the documentation: TPR = (I2C_CLK / (I2C_FREQ * (SCL_LP + SCL_HP))) - 1 where: 190 // From the documentation: TPR = (I2C_CLK / (I2C_FREQ * (SCL_LP + SCL_HP))) - 1 where:
184 // - I2C_FREQ is desired I2C frequency (= I2C_BASE_FREQ divided by I2C_DIV) 191 // - I2C_FREQ is desired I2C frequency (= I2C_BASE_FREQ divided by I2C_DIV)
@@ -186,13 +193,13 @@ impl Config {
186 // - SCL_LP is the SCL Low period (fixed at 6) 193 // - SCL_LP is the SCL Low period (fixed at 6)
187 // - SCL_HP is the SCL High period (fixed at 4) 194 // - SCL_HP is the SCL High period (fixed at 4)
188 // - I2C_CLK is functional clock frequency 195 // - I2C_CLK is functional clock frequency
189 return (((self.calculate_clock_rate() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1) 196 return (((self.calculate_clock_source() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1)
190 .try_into() 197 .try_into()
191 .unwrap(); 198 .unwrap();
192 } 199 }
193 200
194 #[cfg(any(mspm0c110x))] 201 #[cfg(any(mspm0c110x))]
195 pub fn calculate_clock_rate(&self) -> Hertz { 202 fn calculate_clock_source(&self) -> Hertz {
196 // Assume that BusClk has default value. 203 // Assume that BusClk has default value.
197 // TODO: calculate BusClk more precisely. 204 // TODO: calculate BusClk more precisely.
198 match self.clock_source { 205 match self.clock_source {
@@ -205,7 +212,7 @@ impl Config {
205 mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x, 212 mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x,
206 mspm0l134x, mspm0l222x 213 mspm0l134x, mspm0l222x
207 ))] 214 ))]
208 pub fn calculate_clock_rate(&self) -> Hertz { 215 fn calculate_clock_source(&self) -> Hertz {
209 // Assume that BusClk has default value. 216 // Assume that BusClk has default value.
210 // TODO: calculate BusClk more precisely. 217 // TODO: calculate BusClk more precisely.
211 match self.clock_source { 218 match self.clock_source {
@@ -214,16 +221,47 @@ impl Config {
214 } 221 }
215 } 222 }
216 223
217 pub fn check_clock_rate(&self) -> bool { 224 fn check_clock_i2c(&self) -> bool {
218 // make sure source clock is ~20 faster than i2c clock 225 // make sure source clock is ~20 faster than i2c clock
219 let clk_ratio = 20u8; 226 let clk_ratio = 20u8;
220 227
221 let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider(); 228 let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider();
222 let src_clk = self.calculate_clock_rate(); 229 let src_clk = self.calculate_clock_source();
223 230
224 // check clock rate 231 // check clock rate
225 return src_clk >= i2c_clk * clk_ratio; 232 return src_clk >= i2c_clk * clk_ratio;
226 } 233 }
234
235 fn define_clock_source(&mut self) -> bool {
236 // decide which clock source to choose based on i2c clock.
237 // If i2c speed <= 200kHz, use MfClk, otherwise use BusClk
238 if self.bus_speed.hertz() / self.clock_div.divider() > Hertz::khz(200) {
239 // TODO: check if BUSCLK enabled
240 self.clock_source = ClockSel::BusClk;
241 } else {
242 // is MFCLK enabled
243 if !pac::SYSCTL.mclkcfg().read().usemftick() {
244 return false;
245 }
246 self.clock_source = ClockSel::MfClk;
247 }
248 return true;
249 }
250
251 /// Check the config.
252 ///
253 /// Make sure that configuration is valid and enabled by the system.
254 pub fn check_config(&mut self) -> Result<(), ConfigError> {
255 if !self.define_clock_source() {
256 return Err(ConfigError::ClockSourceNotEnabled);
257 }
258
259 if !self.check_clock_i2c() {
260 return Err(ConfigError::InvalidClockRate);
261 }
262
263 Ok(())
264 }
227} 265}
228 266
229/// Serial error 267/// Serial error
@@ -288,7 +326,7 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> {
288 type ConfigError = ConfigError; 326 type ConfigError = ConfigError;
289 327
290 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { 328 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
291 self.set_config(config) 329 self.set_config(*config)
292 } 330 }
293} 331}
294 332
@@ -297,10 +335,10 @@ impl<'d> I2c<'d, Blocking> {
297 peri: Peri<'d, T>, 335 peri: Peri<'d, T>,
298 scl: Peri<'d, impl SclPin<T>>, 336 scl: Peri<'d, impl SclPin<T>>,
299 sda: Peri<'d, impl SdaPin<T>>, 337 sda: Peri<'d, impl SdaPin<T>>,
300 config: Config, 338 mut config: Config,
301 ) -> Result<Self, ConfigError> { 339 ) -> Result<Self, ConfigError> {
302 if !config.check_clock_rate() { 340 if let Err(err) = config.check_config() {
303 return Err(ConfigError::InvalidClockRate); 341 return Err(err);
304 } 342 }
305 343
306 Self::new_inner(peri, scl, sda, config) 344 Self::new_inner(peri, scl, sda, config)
@@ -313,10 +351,10 @@ impl<'d> I2c<'d, Async> {
313 scl: Peri<'d, impl SclPin<T>>, 351 scl: Peri<'d, impl SclPin<T>>,
314 sda: Peri<'d, impl SdaPin<T>>, 352 sda: Peri<'d, impl SdaPin<T>>,
315 _irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd, 353 _irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd,
316 config: Config, 354 mut config: Config,
317 ) -> Result<Self, ConfigError> { 355 ) -> Result<Self, ConfigError> {
318 if !config.check_clock_rate() { 356 if let Err(err) = config.check_config() {
319 return Err(ConfigError::InvalidClockRate); 357 return Err(err);
320 } 358 }
321 359
322 let i2c = Self::new_inner(peri, scl, sda, config); 360 let i2c = Self::new_inner(peri, scl, sda, config);
@@ -330,9 +368,9 @@ impl<'d> I2c<'d, Async> {
330 368
331impl<'d, M: Mode> I2c<'d, M> { 369impl<'d, M: Mode> I2c<'d, M> {
332 /// Reconfigure the driver 370 /// Reconfigure the driver
333 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 371 pub fn set_config(&mut self, mut config: Config) -> Result<(), ConfigError> {
334 if !config.check_clock_rate() { 372 if let Err(err) = config.check_config() {
335 return Err(ConfigError::InvalidClockRate); 373 return Err(err);
336 } 374 }
337 375
338 self.info.interrupt.disable(); 376 self.info.interrupt.disable();
@@ -345,7 +383,7 @@ impl<'d, M: Mode> I2c<'d, M> {
345 scl.update_pf(config.scl_pf()); 383 scl.update_pf(config.scl_pf());
346 } 384 }
347 385
348 self.init(config) 386 self.init(&config)
349 } 387 }
350 388
351 fn init(&mut self, config: &Config) -> Result<(), ConfigError> { 389 fn init(&mut self, config: &Config) -> Result<(), ConfigError> {
@@ -370,21 +408,25 @@ impl<'d, M: Mode> I2c<'d, M> {
370 }); 408 });
371 409
372 // Reset controller transfer, follow TI example 410 // Reset controller transfer, follow TI example
373 self.info 411 self.info.regs.controller(0).cctr().modify(|w| {
374 .regs 412 w.set_burstrun(false);
375 .controller(0) 413 w.set_start(false);
376 .cctr() 414 w.set_stop(false);
377 .write_value(i2c::regs::Cctr::default()); 415 w.set_ack(false);
416 w.set_cackoen(false);
417 w.set_rd_on_txempty(false);
418 w.set_cblen(0);
419 });
378 420
379 self.state 421 self.state
380 .clock 422 .clock
381 .store(config.calculate_clock_rate().0, Ordering::Relaxed); 423 .store(config.calculate_clock_source().0, Ordering::Relaxed);
382 424
383 self.info 425 self.info
384 .regs 426 .regs
385 .controller(0) 427 .controller(0)
386 .ctpr() 428 .ctpr()
387 .write(|w| w.set_tpr(config.timer_period())); 429 .write(|w| w.set_tpr(config.calculate_timer_period()));
388 430
389 // Set Tx Fifo threshold, follow TI example 431 // Set Tx Fifo threshold, follow TI example
390 self.info 432 self.info
@@ -1087,39 +1129,39 @@ mod tests {
1087 1129
1088 /// These tests are based on TI's reference caluclation. 1130 /// These tests are based on TI's reference caluclation.
1089 #[test] 1131 #[test]
1090 fn ti_timer_period() { 1132 fn ti_calculate_timer_period() {
1091 let mut config = Config::default(); 1133 let mut config = Config::default();
1092 config.clock_div = ClockDiv::DivBy1; 1134 config.clock_div = ClockDiv::DivBy1;
1093 config.bus_speed = BusSpeed::FastMode; 1135 config.bus_speed = BusSpeed::FastMode;
1094 config.clock_source = ClockSel::BusClk; 1136 config.clock_source = ClockSel::BusClk;
1095 assert!(matches!(config.timer_period(), 7)); 1137 assert!(matches!(config.calculate_timer_period(), 7));
1096 } 1138 }
1097 1139
1098 #[test] 1140 #[test]
1099 fn ti_timer_period_2() { 1141 fn ti_calculate_timer_period_2() {
1100 let mut config = Config::default(); 1142 let mut config = Config::default();
1101 config.clock_div = ClockDiv::DivBy2; 1143 config.clock_div = ClockDiv::DivBy2;
1102 config.bus_speed = BusSpeed::FastMode; 1144 config.bus_speed = BusSpeed::FastMode;
1103 config.clock_source = ClockSel::BusClk; 1145 config.clock_source = ClockSel::BusClk;
1104 assert!(matches!(config.timer_period(), 3)); 1146 assert!(matches!(config.calculate_timer_period(), 3));
1105 } 1147 }
1106 1148
1107 #[test] 1149 #[test]
1108 fn ti_timer_period_3() { 1150 fn ti_calculate_timer_period_3() {
1109 let mut config = Config::default(); 1151 let mut config = Config::default();
1110 config.clock_div = ClockDiv::DivBy2; 1152 config.clock_div = ClockDiv::DivBy2;
1111 config.bus_speed = BusSpeed::Standard; 1153 config.bus_speed = BusSpeed::Standard;
1112 config.clock_source = ClockSel::BusClk; 1154 config.clock_source = ClockSel::BusClk;
1113 assert!(matches!(config.timer_period(), 15)); 1155 assert!(matches!(config.calculate_timer_period(), 15));
1114 } 1156 }
1115 1157
1116 #[test] 1158 #[test]
1117 fn ti_timer_period_4() { 1159 fn ti_calculate_timer_period_4() {
1118 let mut config = Config::default(); 1160 let mut config = Config::default();
1119 config.clock_div = ClockDiv::DivBy2; 1161 config.clock_div = ClockDiv::DivBy2;
1120 config.bus_speed = BusSpeed::Custom(100_000); 1162 config.bus_speed = BusSpeed::Custom(100_000);
1121 config.clock_source = ClockSel::BusClk; 1163 config.clock_source = ClockSel::BusClk;
1122 assert!(matches!(config.timer_period(), 15)); 1164 assert!(matches!(config.calculate_timer_period(), 15));
1123 } 1165 }
1124 1166
1125 #[test] 1167 #[test]
@@ -1127,7 +1169,7 @@ mod tests {
1127 let mut config = Config::default(); 1169 let mut config = Config::default();
1128 config.clock_source = ClockSel::BusClk; 1170 config.clock_source = ClockSel::BusClk;
1129 config.bus_speed = BusSpeed::FastModePlus; 1171 config.bus_speed = BusSpeed::FastModePlus;
1130 assert!(config.check_clock_rate()); 1172 assert!(config.check_clock_i2c());
1131 } 1173 }
1132 1174
1133 #[test] 1175 #[test]
@@ -1135,7 +1177,7 @@ mod tests {
1135 let mut config = Config::default(); 1177 let mut config = Config::default();
1136 config.clock_source = ClockSel::BusClk; 1178 config.clock_source = ClockSel::BusClk;
1137 config.bus_speed = BusSpeed::FastMode; 1179 config.bus_speed = BusSpeed::FastMode;
1138 assert!(config.check_clock_rate()); 1180 assert!(config.check_clock_i2c());
1139 } 1181 }
1140 1182
1141 #[test] 1183 #[test]
@@ -1143,7 +1185,7 @@ mod tests {
1143 let mut config = Config::default(); 1185 let mut config = Config::default();
1144 config.clock_source = ClockSel::MfClk; 1186 config.clock_source = ClockSel::MfClk;
1145 config.bus_speed = BusSpeed::FastModePlus; 1187 config.bus_speed = BusSpeed::FastModePlus;
1146 assert!(!config.check_clock_rate()); 1188 assert!(!config.check_clock_i2c());
1147 } 1189 }
1148 1190
1149 #[test] 1191 #[test]
@@ -1151,6 +1193,6 @@ mod tests {
1151 let mut config = Config::default(); 1193 let mut config = Config::default();
1152 config.clock_source = ClockSel::MfClk; 1194 config.clock_source = ClockSel::MfClk;
1153 config.bus_speed = BusSpeed::FastMode; 1195 config.bus_speed = BusSpeed::FastMode;
1154 assert!(!config.check_clock_rate()); 1196 assert!(!config.check_clock_i2c());
1155 } 1197 }
1156} 1198}