embedded_ccs811/
boot_mode.rs

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