pru: Support config_reset command to manually reset mcu

Add support for resetting the MCU via a software only mechanism.  This
is useful on the PRU.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-09-03 22:02:48 -04:00
parent 7b7f57e01c
commit 7083a33ecd
6 changed files with 52 additions and 12 deletions

View File

@ -430,14 +430,17 @@ class MCU:
self._shutdown_msg = "" self._shutdown_msg = ""
self._timeout_timer = printer.reactor.register_timer( self._timeout_timer = printer.reactor.register_timer(
self.timeout_handler) self.timeout_handler)
rmethods = {m: m for m in ['arduino', 'command', 'rpi_usb']} self._restart_method = 'command'
self._restart_method = config.getchoice( if baud:
'restart_method', rmethods, 'arduino') rmethods = {m: m for m in ['arduino', 'command', 'rpi_usb']}
self._restart_method = config.getchoice(
'restart_method', rmethods, 'arduino')
# Config building # Config building
if printer.bglogger is not None: if printer.bglogger is not None:
printer.bglogger.set_rollover_info("mcu", None) printer.bglogger.set_rollover_info("mcu", None)
pins.get_printer_pins(printer).register_chip("mcu", self) pins.get_printer_pins(printer).register_chip("mcu", self)
self._emergency_stop_cmd = self._reset_cmd = None self._emergency_stop_cmd = None
self._reset_cmd = self._config_reset_cmd = None
self._oid_count = 0 self._oid_count = 0
self._config_objects = [] self._config_objects = []
self._init_cmds = [] self._init_cmds = []
@ -502,10 +505,8 @@ class MCU:
self._stats_sumsq_base = self.serial.msgparser.get_constant_float( self._stats_sumsq_base = self.serial.msgparser.get_constant_float(
'STATS_SUMSQ_BASE') 'STATS_SUMSQ_BASE')
self._emergency_stop_cmd = self.lookup_command("emergency_stop") self._emergency_stop_cmd = self.lookup_command("emergency_stop")
try: self._reset_cmd = self.try_lookup_command("reset")
self._reset_cmd = self.lookup_command("reset") self._config_reset_cmd = self.try_lookup_command("config_reset")
except self.serial.msgparser.error as e:
pass
self.register_msg(self.handle_shutdown, 'shutdown') self.register_msg(self.handle_shutdown, 'shutdown')
self.register_msg(self.handle_shutdown, 'is_shutdown') self.register_msg(self.handle_shutdown, 'is_shutdown')
self.register_msg(self.handle_mcu_stats, 'stats') self.register_msg(self.handle_mcu_stats, 'stats')
@ -560,11 +561,21 @@ class MCU:
if self._restart_method == 'command': if self._restart_method == 'command':
last_clock, last_clock_time = self.serial.get_last_clock() last_clock, last_clock_time = self.serial.get_last_clock()
eventtime = reactor.monotonic() eventtime = reactor.monotonic()
if (self._reset_cmd is None if ((self._reset_cmd is None and self._config_reset_cmd is None)
or eventtime > last_clock_time + self.COMM_TIMEOUT): or eventtime > last_clock_time + self.COMM_TIMEOUT):
logging.info("Unable to issue reset command") logging.info("Unable to issue reset command")
return return
# Attempt reset via command if self._reset_cmd is None:
# Attempt reset via config_reset command
logging.info("Attempting a microcontroller config_reset command")
self.is_shutdown = True
self.force_shutdown()
reactor.pause(reactor.monotonic() + 0.015)
self.send(self._config_reset_cmd.encode())
reactor.pause(reactor.monotonic() + 0.015)
self.disconnect()
return
# Attempt reset via reset command
logging.info("Attempting a microcontroller reset command") logging.info("Attempting a microcontroller reset command")
self.send(self._reset_cmd.encode()) self.send(self._reset_cmd.encode())
reactor.pause(reactor.monotonic() + 0.015) reactor.pause(reactor.monotonic() + 0.015)
@ -682,6 +693,11 @@ class MCU:
return self.serial.alloc_command_queue() return self.serial.alloc_command_queue()
def lookup_command(self, msgformat): def lookup_command(self, msgformat):
return self.serial.msgparser.lookup_command(msgformat) return self.serial.msgparser.lookup_command(msgformat)
def try_lookup_command(self, msgformat):
try:
return self.serial.msgparser.lookup_command(msgformat)
except self.serial.msgparser.error as e:
return None
def create_command(self, msg): def create_command(self, msg):
return self.serial.msgparser.create_command(msg) return self.serial.msgparser.create_command(msg)
# Clock syncing # Clock syncing

View File

@ -215,6 +215,25 @@ command_finalize_config(uint32_t *args)
} }
DECL_COMMAND(command_finalize_config, "finalize_config crc=%u"); DECL_COMMAND(command_finalize_config, "finalize_config crc=%u");
// Attempt a full manual reset of the config
void
config_reset(uint32_t *args)
{
if (! sched_is_shutdown())
shutdown("config_reset only available when shutdown");
irq_disable();
config_crc = 0;
oid_count = 0;
oids = NULL;
move_free_list = NULL;
move_list = NULL;
move_count = move_item_size = 0;
alloc_init();
sched_timer_reset();
sched_clear_shutdown();
irq_enable();
}
/**************************************************************** /****************************************************************
* Timing and load stats * Timing and load stats

View File

@ -10,6 +10,7 @@ void *oid_lookup(uint8_t oid, void *type);
void *oid_alloc(uint8_t oid, void *type, uint16_t size); void *oid_alloc(uint8_t oid, void *type, uint16_t size);
void *oid_next(uint8_t *i, void *type); void *oid_next(uint8_t *i, void *type);
void stats_update(uint32_t start, uint32_t cur); void stats_update(uint32_t start, uint32_t cur);
void config_reset(uint32_t *args);
#define foreach_oid(pos,data,oidtype) \ #define foreach_oid(pos,data,oidtype) \
for (pos=-1; (data=oid_next(&pos, oidtype)); ) for (pos=-1; (data=oid_next(&pos, oidtype)); )

View File

@ -212,6 +212,9 @@ struct my_resource_table {
* Startup * Startup
****************************************************************/ ****************************************************************/
// Support config_reset
DECL_COMMAND_FLAGS(config_reset, HF_IN_SHUTDOWN, "config_reset");
// Main entry point // Main entry point
int int
main(void) main(void)

View File

@ -165,8 +165,8 @@ sched_timer_dispatch(void)
return next_waketime; return next_waketime;
} }
// Remove all user timers on a shutdown // Remove all user timers
static void void
sched_timer_reset(void) sched_timer_reset(void)
{ {
timer_list = &deleted_timer; timer_list = &deleted_timer;

View File

@ -29,6 +29,7 @@ struct task_wake {
void sched_add_timer(struct timer*); void sched_add_timer(struct timer*);
void sched_del_timer(struct timer *del); void sched_del_timer(struct timer *del);
unsigned int sched_timer_dispatch(void); unsigned int sched_timer_dispatch(void);
void sched_timer_reset(void);
void sched_wake_tasks(void); void sched_wake_tasks(void);
uint8_t sched_tasks_busy(void); uint8_t sched_tasks_busy(void);
void sched_wake_task(struct task_wake *w); void sched_wake_task(struct task_wake *w);