embedded_ccs811/
boot_mode.rs

1use 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    // Note: is_verifying is false after a reset
127    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}