From abc76ee963d4154dce0bd56f2fdb946d5065cc86 Mon Sep 17 00:00:00 2001 From: Timofey Titovets Date: Thu, 13 Mar 2025 04:50:46 +0100 Subject: [PATCH] software_spi: set rate limiting ticks from the host Signed-off-by: Timofey Titovets --- klippy/extras/bus.py | 13 ++++++++++ scripts/spi_flash/spi_flash.py | 45 ++++++++++++++++++++++------------ src/spi_software.c | 15 +++++------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/klippy/extras/bus.py b/klippy/extras/bus.py index b8236dc7..ceeed732 100644 --- a/klippy/extras/bus.py +++ b/klippy/extras/bus.py @@ -43,6 +43,7 @@ class MCU_SPI: cs_active_high=False): self.mcu = mcu self.bus = bus + self.speed = speed # Config SPI object (set all CS pins high before spi_set_bus commands) self.oid = mcu.create_oid() if pin is None: @@ -51,11 +52,17 @@ class MCU_SPI: mcu.add_config_cmd("config_spi oid=%d pin=%s cs_active_high=%d" % (self.oid, pin, cs_active_high)) # Generate SPI bus config message + self.config_fmt_ticks = None if sw_pins is not None: self.config_fmt = ( "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)) + self.config_fmt_ticks = ( + "spi_set_sw_bus oid=%d" + " miso_pin=%s mosi_pin=%s sclk_pin=%s mode=%d pulse_ticks=%%d" + % (self.oid, sw_pins[0], sw_pins[1], + sw_pins[2], mode)) else: self.config_fmt = ( "spi_set_bus oid=%d spi_bus=%%s mode=%d rate=%d" @@ -78,6 +85,12 @@ class MCU_SPI: if '%' in self.config_fmt: bus = resolve_bus_name(self.mcu, "spi_bus", self.bus) self.config_fmt = self.config_fmt % (bus,) + if self.config_fmt_ticks: + if self.mcu.try_lookup_command("spi_set_sw_bus oid=%c miso_pin=%u " + "mosi_pin=%u sclk_pin=%u " + "mode=%u pulse_ticks=%u"): + pulse_ticks = self.mcu.seconds_to_clock(1./self.speed) + self.config_fmt = self.config_fmt_ticks % (pulse_ticks,) 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) diff --git a/scripts/spi_flash/spi_flash.py b/scripts/spi_flash/spi_flash.py index cbe769e5..6784487f 100644 --- a/scripts/spi_flash/spi_flash.py +++ b/scripts/spi_flash/spi_flash.py @@ -112,8 +112,12 @@ SPI_CFG_CMDS = ( "config_spi oid=%d pin=%s" # Original ) SPI_BUS_CMD = "spi_set_bus oid=%d spi_bus=%s mode=%d rate=%d" -SW_SPI_BUS_CMD = "spi_set_software_bus oid=%d " \ - "miso_pin=%s mosi_pin=%s sclk_pin=%s mode=%d rate=%d" +SW_SPI_BUS_CMDS = ( + "spi_set_sw_bus oid=%d miso_pin=%s mosi_pin=%s " + "sclk_pin=%s mode=%d pulse_ticks=%d", + "spi_set_software_bus oid=%d miso_pin=%s mosi_pin=%s " + "sclk_pin=%s mode=%d rate=%d", +) SPI_SEND_CMD = "spi_send oid=%c data=%*s" SPI_XFER_CMD = "spi_transfer oid=%c data=%*s" SPI_XFER_RESPONSE = "spi_transfer_response oid=%c response=%*s" @@ -1279,6 +1283,8 @@ class MCUConnection: 'spi_bus', self.enumerations.get('bus')) pin_enums = self.enumerations.get('pin') if bus == "swspi": + mcu_freq = self.clocksync.print_time_to_clock(1) + pulse_ticks = mcu_freq//SD_SPI_SPEED cfgpins = self.board_config['spi_pins'] pins = [p.strip().upper() for p in cfgpins.split(',') if p.strip()] pin_err_msg = "Invalid Software SPI Pins: %s" % (cfgpins,) @@ -1287,30 +1293,27 @@ class MCUConnection: for p in pins: if p not in pin_enums: raise SPIFlashError(pin_err_msg) - bus_cmd = SW_SPI_BUS_CMD % (SPI_OID, pins[0], pins[1], pins[2], - SPI_MODE, SD_SPI_SPEED) + bus_cmds = [ + SW_SPI_BUS_CMDS[0] % (SPI_OID, pins[0], pins[1], pins[2], + SPI_MODE, pulse_ticks), + SW_SPI_BUS_CMDS[1] % (SPI_OID, pins[0], pins[1], pins[2], + SPI_MODE, SD_SPI_SPEED) + ] else: if bus not in bus_enums: raise SPIFlashError("Invalid SPI Bus: %s" % (bus,)) - bus_cmd = SPI_BUS_CMD % (SPI_OID, bus, SPI_MODE, SD_SPI_SPEED) + bus_cmds = SPI_BUS_CMD % (SPI_OID, bus, SPI_MODE, SD_SPI_SPEED) if cs_pin not in pin_enums: raise SPIFlashError("Invalid CS Pin: %s" % (cs_pin,)) - cfg_cmds = [ALLOC_OIDS_CMD % (1,), bus_cmd] + cfg_cmds = [ALLOC_OIDS_CMD % (1,),] self._serial.send(cfg_cmds[0]) spi_cfg_cmds = [ SPI_CFG_CMDS[0] % (SPI_OID, cs_pin, False), SPI_CFG_CMDS[1] % (SPI_OID, cs_pin), ] - for cmd in spi_cfg_cmds: - try: - self._serial.send(cmd) - except self.proto_error: - if cmd == spi_cfg_cmds[-1]: - raise - else: - cfg_cmds.insert(1, cmd) - break - self._serial.send(bus_cmd) + cfg_cmds.append(self._try_send_command(spi_cfg_cmds)) + cfg_cmds.append(self._try_send_command(bus_cmds)) + self._try_send_command(cfg_cmds) config_crc = zlib.crc32('\n'.join(cfg_cmds).encode()) & 0xffffffff self._serial.send(FINALIZE_CFG_CMD % (config_crc,)) config = self.get_mcu_config() @@ -1326,6 +1329,16 @@ class MCUConnection: raise SPIFlashError( "Failed to Initialize SD Card. Is it inserted?") + def _try_send_command(self, cmd_list): + for cmd in cmd_list: + try: + self._serial.send(cmd) + except self.proto_error: + if cmd == cmd_list[-1]: + raise + else: + return cmd + def _configure_mcu_sdiobus(self, printfunc=logging.info): bus = self.board_config['sdio_bus'] bus_enums = self.enumerations.get( diff --git a/src/spi_software.c b/src/spi_software.c index 4d5e7d97..73cd8788 100644 --- a/src/spi_software.c +++ b/src/spi_software.c @@ -20,11 +20,10 @@ struct spi_software { }; void -command_spi_set_software_bus(uint32_t *args) +command_spi_set_sw_bus(uint32_t *args) { uint8_t mode = args[4]; - uint32_t rate = args[5]; - uint8_t div = 0; + uint32_t pulse_ticks = args[5]; if (mode > 3) shutdown("Invalid spi config"); @@ -34,14 +33,12 @@ command_spi_set_software_bus(uint32_t *args) ss->mosi = gpio_out_setup(args[2], 0); ss->sclk = gpio_out_setup(args[3], 0); ss->mode = mode; - while (((CONFIG_CLOCK_FREQ/2) >> div) > rate) - div++; - ss->sck_ticks = 1 << div; + ss->sck_ticks = pulse_ticks; spidev_set_software_bus(spi, ss); } -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"); +DECL_COMMAND(command_spi_set_sw_bus, + "spi_set_sw_bus oid=%c miso_pin=%u mosi_pin=%u sclk_pin=%u" + " mode=%u pulse_ticks=%u"); void spi_software_prepare(struct spi_software *ss)