Skip to content

Commit

Permalink
hub-ctrl: Add support for micro-controller reset via RPi usb power to…
Browse files Browse the repository at this point in the history
…ggling

Signed-off-by: Kevin O'Connor <[email protected]>
  • Loading branch information
KevinOConnor committed Apr 13, 2017
1 parent 9f9e3e6 commit daff83e
Show file tree
Hide file tree
Showing 6 changed files with 480 additions and 22 deletions.
9 changes: 6 additions & 3 deletions config/example.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,12 @@ pin_map: arduino
# default is to not enable the aliases.
#restart_method: arduino
# This controls the mechanism the host will use to reset the
# micro-controller. The choices are 'arduino' and 'command'. The
# 'arduino' method (toggle DTR; set baud to 1200) is common on
# Arduino boards and clones. The 'command' method involves sending a
# micro-controller. The choices are 'arduino', 'rpi_usb', and
# 'command'. The 'arduino' method (toggle DTR; set baud to 1200) is
# common on Arduino boards and clones. The 'rpi_usb' method is
# useful on Raspberry Pi boards with micro-controllers powered over
# USB - it briefly disables power to all USB ports to accomplish a
# micro-controller reset. The 'command' method involves sending a
# Klipper command to the micro-controller so that it can reset
# itself. The default is 'arduino'.
custom:
Expand Down
2 changes: 1 addition & 1 deletion docs/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ following commands:

```
sudo apt-get update
sudo apt-get install libncurses-dev
sudo apt-get install libncurses-dev libusb-dev
sudo apt-get install avrdude gcc-avr binutils-avr avr-libc # AVR toolchain
sudo apt-get install bossa-cli libnewlib-arm-none-eabi # ARM toolchain
```
Expand Down
41 changes: 32 additions & 9 deletions klippy/chelper.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Wrapper around C helper code
#
# Copyright (C) 2016 Kevin O'Connor <[email protected]>
# Copyright (C) 2016,2017 Kevin O'Connor <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import os, logging
import cffi


######################################################################
# c_helper.so compiling
######################################################################

COMPILE_CMD = "gcc -Wall -g -O2 -shared -fPIC -o %s %s"
SOURCE_FILES = ['stepcompress.c', 'serialqueue.c', 'pyhelper.c']
DEST_LIB = "c_helper.so"
Expand Down Expand Up @@ -79,14 +84,14 @@ def get_mtimes(srcdir, filelist):
return out

# Check if the code needs to be compiled
def check_build_code(srcdir):
src_times = get_mtimes(srcdir, SOURCE_FILES + OTHER_FILES)
obj_times = get_mtimes(srcdir, [DEST_LIB])
def check_build_code(srcdir, target, sources, cmd, other_files=[]):
src_times = get_mtimes(srcdir, sources + other_files)
obj_times = get_mtimes(srcdir, [target])
if not obj_times or max(src_times) > min(obj_times):
logging.info("Building C code module")
srcfiles = [os.path.join(srcdir, fname) for fname in SOURCE_FILES]
destlib = os.path.join(srcdir, DEST_LIB)
os.system(COMPILE_CMD % (destlib, ' '.join(srcfiles)))
logging.info("Building C code module %s" % (target,))
srcfiles = [os.path.join(srcdir, fname) for fname in sources]
destlib = os.path.join(srcdir, target)
os.system(cmd % (destlib, ' '.join(srcfiles)))

FFI_main = None
FFI_lib = None
Expand All @@ -97,7 +102,8 @@ def get_ffi():
global FFI_main, FFI_lib, pyhelper_logging_callback
if FFI_lib is None:
srcdir = os.path.dirname(os.path.realpath(__file__))
check_build_code(srcdir)
check_build_code(srcdir, DEST_LIB, SOURCE_FILES, COMPILE_CMD
, OTHER_FILES)
FFI_main = cffi.FFI()
FFI_main.cdef(defs_stepcompress)
FFI_main.cdef(defs_serialqueue)
Expand All @@ -110,3 +116,20 @@ def logging_callback(msg):
"void(const char *)", logging_callback)
FFI_lib.set_python_logging_callback(pyhelper_logging_callback)
return FFI_main, FFI_lib


######################################################################
# hub-ctrl hub power controller
######################################################################

HC_COMPILE_CMD = "gcc -Wall -g -O2 -o %s %s -lusb"
HC_SOURCE_FILES = ['hub-ctrl.c']
HC_SOURCE_DIR = '../lib/hub-ctrl'
HC_TARGET = "hub-ctrl"
HC_CMD = "sudo %s/hub-ctrl -h 0 -P 2 -p %d"

def run_hub_ctrl(enable_power):
srcdir = os.path.dirname(os.path.realpath(__file__))
hubdir = os.path.join(srcdir, HC_SOURCE_DIR)
check_build_code(hubdir, HC_TARGET, HC_SOURCE_FILES, HC_COMPILE_CMD)
os.system(HC_CMD % (hubdir, enable_power))
34 changes: 25 additions & 9 deletions klippy/mcu.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Multi-processor safe interface to micro-controller
#
# Copyright (C) 2016 Kevin O'Connor <[email protected]>
# Copyright (C) 2016,2017 Kevin O'Connor <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys, zlib, logging, math
import sys, os, zlib, logging, math
import serialhdl, pins, chelper

class error(Exception):
Expand Down Expand Up @@ -381,7 +381,7 @@ def __init__(self, printer, config):
self._is_fileoutput = False
self._timeout_timer = printer.reactor.register_timer(
self.timeout_handler)
rmethods = {m: m for m in ['arduino', 'command']}
rmethods = {m: m for m in ['arduino', 'command', 'rpi_usb']}
self._restart_method = config.getchoice(
'restart_method', rmethods, 'arduino')
# Config building
Expand Down Expand Up @@ -424,8 +424,19 @@ def handle_shutdown(self, params):
self.serial.dump_debug()
self._printer.note_shutdown(self._shutdown_msg)
# Connection phase
def _check_restart(self, reason):
if self._printer.get_startup_state() == 'firmware_restart':
return
logging.info("Attempting automated firmware restart: %s" % (reason,))
self._printer.request_exit('firmware_restart')
self._printer.reactor.pause(self._printer.reactor.monotonic() + 2.000)
raise error("Attempt firmware restart failed")
def connect(self):
if not self._is_fileoutput:
if (self._restart_method == 'rpi_usb'
and not os.path.exists(self._serialport)):
# Try toggling usb power
self._check_restart("enable power")
self.serial.connect()
self._printer.reactor.update_timer(
self._timeout_timer, self.monotonic() + self.COMM_TIMEOUT)
Expand Down Expand Up @@ -478,6 +489,13 @@ def clear_shutdown(self):
self.send(self._clear_shutdown_cmd.encode())
def microcontroller_restart(self):
reactor = self._printer.reactor
if self._restart_method == 'rpi_usb':
logging.info("Attempting a microcontroller reset via rpi usb power")
self.disconnect()
chelper.run_hub_ctrl(0)
reactor.pause(reactor.monotonic() + 2.000)
chelper.run_hub_ctrl(1)
return
if self._restart_method == 'command':
last_clock, last_clock_time = self.serial.get_last_clock()
eventtime = reactor.monotonic()
Expand Down Expand Up @@ -539,6 +557,9 @@ def _send_config(self):
else:
config_params = self.serial.send_with_response(msg, 'config')
if not config_params['is_config']:
if self._restart_method == 'rpi_usb':
# Only configure mcu after usb power reset
self._check_restart("full reset before config")
# Send config commands
logging.info("Sending printer configuration...")
for c in self._config_cmds:
Expand All @@ -551,12 +572,7 @@ def _send_config(self):
self._shutdown_msg,))
raise error("Unable to configure printer")
if self._config_crc != config_params['crc']:
if self._printer.get_startup_state() != 'firmware_restart':
# Attempt a firmware restart to fix the CRC error
logging.info(
"Printer CRC mismatch - attempting firmware restart")
self._printer.request_exit('firmware_restart')
self._printer.reactor.pause(0.100)
self._check_restart("CRC mismatch")
raise error("Printer CRC does not match config")
move_count = config_params['move_count']
logging.info("Configured (%d moves)" % (move_count,))
Expand Down
4 changes: 4 additions & 0 deletions lib/README
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ The cmsis-sam3x8e directory contains code from the Arduino project:
version 1.5.1 (extracted on 20160608). It has been modified to
compile with gcc's LTO feature. See cmsis-sam3x8e.patch for the
modifications.

The hub-ctrl directory contains code from:
https://github.com/codazoda/hub-ctrl.c/
revision 42095e522859059e8a5f4ec05c1e3def01a870a9.
Loading

0 comments on commit daff83e

Please sign in to comment.