diff --git a/klippy/extras/bus.py b/klippy/extras/bus.py index 8bd4bc9f..d7e2be51 100644 --- a/klippy/extras/bus.py +++ b/klippy/extras/bus.py @@ -38,37 +38,33 @@ def resolve_bus_name(mcu, param, bus): # Helper code for working with devices connected to an MCU via an SPI bus class MCU_SPI: - def __init__(self, mcu, bus, pin, mode, speed, shutdown_seq, sw_pins=None): + def __init__(self, mcu, bus, pin, mode, speed, sw_pins=None): self.mcu = mcu self.bus = bus - shutdown_msg = "".join(["%02x" % (x,) for x in shutdown_seq]) - self.oid = self.mcu.create_oid() - if pin is not None: - # Set all CS pins high before first config_spi - self.mcu.add_config_cmd("set_digital_out pin=%s value=1" % (pin,)) - self.config_sw_msg = None + # Config SPI object (set all CS pins high before spi_set_bus commands) + self.oid = mcu.create_oid() + if pin is None: + mcu.add_config_cmd("config_spi_without_cs oid=%d" % (self.oid,)) + else: + mcu.add_config_cmd("config_spi oid=%d pin=%s" % (self.oid, pin)) + # Generate SPI bus config message if sw_pins is not None: - software_spi_oid = self.mcu.create_oid() - self.config_sw_msg = ( - "config_software_spi oid=%d sclk_pin=%s mosi_pin=%s miso_pin=%s" - " mode=%d rate=%d" % ( - software_spi_oid, sw_pins[0], sw_pins[1], sw_pins[2], - mode, speed)) self.config_fmt = ( - "config_spi_from_software oid=%d sw_oid=%d pin=%s" - " shutdown_msg=%s" % ( - self.oid, software_spi_oid, pin, shutdown_msg)) - elif pin is None: - self.config_fmt = ( - "config_spi_without_cs oid=%d spi_bus=%%s mode=%d rate=%d" - " shutdown_msg=%s" % (self.oid, mode, speed, shutdown_msg)) + "spi_set_software_bus oid=%d" + " miso_pin=%s mosi_pin=%s sclk_pin=%s mode=%d rate=%d" + % (self.oid, sw_pins[0], sw_pins[1], sw_pins[2], mode, speed)) else: self.config_fmt = ( - "config_spi oid=%d spi_bus=%%s pin=%s mode=%d rate=%d" - " shutdown_msg=%s" % (self.oid, pin, mode, speed, shutdown_msg)) - self.cmd_queue = self.mcu.alloc_command_queue() - self.mcu.register_config_callback(self.build_config) + "spi_set_bus oid=%d spi_bus=%%s mode=%d rate=%d" + % (self.oid, mode, speed)) + self.cmd_queue = mcu.alloc_command_queue() + mcu.register_config_callback(self.build_config) self.spi_send_cmd = self.spi_transfer_cmd = None + def setup_shutdown_msg(self, shutdown_seq): + shutdown_msg = "".join(["%02x" % (x,) for x in shutdown_seq]) + self.mcu.add_config_cmd( + "config_spi_shutdown oid=%d spi_oid=%d shutdown_msg=%s" + % (self.mcu.create_oid(), self.oid, shutdown_msg)) def get_oid(self): return self.oid def get_mcu(self): @@ -76,12 +72,10 @@ class MCU_SPI: def get_command_queue(self): return self.cmd_queue def build_config(self): - if self.config_sw_msg is not None: - self.mcu.add_config_cmd(self.config_sw_msg) - self.mcu.add_config_cmd(self.config_fmt) - else: + if '%' in self.config_fmt: bus = resolve_bus_name(self.mcu, "spi_bus", self.bus) - self.mcu.add_config_cmd(self.config_fmt % (bus,)) + self.config_fmt = self.config_fmt % (bus,) + self.mcu.add_config_cmd(self.config_fmt) self.spi_send_cmd = self.mcu.lookup_command( "spi_send oid=%c data=%*s", cq=self.cmd_queue) self.spi_transfer_cmd = self.mcu.lookup_command( @@ -101,7 +95,7 @@ class MCU_SPI: # Helper to setup an spi bus from settings in a config section def MCU_SPI_from_config(config, mode, pin_option="cs_pin", - default_speed=100000, shutdown_seq=()): + default_speed=100000): # Determine pin from config ppins = config.get_printer().lookup_object("pins") cs_pin = config.get(pin_option) @@ -115,7 +109,7 @@ def MCU_SPI_from_config(config, mode, pin_option="cs_pin", speed = config.getint('spi_speed', default_speed, minval=100000) if config.get('spi_software_sclk_pin', None) is not None: sw_pin_names = ['spi_software_%s_pin' % (name,) - for name in ['sclk', 'mosi', 'miso']] + for name in ['miso', 'mosi', 'sclk']] sw_pin_params = [ppins.lookup_pin(config.get(name), share_type=name) for name in sw_pin_names] for pin_params in sw_pin_params: @@ -128,7 +122,7 @@ def MCU_SPI_from_config(config, mode, pin_option="cs_pin", bus = config.get('spi_bus', None) sw_pins = None # Create MCU_SPI object - return MCU_SPI(mcu, bus, pin, mode, speed, shutdown_seq, sw_pins) + return MCU_SPI(mcu, bus, pin, mode, speed, sw_pins) ###################################################################### diff --git a/klippy/extras/replicape.py b/klippy/extras/replicape.py index b6419217..75687277 100644 --- a/klippy/extras/replicape.py +++ b/klippy/extras/replicape.py @@ -201,8 +201,8 @@ class Replicape: if not self.host_mcu.is_fileoutput() and os.path.exists( '/sys/devices/platform/ocp/481a0000.spi/spi_master/spi2'): sr_spi_bus = "spidev2.1" - self.sr_spi = bus.MCU_SPI(self.host_mcu, sr_spi_bus, - None, 0, 50000000, self.sr_disabled) + self.sr_spi = bus.MCU_SPI(self.host_mcu, sr_spi_bus, None, 0, 50000000) + self.sr_spi.setup_shutdown_msg(self.sr_disabled) self.sr_spi.spi_send(self.sr_disabled) def note_pwm_start_value(self, channel, start_value, shutdown_value): self.mcu_pwm_start_value |= not not start_value diff --git a/src/atsamd/spi.c b/src/atsamd/spi.c index 67c68cea..02aad5d3 100644 --- a/src/atsamd/spi.c +++ b/src/atsamd/spi.c @@ -6,9 +6,7 @@ // This file may be distributed under the terms of the GNU GPLv3 license. #include "internal.h" // enable_pclock -#include "command.h" // shutdown #include "gpio.h" // spi_setup -#include "sched.h" // sched_shutdown void spi_init(uint32_t bus, SercomSpi *ss, uint32_t ctrla, uint32_t baud) diff --git a/src/basecmd.c b/src/basecmd.c index 95511885..7b402ca1 100644 --- a/src/basecmd.c +++ b/src/basecmd.c @@ -27,7 +27,7 @@ alloc_init(void) DECL_INIT(alloc_init); // Allocate an area of memory -static void * +void * alloc_chunk(size_t size) { if (alloc_end + size > dynmem_end()) diff --git a/src/basecmd.h b/src/basecmd.h index 21555bf8..f4ea1cc7 100644 --- a/src/basecmd.h +++ b/src/basecmd.h @@ -1,8 +1,10 @@ #ifndef __BASECMD_H #define __BASECMD_H +#include // size_t #include // uint8_t +void *alloc_chunk(size_t size); void move_free(void *m); void *move_alloc(void); void move_request_size(int size); diff --git a/src/linux/spidev.c b/src/linux/spidev.c index 5c613cba..764541e3 100644 --- a/src/linux/spidev.c +++ b/src/linux/spidev.c @@ -97,13 +97,13 @@ spi_transfer(struct spi_config config, uint8_t receive_data int ret = ioctl(config.fd, SPI_IOC_MESSAGE(1), &transfer); if (ret < 0) { report_errno("spi ioctl", ret); - shutdown("Unable to issue spi ioctl"); + try_shutdown("Unable to issue spi ioctl"); } } else { int ret = write(config.fd, data, len); if (ret < 0) { report_errno("write spi", ret); - shutdown("Unable to write to spi"); + try_shutdown("Unable to write to spi"); } } } diff --git a/src/spi_software.c b/src/spi_software.c index 2d086f78..345e2f81 100644 --- a/src/spi_software.c +++ b/src/spi_software.c @@ -9,39 +9,33 @@ #include "basecmd.h" // oid_alloc #include "command.h" // DECL_COMMAND #include "sched.h" // sched_shutdown +#include "spicmds.h" // spidev_set_software_bus struct spi_software { - struct gpio_out sclk, mosi; struct gpio_in miso; + struct gpio_out mosi, sclk; uint8_t mode; }; void -command_config_software_spi(uint32_t *args) +command_spi_set_software_bus(uint32_t *args) { - uint8_t oid = args[0], sclk_pin = args[1], mosi_pin = args[2]; - uint8_t miso_pin = args[3], mode = args[4]; + uint8_t mode = args[4]; if (mode > 3) - shutdown("Invalid spi mode"); + shutdown("Invalid spi config"); - struct spi_software *spi = oid_alloc(oid, command_config_software_spi - , sizeof(*spi)); - - spi->sclk = gpio_out_setup(sclk_pin, 0); - spi->mosi = gpio_out_setup(mosi_pin, 0); - spi->miso = gpio_in_setup(miso_pin, 1); - spi->mode = mode; + struct spidev_s *spi = spidev_oid_lookup(args[0]); + struct spi_software *ss = alloc_chunk(sizeof(*ss)); + ss->miso = gpio_in_setup(args[1], 1); + ss->mosi = gpio_out_setup(args[2], 0); + ss->sclk = gpio_out_setup(args[3], 0); + ss->mode = mode; + spidev_set_software_bus(spi, ss); } -DECL_COMMAND(command_config_software_spi, - "config_software_spi oid=%c sclk_pin=%u mosi_pin=%u miso_pin=%u" +DECL_COMMAND(command_spi_set_software_bus, + "spi_set_software_bus oid=%c miso_pin=%u mosi_pin=%u sclk_pin=%u" " mode=%u rate=%u"); -struct spi_software * -spi_software_oid_lookup(uint8_t oid) -{ - return oid_lookup(oid, command_config_software_spi); -} - void spi_software_prepare(struct spi_software *ss) { diff --git a/src/spicmds.c b/src/spicmds.c index 527cb0af..654e9436 100644 --- a/src/spicmds.c +++ b/src/spicmds.c @@ -1,6 +1,6 @@ // Commands for sending messages on an SPI bus // -// Copyright (C) 2016-2018 Kevin O'Connor +// Copyright (C) 2016-2019 Kevin O'Connor // // This file may be distributed under the terms of the GNU GPLv3 license. @@ -20,69 +20,27 @@ struct spidev_s { }; struct gpio_out pin; uint8_t flags; - uint8_t shutdown_msg_len; - uint8_t shutdown_msg[]; }; enum { - SF_HAVE_PIN = 1, SF_SOFTWARE = 2, + SF_HAVE_PIN = 1, SF_SOFTWARE = 2, SF_HARDWARE = 4, }; void command_config_spi(uint32_t *args) { - uint8_t mode = args[3], shutdown_msg_len = args[5]; - if (mode > 3) - shutdown("Invalid spi mode"); - struct spidev_s *spi = oid_alloc(args[0], command_config_spi - , sizeof(*spi) + shutdown_msg_len); - spi->pin = gpio_out_setup(args[2], 1); - spi->flags = SF_HAVE_PIN; - spi->spi_config = spi_setup(args[1], mode, args[4]); - spi->shutdown_msg_len = shutdown_msg_len; - uint8_t *shutdown_msg = (void*)(size_t)args[6]; - memcpy(spi->shutdown_msg, shutdown_msg, shutdown_msg_len); + struct spidev_s *spi = oid_alloc(args[0], command_config_spi, sizeof(*spi)); + spi->pin = gpio_out_setup(args[1], 1); + spi->flags |= SF_HAVE_PIN; } -DECL_COMMAND(command_config_spi, - "config_spi oid=%c spi_bus=%u pin=%u mode=%u rate=%u" - " shutdown_msg=%*s"); +DECL_COMMAND(command_config_spi, "config_spi oid=%c pin=%u"); void command_config_spi_without_cs(uint32_t *args) { - uint8_t mode = args[2], shutdown_msg_len = args[4]; - if (mode > 3) - shutdown("Invalid spi mode"); - struct spidev_s *spi = oid_alloc(args[0], command_config_spi - , sizeof(*spi) + shutdown_msg_len); - spi->spi_config = spi_setup(args[1], mode, args[3]); - spi->shutdown_msg_len = shutdown_msg_len; - uint8_t *shutdown_msg = (void*)(size_t)args[5]; - memcpy(spi->shutdown_msg, shutdown_msg, shutdown_msg_len); + struct spidev_s *spi = oid_alloc(args[0], command_config_spi, sizeof(*spi)); } -DECL_COMMAND(command_config_spi_without_cs, - "config_spi_without_cs oid=%c spi_bus=%u mode=%u rate=%u" - " shutdown_msg=%*s"); - -void -command_config_spi_from_software(uint32_t *args) -{ - uint8_t shutdown_msg_len = args[3]; - struct spi_software *sspi = spi_software_oid_lookup(args[1]); - struct spidev_s *spi = oid_alloc(args[0], command_config_spi - , sizeof(*spi) + shutdown_msg_len); - spi->pin = gpio_out_setup(args[2], 1); - spi->flags = SF_HAVE_PIN | SF_SOFTWARE; - spi->spi_software = sspi; - spi->shutdown_msg_len = shutdown_msg_len; - uint8_t *shutdown_msg = (void*)(size_t)args[4]; - memcpy(spi->shutdown_msg, shutdown_msg, shutdown_msg_len); -} -#if CONFIG_HAVE_GPIO_BITBANGING -DECL_COMMAND(command_config_spi_from_software, - "config_spi_from_software oid=%c sw_oid=%u pin=%u" - " shutdown_msg=%*s"); -#endif +DECL_COMMAND(command_config_spi_without_cs, "config_spi_without_cs oid=%c"); struct spidev_s * spidev_oid_lookup(uint8_t oid) @@ -90,10 +48,36 @@ spidev_oid_lookup(uint8_t oid) return oid_lookup(oid, command_config_spi); } +void +command_spi_set_bus(uint32_t *args) +{ + struct spidev_s *spi = spidev_oid_lookup(args[0]); + uint8_t mode = args[2]; + if (mode > 3 || spi->flags & (SF_SOFTWARE|SF_HARDWARE)) + shutdown("Invalid spi config"); + spi->spi_config = spi_setup(args[1], mode, args[3]); + spi->flags |= SF_HARDWARE; +} +DECL_COMMAND(command_spi_set_bus, + "spi_set_bus oid=%c spi_bus=%u mode=%u rate=%u"); + +void +spidev_set_software_bus(struct spidev_s *spi, struct spi_software *ss) +{ + if (spi->flags & (SF_SOFTWARE|SF_HARDWARE)) + shutdown("Invalid spi config"); + spi->spi_software = ss; + spi->flags |= SF_SOFTWARE; +} + void spidev_transfer(struct spidev_s *spi, uint8_t receive_data , uint8_t data_len, uint8_t *data) { + if (!(spi->flags & (SF_SOFTWARE|SF_HARDWARE))) + // Not yet initialized + return; + if (CONFIG_HAVE_GPIO_BITBANGING && spi->flags & SF_SOFTWARE) spi_software_prepare(spi->spi_software); else @@ -115,7 +99,7 @@ void command_spi_transfer(uint32_t *args) { uint8_t oid = args[0]; - struct spidev_s *spi = oid_lookup(oid, command_config_spi); + struct spidev_s *spi = spidev_oid_lookup(oid); uint8_t data_len = args[1]; uint8_t *data = (void*)(size_t)args[2]; spidev_transfer(spi, 1, data_len, data); @@ -126,14 +110,39 @@ DECL_COMMAND(command_spi_transfer, "spi_transfer oid=%c data=%*s"); void command_spi_send(uint32_t *args) { - uint8_t oid = args[0]; - struct spidev_s *spi = oid_lookup(oid, command_config_spi); + struct spidev_s *spi = spidev_oid_lookup(args[0]); uint8_t data_len = args[1]; uint8_t *data = (void*)(size_t)args[2]; spidev_transfer(spi, 0, data_len, data); } DECL_COMMAND(command_spi_send, "spi_send oid=%c data=%*s"); + +/**************************************************************** + * Shutdown handling + ****************************************************************/ + +struct spidev_shutdown_s { + struct spidev_s *spi; + uint8_t shutdown_msg_len; + uint8_t shutdown_msg[]; +}; + +void +command_config_spi_shutdown(uint32_t *args) +{ + struct spidev_s *spi = spidev_oid_lookup(args[1]); + uint8_t shutdown_msg_len = args[2]; + struct spidev_shutdown_s *sd = oid_alloc( + args[0], command_config_spi_shutdown, sizeof(*sd) + shutdown_msg_len); + sd->spi = spi; + sd->shutdown_msg_len = shutdown_msg_len; + uint8_t *shutdown_msg = (void*)(size_t)args[3]; + memcpy(sd->shutdown_msg, shutdown_msg, shutdown_msg_len); +} +DECL_COMMAND(command_config_spi_shutdown, + "config_spi_shutdown oid=%c spi_oid=%c shutdown_msg=%*s"); + void spidev_shutdown(void) { @@ -146,9 +155,9 @@ spidev_shutdown(void) } // Send shutdown messages - foreach_oid(oid, spi, command_config_spi) { - if (spi->shutdown_msg_len) - spidev_transfer(spi, 0, spi->shutdown_msg_len, spi->shutdown_msg); + struct spidev_shutdown_s *sd; + foreach_oid(oid, sd, command_config_spi_shutdown) { + spidev_transfer(sd->spi, 0, sd->shutdown_msg_len, sd->shutdown_msg); } } DECL_SHUTDOWN(spidev_shutdown); diff --git a/src/spicmds.h b/src/spicmds.h index dee50665..959fddb9 100644 --- a/src/spicmds.h +++ b/src/spicmds.h @@ -4,7 +4,9 @@ #include // uint8_t struct spidev_s *spidev_oid_lookup(uint8_t oid); +struct spi_software; +void spidev_set_software_bus(struct spidev_s *spi, struct spi_software *ss); void spidev_transfer(struct spidev_s *spi, uint8_t receive_data , uint8_t data_len, uint8_t *data); -#endif // stepper.h +#endif // spicmds.h