embedded_ccs811/
boot_mode.rs1use crate::hal::{delay::DelayNs, digital::OutputPin};
2use crate::{
3 hal, mode, ActionInProgress, BitFlags, Ccs811, Ccs811Awake, Ccs811BootMode, Ccs811Device,
4 Error, ErrorAwake, ModeChangeError, Register,
5};
6
7impl<I2C, E> Ccs811BootMode for Ccs811Awake<I2C, mode::Boot>
8where
9 I2C: hal::i2c::I2c<Error = E>,
10{
11 type Error = ErrorAwake<E>;
12 type ModeChangeError = ModeChangeError<Self::Error, Self>;
13 type TargetType = Ccs811Awake<I2C, mode::App>;
14
15 fn start_application(mut self) -> Result<Self::TargetType, Self::ModeChangeError> {
16 match self.has_valid_app() {
17 Err(e) => Err(ModeChangeError::new(self, e)),
18 Ok(is_valid) => {
19 if !is_valid {
20 Err(ModeChangeError::new(self, ErrorAwake::NoValidApp))
21 } else {
22 match self.write_register_no_data(Register::APP_START) {
23 Err(e) => Err(ModeChangeError::new(self, e)),
24 Ok(_) => Ok(Ccs811Awake::create(self.i2c, self.address)),
25 }
26 }
27 }
28 }
29 }
30
31 fn verify_application(&mut self) -> nb::Result<(), Self::Error> {
32 let status = self.read_status().map_err(nb::Error::Other)?;
33 let verified = (status & BitFlags::APP_VERIFY) != 0;
34 if !verified {
35 if self.in_progress == ActionInProgress::Verification {
36 Err(nb::Error::WouldBlock)
37 } else {
38 let result = self
39 .i2c
40 .write(self.address, &[Register::APP_VERIFY])
41 .map_err(ErrorAwake::I2C);
42 match result {
43 Ok(_) => {
44 self.in_progress = ActionInProgress::Verification;
45 Err(nb::Error::WouldBlock)
46 }
47 Err(e) => Err(nb::Error::Other(e)),
48 }
49 }
50 } else {
51 self.in_progress = ActionInProgress::None;
52 Ok(())
53 }
54 }
55
56 fn erase_application(&mut self) -> nb::Result<(), Self::Error> {
57 let status = self.read_status().map_err(nb::Error::Other)?;
58 let erased = (status & BitFlags::APP_ERASE) != 0;
59 if !erased {
60 if self.in_progress == ActionInProgress::Erase {
61 Err(nb::Error::WouldBlock)
62 } else {
63 let result = self
64 .i2c
65 .write(self.address, &[Register::APP_ERASE, 0xE7, 0xA7, 0xE6, 0x09])
66 .map_err(ErrorAwake::I2C);
67 match result {
68 Ok(_) => {
69 self.in_progress = ActionInProgress::Erase;
70 Err(nb::Error::WouldBlock)
71 }
72 Err(e) => Err(nb::Error::Other(e)),
73 }
74 }
75 } else {
76 self.in_progress = ActionInProgress::None;
77 Ok(())
78 }
79 }
80
81 fn download_application<D: DelayNs>(
82 &mut self,
83 bin: &[u8],
84 delay: &mut D,
85 ) -> Result<(), Self::Error> {
86 if bin.len() % 8 != 0 {
87 return Err(ErrorAwake::InvalidInputData);
88 }
89 let mut data = [0; 9];
90 data[0] = Register::REG_BOOT_APP;
91 for chunk in bin.chunks(8) {
92 data[1..].copy_from_slice(chunk);
93 self.i2c
94 .write(self.address, &data)
95 .map_err(ErrorAwake::I2C)?;
96 delay.delay_ms(50);
97 }
98 self.check_status_error()
99 }
100
101 fn update_application<D: DelayNs>(
102 &mut self,
103 bin: &[u8],
104 delay: &mut D,
105 ) -> Result<(), Self::Error> {
106 self.write_sw_reset()?;
107 delay.delay_ms(20);
108 loop {
109 match self.erase_application() {
110 Err(nb::Error::WouldBlock) => delay.delay_ms(500),
111 Err(nb::Error::Other(e)) => return Err(e),
112 Ok(_) => break,
113 }
114 }
115 self.download_application(bin, delay)?;
116 loop {
117 match self.verify_application() {
118 Err(nb::Error::WouldBlock) => delay.delay_ms(70),
119 Err(nb::Error::Other(e)) => return Err(e),
120 Ok(_) => break,
121 }
122 }
123 Ok(())
124 }
125
126 fn software_reset(&mut self) -> Result<(), Self::Error> {
128 self.write_sw_reset()
129 }
130}
131
132impl<I2C, CommE, PinE, NWAKE, WAKEDELAY> Ccs811BootMode
133 for Ccs811<I2C, NWAKE, WAKEDELAY, mode::Boot>
134where
135 I2C: hal::i2c::I2c<Error = CommE>,
136 NWAKE: OutputPin<Error = PinE>,
137 WAKEDELAY: DelayNs,
138{
139 type Error = Error<CommE, PinE>;
140 type ModeChangeError = ModeChangeError<Self::Error, Self>;
141 type TargetType = Ccs811<I2C, NWAKE, WAKEDELAY, mode::App>;
142
143 fn start_application(self) -> Result<Self::TargetType, Self::ModeChangeError> {
144 self.wrap_mode_change(|s| s.start_application())
145 }
146
147 fn verify_application(&mut self) -> nb::Result<(), Self::Error> {
148 self.on_awaken_nb(|s| s.dev.verify_application())
149 }
150
151 fn erase_application(&mut self) -> nb::Result<(), Self::Error> {
152 self.on_awaken_nb(|s| s.dev.erase_application())
153 }
154
155 fn download_application<D: DelayNs>(
156 &mut self,
157 bin: &[u8],
158 delay: &mut D,
159 ) -> Result<(), Self::Error> {
160 self.on_awaken(|s| s.dev.download_application(bin, delay))
161 }
162
163 fn update_application<D: DelayNs>(
164 &mut self,
165 bin: &[u8],
166 delay: &mut D,
167 ) -> Result<(), Self::Error> {
168 self.on_awaken(|s| s.dev.update_application(bin, delay))
169 }
170
171 fn software_reset(&mut self) -> Result<(), Self::Error> {
172 self.on_awaken(|s| s.dev.software_reset())
173 }
174}