Skip to content

Commit 4108a2e

Browse files
committed
Changed const variables to static const
Introduced a fast_exit mode to the daemon to support a faster restart Added a call to Wire.end() to the initialization of the I2C bus. This allows to re-init the bus at any time with the same call. After half of the timeout the ATTiny starts to re-initialize the I2C bus every second as long as there is no new communication with the RPi. The combination of measures should allow for a faster recovery if the I2C bus is blocked
1 parent 3707c0d commit 4108a2e

File tree

5 files changed

+48
-38
lines changed

5 files changed

+48
-38
lines changed

daemon/attiny_daemon.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
from collections.abc import Mapping
1212
from pathlib import Path
1313
from attiny_i2c import ATTiny
14+
#from attiny_i2c_new import ATTiny
1415

1516
### Global configuration of the daemon. You should know what you do if you change
1617
### these values.
1718

1819
# Version information
1920
major = 2
20-
minor = 12
21-
patch = 3
21+
minor = 13
22+
patch = 1
2223

2324
# config file is in the same directory as the script:
2425
_configfile_default = str(Path(__file__).parent.absolute()) + "/attiny_daemon.cfg"
@@ -82,6 +83,7 @@ def main(*args):
8283
logging.info("Merging completed")
8384

8485
# loop until stopped or error
86+
fast_exit = False
8587
set_unprimed = False
8688
try:
8789
while True:
@@ -91,6 +93,7 @@ def main(*args):
9193
logging.error("Lost connection to ATTiny.")
9294
# disable to fasten restart
9395
# set_unprimed = True # we still try to reset primed
96+
fast_exit = True
9497
exit(1) # executes finally clause and lets the system restart the daemon
9598

9699
if should_shutdown > SL_INITIATED:
@@ -120,13 +123,15 @@ def main(*args):
120123
except Exception as e:
121124
logging.error("An exception occurred: '" + str(e) + "' Exiting...")
122125
finally:
123-
# will not be executed on SIGTERM, leaving primed set to the config value
124-
primed = config[Config.PRIMED]
125-
if args.nodaemon or set_unprimed:
126-
primed = False
127-
if primed == False:
128-
logging.info("Trying to reset primed flag")
129-
attiny.set_primed(primed)
126+
if fast_exit == False:
127+
# will not be executed on SIGTERM, leaving primed set to the config value
128+
primed = config[Config.PRIMED]
129+
if args.nodaemon or set_unprimed:
130+
primed = False
131+
if primed == False:
132+
logging.info("Trying to reset primed flag")
133+
attiny.set_primed(primed)
134+
del attiny
130135

131136

132137
def parse_cmdline(args: Tuple[Any]) -> Namespace:

firmware/ATTinyDaemon/ATTinyDaemon.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
/*
1818
Our version number - used by the daemon to ensure that the major number is equal between firmware and daemon
1919
*/
20-
const uint32_t MAJOR = 2;
21-
const uint32_t MINOR = 13;
22-
const uint32_t PATCH = 7;
20+
static const uint32_t MAJOR = 2;
21+
static const uint32_t MINOR = 13;
22+
static const uint32_t PATCH = 14;
2323

2424
/*
2525
Flash size definition
@@ -54,11 +54,11 @@ const uint32_t PATCH = 7;
5454
7 SCK ADC1 PCINT2 PB2 INT0
5555
8 VCC
5656
*/
57-
const uint8_t LED_BUTTON = PB4; // combined led/button pin
58-
const uint8_t PIN_SWITCH = PB1; // pin used for pushing the switch (the normal way to reset the RPi)
59-
const uint8_t PIN_RESET = PB5; // Reset pin (used as an alternative direct way to reset the RPi)
57+
static const uint8_t LED_BUTTON = PB4; // combined led/button pin
58+
static const uint8_t PIN_SWITCH = PB1; // pin used for pushing the switch (the normal way to reset the RPi)
59+
static const uint8_t PIN_RESET = PB5; // Reset pin (used as an alternative direct way to reset the RPi)
6060
// The following pin definition is needed as a define statement to allow the macro expansion in handleVoltages.ino
61-
#define EXT_VOLTAGE ADC3 // ADC number, used to measure external or RPi voltage (Ax, ADCx or x)
61+
#define EXT_VOLTAGE ADC3 // ADC number, used to measure external or RPi voltage (Ax, ADCx or x)
6262

6363

6464
#if defined SERIAL_DEBUG
@@ -69,10 +69,10 @@ const uint8_t PIN_RESET = PB5; // Reset pin (used as an alternative
6969
/*
7070
Basic constants
7171
*/
72-
const uint8_t BLINK_TIME = 100; // time in milliseconds for the LED to blink
73-
const uint16_t MIN_POWER_LEVEL = 4700; // the voltage level seen as "ON" at the external voltage after a reset
74-
const uint8_t NUM_MEASUREMENTS = 5; // the number of ADC measurements we average, should be larger than 4
75-
const uint8_t SW_TO_PULSE_DIV = 4; // The divisor from switch_delay_revocery to delay between multiple pulses
72+
static const uint8_t BLINK_TIME = 100; // time in milliseconds for the LED to blink
73+
static const uint16_t MIN_POWER_LEVEL = 4700; // the voltage level seen as "ON" at the external voltage after a reset
74+
static const uint8_t NUM_MEASUREMENTS = 5; // the number of ADC measurements we average, should be larger than 4
75+
static const uint8_t SW_TO_PULSE_DIV = 4; // The divisor from switch_delay_revocery to delay between multiple pulses
7676

7777
/*
7878
Values modelling the different states the system can be in
@@ -125,16 +125,16 @@ enum EEPROM_Address {
125125
This way, whenever the minor or major version changes, the eeprom will be initialized again to
126126
ensure that everything works without problems.
127127
*/
128-
const uint8_t BITS_FOR_MINOR = 5;
129-
const uint8_t BITS_FOR_MAJOR = CHAR_BIT - BITS_FOR_MINOR;
130-
const uint8_t MINOR_PART = MINOR & ((1<<BITS_FOR_MINOR)-1);
131-
const uint8_t MAJOR_PART = (MAJOR & BITS_FOR_MAJOR) << BITS_FOR_MINOR;
132-
const uint8_t EEPROM_INIT_VALUE = MAJOR_PART | MINOR_PART;
128+
static const uint8_t BITS_FOR_MINOR = 5;
129+
static const uint8_t BITS_FOR_MAJOR = CHAR_BIT - BITS_FOR_MINOR;
130+
static const uint8_t MINOR_PART = MINOR & ((1<<BITS_FOR_MINOR)-1);
131+
static const uint8_t MAJOR_PART = (MAJOR & BITS_FOR_MAJOR) << BITS_FOR_MINOR;
132+
static const uint8_t EEPROM_INIT_VALUE = MAJOR_PART | MINOR_PART;
133133

134134
/*
135135
I2C interface and register definitions
136136
*/
137-
const uint8_t I2C_ADDRESS = 0x37;
137+
static const uint8_t I2C_ADDRESS = 0x37;
138138

139139
enum class Register : uint8_t {
140140
last_access = 0x01,

firmware/ATTinyDaemon/ATTinyDaemon.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/*
1010
Store major and minor version and the patch level in a constant
1111
*/
12-
const uint32_t prog_version = (MAJOR << 16) | (MINOR << 8) | PATCH;
12+
static const uint32_t prog_version = (MAJOR << 16) | (MINOR << 8) | PATCH;
1313

1414
/*
1515
The state variable encapsulates the all-over state of the system (ATTiny and RPi
@@ -93,7 +93,7 @@ volatile bool update_eeprom = false;
9393
have been changed
9494
*/
9595
volatile uint8_t reset_bat_voltage = false;
96-
96+
9797
void setup() {
9898
mcusr_mirror = MCUSR;
9999
reset_watchdog (); // do this first in case WDT fires

firmware/ATTinyDaemon/handleI2C.ino

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ void init_I2C() {
55
#if defined SERIAL_DEBUG
66
Serial.println(F("In init_I2C()"));
77
#endif
8-
8+
Wire.end();
99
Wire.begin(I2C_ADDRESS);
1010
Wire.onRequest(request_event);
1111
Wire.onReceive(receive_event);
12-
// Wire.onInterrupt(disable_watchdog);
1312
}
1413

1514
/*

firmware/ATTinyDaemon/handleState.ino

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void handle_state() {
4747
// already signalled that it is doing so
4848
if (state <= State::warn_state) {
4949
// we first check whether the Raspberry is already in the shutdown process
50-
if(!(should_shutdown & Shutdown_Cause::rpi_initiated)) {
50+
if (!(should_shutdown & Shutdown_Cause::rpi_initiated)) {
5151
if (should_shutdown > Shutdown_Cause::rpi_initiated && (seconds_safe < timeout)) {
5252
// RPi should take action, possibly shut down. Signal by blinking 5 times
5353
blink_led(5, BLINK_TIME);
@@ -77,7 +77,7 @@ void handle_state() {
7777

7878
/*
7979
Act on the current state
80-
*/
80+
*/
8181
void act_on_state_change() {
8282
// This is placed before the general check of all stages as to
8383
// not duplicate the code of the shutdown_state
@@ -108,7 +108,7 @@ void act_on_state_change() {
108108
should_shutdown = Shutdown_Cause::none;
109109
} else if (state == State::warn_to_running) {
110110
// we have recovered from a warn state and are now at a safe voltage
111-
// we switch to State::running_state and let that state (below) handle
111+
// we switch to State::running_state and let that state (below) handle
112112
// the restart
113113
state = State::running_state;
114114
should_shutdown = Shutdown_Cause::none;
@@ -119,15 +119,21 @@ void act_on_state_change() {
119119

120120
if (state == State::running_state) {
121121
bool should_restart = false;
122+
bool reset_i2c_bus = false;
122123

123-
if(vext_off_is_shutdown) {
124+
if (vext_off_is_shutdown) {
124125
should_restart = ext_voltage < MIN_POWER_LEVEL;
125126
} else {
126127
ATOMIC_BLOCK(ATOMIC_FORCEON) {
127128
should_restart = seconds > timeout;
129+
reset_i2c_bus = seconds > (timeout / 2);
128130
}
129131
}
130132

133+
// reset bus until we get connection again or until time is out
134+
if (reset_i2c_bus) {
135+
init_I2C();
136+
}
131137
if (should_restart) {
132138
if (primed == 1) {
133139
// RPi has not accessed the I2C interface for more than timeout seconds.
@@ -157,11 +163,11 @@ void voltage_dependent_state_change() {
157163
}
158164

159165
if (bat_voltage <= ups_shutdown_voltage_safe) {
160-
if(state < State::warn_to_shutdown) {
166+
if (state < State::warn_to_shutdown) {
161167
state = State::warn_to_shutdown;
162168
}
163169
} else if (bat_voltage <= warn_voltage_safe) {
164-
if(state < State::warn_state) {
170+
if (state < State::warn_state) {
165171
state = State::warn_state;
166172
should_shutdown |= Shutdown_Cause::bat_voltage;
167173
}
@@ -198,10 +204,10 @@ void voltage_dependent_state_change() {
198204
/*
199205
When we get an I2C communication then this might change our state (because now we
200206
know the RPi is alive). Called only during an interrupt.
201-
*/
207+
*/
202208
void i2c_triggered_state_change() {
203209
// If we are in an unclear state, then a communication from the RPi moves us to running state
204210
if (state == State::unclear_state) {
205211
state = State::running_state;
206-
}
212+
}
207213
}

0 commit comments

Comments
 (0)