Skip to content

Commit 55dba9a

Browse files
committed
Made odometer persist after firmware updates, added hw runtime counter
1 parent d35e494 commit 55dba9a

10 files changed

+127
-32
lines changed

CHANGELOG

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* Better current controller windup protection.
1818
* Field weakening support (experimental, be careful and use at your own risk).
1919
* Use filtered current for axis decoupling.
20+
* Odometer is now persistent after firmware updates.
21+
* Added hw runtime counter (see hw_status in terminal)
2022

2123
=== FW 5.02 ===
2224
* IMU calibration improvement.

commands.c

+1
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ void commands_process_packet(unsigned char *data, unsigned int len,
582582
} break;
583583

584584
case COMM_REBOOT:
585+
conf_general_store_backup_data();
585586
// Lock the system and enter an infinite loop. The watchdog will reboot.
586587
__disable_irq();
587588
for(;;){};

conf_general.c

+77
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
#define EEPROM_BASE_HW 3000
4949
#define EEPROM_BASE_CUSTOM 4000
5050
#define EEPROM_BASE_MCCONF_2 5000
51+
#define EEPROM_BASE_BACKUP 6000
5152

5253
// Global variables
5354
uint16_t VirtAddVarTab[NB_OF_VAR];
5455
bool conf_general_permanent_nrf_found = false;
56+
__attribute__((section(".ram4"))) volatile backup_data g_backup;
5557

5658
// Private functions
5759
static bool read_eeprom_var(eeprom_var *v, int address, uint16_t base);
@@ -78,11 +80,86 @@ void conf_general_init(void) {
7880
VirtAddVarTab[ind++] = EEPROM_BASE_CUSTOM + i;
7981
}
8082

83+
for (unsigned int i = 0;i < (sizeof(backup_data) / 2);i++) {
84+
VirtAddVarTab[ind++] = EEPROM_BASE_BACKUP + i;
85+
}
86+
8187
FLASH_Unlock();
8288
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
8389
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
8490
EE_Init();
8591
FLASH_Lock();
92+
93+
// Read backup data
94+
bool is_ok = true;
95+
backup_data backup_tmp;
96+
uint8_t *data_addr = (uint8_t*)&backup_tmp;
97+
uint16_t var;
98+
99+
for (unsigned int i = 0;i < (sizeof(backup_data) / 2);i++) {
100+
if (EE_ReadVariable(EEPROM_BASE_BACKUP + i, &var) == 0) {
101+
data_addr[2 * i] = (var >> 8) & 0xFF;
102+
data_addr[2 * i + 1] = var & 0xFF;
103+
} else {
104+
is_ok = false;
105+
break;
106+
}
107+
}
108+
109+
if (!is_ok) {
110+
memset(data_addr, 0, sizeof(backup_data));
111+
112+
// If the missing data is a result of programming it might still be in RAM4. Check
113+
// and recover the valid values one by one.
114+
115+
if (g_backup.odometer_init_flag == BACKUP_VAR_INIT_CODE) {
116+
backup_tmp.odometer = g_backup.odometer;
117+
}
118+
119+
if (g_backup.runtime_init_flag == BACKUP_VAR_INIT_CODE) {
120+
backup_tmp.runtime = g_backup.runtime;
121+
}
122+
}
123+
124+
backup_tmp.odometer_init_flag = BACKUP_VAR_INIT_CODE;
125+
backup_tmp.runtime_init_flag = BACKUP_VAR_INIT_CODE;
126+
127+
g_backup = backup_tmp;
128+
conf_general_store_backup_data();
129+
}
130+
131+
/*
132+
* Store backup data to emulated eeprom. Currently this is only done from the shutdown function, which
133+
* only works if the hardware has a power switch. It would be possible to do this when the input voltage
134+
* drops (e.g. on FAULT_CODE_UNDER_VOLTAGE) to not rely on a power switch. The risk with that is that
135+
* a page swap might longer than the capacitors have voltage left, which could make cause the motor and
136+
* app config to get lost.
137+
*/
138+
bool conf_general_store_backup_data(void) {
139+
timeout_configure_IWDT_slowest();
140+
141+
bool is_ok = true;
142+
uint8_t *data_addr = (uint8_t*)&g_backup;
143+
uint16_t var;
144+
145+
FLASH_Unlock();
146+
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
147+
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
148+
149+
for (unsigned int i = 0;i < (sizeof(backup_data) / 2);i++) {
150+
var = (data_addr[2 * i] << 8) & 0xFF00;
151+
var |= data_addr[2 * i + 1] & 0xFF;
152+
153+
if (EE_WriteVariable(EEPROM_BASE_BACKUP + i, var) != FLASH_COMPLETE) {
154+
is_ok = false;
155+
break;
156+
}
157+
}
158+
FLASH_Lock();
159+
160+
timeout_configure_IWDT();
161+
162+
return is_ok;
86163
}
87164

88165
/**

conf_general.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#define FW_VERSION_MAJOR 5
2525
#define FW_VERSION_MINOR 03
2626
// Set to 0 for building a release and iterate during beta test builds
27-
#define FW_TEST_VERSION_NUMBER 20
27+
#define FW_TEST_VERSION_NUMBER 21
2828

2929
#include "datatypes.h"
3030

@@ -315,9 +315,11 @@
315315

316316
// Global configuration variables
317317
extern bool conf_general_permanent_nrf_found;
318+
extern volatile backup_data g_backup;
318319

319320
// Functions
320321
void conf_general_init(void);
322+
bool conf_general_store_backup_data(void);
321323
bool conf_general_read_eeprom_var_hw(eeprom_var *v, int address);
322324
bool conf_general_read_eeprom_var_custom(eeprom_var *v, int address);
323325
bool conf_general_store_eeprom_var_hw(eeprom_var *v, int address);

datatypes.h

+10
Original file line numberDiff line numberDiff line change
@@ -1221,4 +1221,14 @@ typedef struct {
12211221
uint8_t num_vescs;
12221222
} setup_values;
12231223

1224+
#define BACKUP_VAR_INIT_CODE 92891934
1225+
1226+
typedef struct __attribute__((packed)) {
1227+
uint32_t odometer_init_flag;
1228+
uint64_t odometer; // Meters
1229+
1230+
uint32_t runtime_init_flag;
1231+
uint64_t runtime; // Seconds
1232+
} backup_data;
1233+
12241234
#endif /* DATATYPES_H_ */

eeprom.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171

7272
/* Variables' number */
7373
#define NB_OF_VAR ((uint16_t)((2 * sizeof(mc_configuration) + sizeof(app_configuration) + 1) / 2) + \
74-
EEPROM_VARS_HW * 2 + EEPROM_VARS_CUSTOM * 2)
74+
EEPROM_VARS_HW * 2 + EEPROM_VARS_CUSTOM * 2 + sizeof(backup_data) * 2)
7575

7676
/* Exported types ------------------------------------------------------------*/
7777
/* Exported macro ------------------------------------------------------------*/

mc_interface.c

+25-24
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ typedef struct {
8383
float m_motor_current_unbalance;
8484
float m_motor_current_unbalance_error_rate;
8585
float m_f_samp_now;
86+
87+
// Backup data counters
88+
uint64_t m_odometer_last;
89+
uint64_t m_runtime_last;
8690
} motor_if_state_t;
8791

8892
// Private variables
@@ -115,8 +119,6 @@ static volatile bool m_sample_is_second_motor;
115119
static volatile mc_fault_code m_fault_stop_fault;
116120
static volatile bool m_fault_stop_is_second_motor;
117121

118-
static volatile uint32_t m_odometer_meters;
119-
120122
// Private functions
121123
static void update_override_limits(volatile motor_if_state_t *motor, volatile mc_configuration *conf);
122124
static void run_timer_tasks(volatile motor_if_state_t *motor);
@@ -159,12 +161,6 @@ void mc_interface_init(void) {
159161
m_sample_mode = DEBUG_SAMPLING_OFF;
160162
m_sample_mode_last = DEBUG_SAMPLING_OFF;
161163
m_sample_is_second_motor = false;
162-
//initialize odometer to EEPROM value
163-
m_odometer_meters = 0;
164-
eeprom_var v;
165-
if(conf_general_read_eeprom_var_custom(&v, EEPROM_ADDR_ODOMETER)) {
166-
m_odometer_meters = v.as_u32;
167-
}
168164

169165
// Start threads
170166
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL);
@@ -2122,6 +2118,23 @@ static void run_timer_tasks(volatile motor_if_state_t *motor) {
21222118
bool is_motor_1 = motor == &m_motor_1;
21232119
mc_interface_select_motor_thread(is_motor_1 ? 1 : 2);
21242120

2121+
// Update backup data (for motor 1 only)
2122+
if (is_motor_1) {
2123+
uint64_t odometer = mc_interface_get_distance_abs();
2124+
g_backup.odometer += odometer - m_motor_1.m_odometer_last;
2125+
m_motor_1.m_odometer_last = odometer;
2126+
2127+
uint64_t runtime = chVTGetSystemTimeX() / CH_CFG_ST_FREQUENCY;
2128+
2129+
// Handle wrap around
2130+
if (runtime < m_motor_1.m_runtime_last) {
2131+
m_motor_1.m_runtime_last = 0;
2132+
}
2133+
2134+
g_backup.runtime += runtime - m_motor_1.m_runtime_last;
2135+
m_motor_1.m_runtime_last = runtime;
2136+
}
2137+
21252138
motor->m_f_samp_now = mc_interface_get_sampling_frequency_now();
21262139

21272140
// Decrease fault iterations
@@ -2453,8 +2466,8 @@ unsigned mc_interface_calc_crc(mc_configuration* conf_in, bool is_motor_2) {
24532466
* @param new_odometer_meters
24542467
* new odometer value in meters
24552468
*/
2456-
void mc_interface_set_odometer(uint32_t new_odometer_meters) {
2457-
m_odometer_meters = new_odometer_meters - roundf(mc_interface_get_distance_abs());
2469+
void mc_interface_set_odometer(uint64_t new_odometer_meters) {
2470+
g_backup.odometer = new_odometer_meters;
24582471
}
24592472

24602473
/**
@@ -2463,18 +2476,6 @@ void mc_interface_set_odometer(uint32_t new_odometer_meters) {
24632476
* @return
24642477
* Odometer value in meters, including current trip
24652478
*/
2466-
uint32_t mc_interface_get_odometer(void) {
2467-
return m_odometer_meters + roundf(mc_interface_get_distance_abs());
2468-
}
2469-
2470-
/**
2471-
* Save current odometer value to persistent memory
2472-
*
2473-
* @return
2474-
* success
2475-
*/
2476-
bool mc_interface_save_odometer(void) {
2477-
eeprom_var v;
2478-
v.as_u32 = mc_interface_get_odometer();
2479-
return conf_general_store_eeprom_var_custom(&v, EEPROM_ADDR_ODOMETER);
2479+
uint64_t mc_interface_get_odometer(void) {
2480+
return g_backup.odometer;
24802481
}

mc_interface.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,8 @@ float mc_interface_get_distance(void);
8686
float mc_interface_get_distance_abs(void);
8787

8888
// odometer
89-
uint32_t mc_interface_get_odometer(void);
90-
void mc_interface_set_odometer(uint32_t new_odometer_meters);
91-
bool mc_interface_save_odometer(void);
89+
uint64_t mc_interface_get_odometer(void);
90+
void mc_interface_set_odometer(uint64_t new_odometer_meters);
9291

9392
setup_values mc_interface_get_setup_values(void);
9493

shutdown.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "shutdown.h"
2121
#include "app.h"
22-
#include "mc_interface.h"
22+
#include "conf_general.h"
2323

2424
#ifdef HW_SHUTDOWN_HOLD_ON
2525

@@ -63,7 +63,7 @@ void shutdown_set_sampling_disabled(bool disabled) {
6363
}
6464

6565
bool do_shutdown(void) {
66-
mc_interface_save_odometer();
66+
conf_general_store_backup_data();
6767
DISABLE_GATE();
6868
HW_SHUTDOWN_HOLD_OFF();
6969
return true;

terminal.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void terminal_process_string(char *str) {
165165
} else if (strcmp(argv[0], "dist") == 0) {
166166
commands_printf("Trip dist. : %.2f m", (double)mc_interface_get_distance());
167167
commands_printf("Trip dist. (ABS): %.2f m", (double)mc_interface_get_distance_abs());
168-
commands_printf("Odometer : %u m\n", mc_interface_get_odometer());
168+
commands_printf("Odometer : %llu m\n", mc_interface_get_odometer());
169169
} else if (strcmp(argv[0], "tim") == 0) {
170170
chSysLock();
171171
volatile int t1_cnt = TIM1->CNT;
@@ -548,6 +548,9 @@ void terminal_process_string(char *str) {
548548
STM32_UUID_8[8], STM32_UUID_8[9], STM32_UUID_8[10], STM32_UUID_8[11]);
549549
commands_printf("Permanent NRF found: %s", conf_general_permanent_nrf_found ? "Yes" : "No");
550550

551+
commands_printf("Odometer : %llu m", mc_interface_get_odometer());
552+
commands_printf("Runtime : %llu s", g_backup.runtime);
553+
551554
float curr0_offset;
552555
float curr1_offset;
553556
float curr2_offset;

0 commit comments

Comments
 (0)