APM:Libraries
Device.cpp
Go to the documentation of this file.
1 /*
2  * This file is free software: you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License as published by the
4  * Free Software Foundation, either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * This file is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License along
13  * with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 
16 #include "Device.h"
17 
18 #include <stdio.h>
19 
20 /*
21  using checked registers allows a device check that a set of critical
22  register values don't change at runtime. This is useful on key
23  sensors (such as IMUs) which may experience brownouts or other
24  issues in flight
25 
26  To use register checking call setup_checked_registers() once to
27  allocate the space for the checked register values. The set the
28  checked flag on any write_register() calls that you want protected.
29 
30  Periodically (say at 50Hz) you should then call
31  check_next_register(). If that returns false then the sensor has had
32  a corrupted register value. Marking the sensor as unhealthy is
33  approriate. The bad value will be corrected
34  */
35 
36 /*
37  setup nregs checked registers
38  */
39 bool AP_HAL::Device::setup_checked_registers(uint8_t nregs, uint8_t frequency)
40 {
41  if (_checked.regs != nullptr) {
42  delete[] _checked.regs;
43  _checked.n_allocated = 0;
44  _checked.n_set = 0;
45  _checked.next = 0;
46  }
47  _checked.regs = new struct checkreg[nregs];
48  if (_checked.regs == nullptr) {
49  return false;
50  }
51  _checked.n_allocated = nregs;
52  _checked.frequency = frequency;
53  _checked.counter = 0;
54  return true;
55 }
56 
57 /*
58  set value of one checked register
59  */
60 void AP_HAL::Device::set_checked_register(uint8_t reg, uint8_t val)
61 {
62  if (_checked.regs == nullptr) {
63  return;
64  }
65  struct checkreg *regs = _checked.regs;
66  for (uint8_t i=0; i<_checked.n_set; i++) {
67  if (regs[i].regnum == reg) {
68  regs[i].value = val;
69  return;
70  }
71  }
72  if (_checked.n_set == _checked.n_allocated) {
73  printf("Not enough checked registers for reg 0x%02x on device 0x%x\n",
74  (unsigned)reg, (unsigned)get_bus_id());
75  return;
76  }
77  regs[_checked.n_set].regnum = reg;
78  regs[_checked.n_set].value = val;
79  _checked.n_set++;
80 }
81 
82 /*
83  check one register value
84  */
86 {
87  if (_checked.n_set == 0) {
88  return true;
89  }
90  if (++_checked.counter < _checked.frequency) {
91  return true;
92  }
93  _checked.counter = 0;
94 
95  struct checkreg &reg = _checked.regs[_checked.next];
96  uint8_t v;
97  if (!read_registers(reg.regnum, &v, 1) || v != reg.value) {
98  // a register has changed value unexpectedly. Try changing it back
99  // and re-check it next time
100 #if 0
101  printf("Device 0x%x fixing 0x%02x 0x%02x -> 0x%02x\n",
102  (unsigned)get_bus_id(),
103  (unsigned)reg.regnum, (unsigned)v, (unsigned)reg.value);
104 #endif
105  write_register(reg.regnum, reg.value);
106  return false;
107  }
108  _checked.next = (_checked.next+1) % _checked.n_set;
109  return true;
110 }
int printf(const char *fmt,...)
Definition: stdio.c:113
uint8_t frequency
Definition: Device.h:305
struct checkreg * regs
Definition: Device.h:307
uint32_t get_bus_id(void) const
Definition: Device.h:60
bool setup_checked_registers(uint8_t num_regs, uint8_t frequency=10)
Definition: Device.cpp:39
struct AP_HAL::Device::@38 _checked
float v
Definition: Printf.cpp:15
void set_checked_register(uint8_t reg, uint8_t val)
Definition: Device.cpp:60
bool check_next_register(void)
Definition: Device.cpp:85
bool read_registers(uint8_t first_reg, uint8_t *recv, uint32_t recv_len)
Definition: Device.h:113
bool write_register(uint8_t reg, uint8_t val, bool checked=false)
Definition: Device.h:125