From 24d4eb16c9a63f1e88c73fcb74ce9e5026c0948a Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Mon, 16 May 2022 09:28:00 -0400 Subject: [PATCH] initial_pins: Port initial_pins capability from Klipper Some boards require an initial gpio state in order to start USB. Port the initial_pins capability from Klipper to provide that support. This also synchronizes scripts/buildcommands.py with the latest code from Klipper. Signed-off-by: Kevin O'Connor --- scripts/buildcommands.py | 84 +++++++++++++++++++++++++++++----------- src/Kconfig | 11 ++++++ src/Makefile | 2 +- src/initial_pins.c | 25 ++++++++++++ src/initial_pins.h | 15 +++++++ 5 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 src/initial_pins.c create mode 100644 src/initial_pins.h diff --git a/scripts/buildcommands.py b/scripts/buildcommands.py index 2a44843..1c56d7f 100644 --- a/scripts/buildcommands.py +++ b/scripts/buildcommands.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # Script to handle build time requests embedded in C code. # -# Copyright (C) 2016-2018 Kevin O'Connor +# Copyright (C) 2016-2021 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. import sys, optparse, logging @@ -11,7 +11,9 @@ FILEHEADER = """ #include #include "board/irq.h" +#include "board/pgm.h" #include "compiler.h" +#include "initial_pins.h" """ def error(msg): @@ -98,7 +100,6 @@ class HandleEnumerations: def generate_code(self, options): return "" - HandlerEnumerations = HandleEnumerations() Handlers.append(HandlerEnumerations) @@ -136,13 +137,63 @@ class HandleConstants: rpins = [v.strip() for v in val.split(',') if v.strip()] reserved_pins.extend(rpins) return reserved_pins + def lookup_pin(self, pin): + avail_pins = HandlerEnumerations.get_available_pins() + gpio = avail_pins.get(pin) + if gpio is None: + error("Pin %s is not available for this build" % (pin,)) + reserved_pins = self.get_reserved_pins() + if pin in reserved_pins: + error("Pin %s is reserved by an active MCU peripheral" % (pin,)) + return gpio def generate_code(self, options): return "" - HandlerConstants = HandleConstants() Handlers.append(HandlerConstants) + +###################################################################### +# Initial pins +###################################################################### + +class HandleInitialPins: + def __init__(self): + self.initial_pins = [] + self.ctr_dispatch = { 'DECL_INITIAL_PINS': self.decl_initial_pins } + def decl_initial_pins(self, req): + pins = req.split(None, 1)[1].strip() + if pins.startswith('"') and pins.endswith('"'): + pins = pins[1:-1] + if pins: + self.initial_pins = [p.strip() for p in pins.split(',')] + HandlerConstants.decl_constant_str( + "_DECL_CONSTANT_STR INITIAL_PINS " + + ','.join(self.initial_pins)) + def map_pins(self): + if not self.initial_pins: + return [] + out = [] + for p in self.initial_pins: + flag = "IP_OUT_HIGH" + if p.startswith('!'): + flag = "0" + p = p[1:].strip() + gpio = HandlerConstants.lookup_pin(p) + out.append("\n {%d, %s}, // %s" % (gpio, flag, p)) + return out + def generate_code(self, options): + out = self.map_pins() + fmt = """ +const struct initial_pin_s initial_pins[] PROGMEM = {%s +}; +const int initial_pins_size PROGMEM = ARRAY_SIZE(initial_pins); +""" + return fmt % (''.join(out),) + +Handlers.append(HandleInitialPins()) + + ###################################################################### # ARM IRQ vector table generation ###################################################################### @@ -182,9 +233,9 @@ const void *VectorTable[] __visible __section(".vector_table") = { """ return fmt % (''.join(defs), ''.join(table)) - Handlers.append(Handle_arm_irq()) + ###################################################################### # Status LED Functionality ###################################################################### @@ -206,21 +257,15 @@ class HandleStatusLED: if pin[0] == "!": led_gpio_high = 0 pin = pin[1:].strip() - avail_pins = HandlerEnumerations.get_available_pins() - reserved_pins = HandlerConstants.get_reserved_pins() - led_gpio = avail_pins.get(pin) - if led_gpio is None: - error("Pin %s is not available for this build" % pin) - if pin in reserved_pins: - error("Pin %s is reserved by an active MCU peripheral" % pin) + led_gpio = HandlerConstants.lookup_pin(pin) fmt = """ uint32_t led_gpio = %d, led_gpio_high = %d; // "%s" """ return fmt % (led_gpio, led_gpio_high, self.pin) - Handlers.append(HandleStatusLED()) + ###################################################################### # Button entry functionality ###################################################################### @@ -247,21 +292,15 @@ class HandleButton: if pin[0] == "!": button_high = 0 pin = pin[1:].strip() - avail_pins = HandlerEnumerations.get_available_pins() - reserved_pins = HandlerConstants.get_reserved_pins() - button_gpio = avail_pins.get(pin) - if button_gpio is None: - error("Pin %s is not available for this build" % pin) - if pin in reserved_pins: - error("Pin %s is reserved by an active MCU peripheral" % pin) + button_gpio = HandlerConstants.lookup_pin(pin) fmt = """ int32_t button_gpio = %d, button_high = %d, button_pullup = %d; // "%s" """ return fmt % (button_gpio, button_high, button_pullup, self.pin) - Handlers.append(HandleButton()) + ###################################################################### # Main code ###################################################################### @@ -271,6 +310,7 @@ def main(): opts = optparse.OptionParser(usage) opts.add_option("-v", action="store_true", dest="verbose", help="enable debug messages") + options, args = opts.parse_args() if len(args) != 2: opts.error("Incorrect arguments") @@ -280,7 +320,7 @@ def main(): # Parse request file ctr_dispatch = { k: v for h in Handlers for k, v in h.ctr_dispatch.items() } - f = open(incmdfile, 'rb') + f = open(incmdfile, 'r') data = f.read() f.close() for req in data.split('\n'): @@ -294,7 +334,7 @@ def main(): # Write output code = "".join([FILEHEADER] + [h.generate_code(options) for h in Handlers]) - f = open(outcfile, 'wb') + f = open(outcfile, 'w') f.write(code) f.close() diff --git a/src/Kconfig b/src/Kconfig index fd7ee11..b5b5b2c 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -44,6 +44,17 @@ config USB_SERIAL_NUMBER string "USB serial number" if !USB_SERIAL_NUMBER_CHIPID endmenu +config INITIAL_PINS + string "GPIO pins to set on bootloader entry" + depends on LOW_LEVEL_OPTIONS + help + One may specify a comma separated list of gpio pins to set + during bootloader entry (these gpio pins are not set if the + main application is started nor are they set while checking + for a bootloader request). By default the pins will be set to + output high - preface a pin with a '!' character to set that + pin to output low. + config ENABLE_DOUBLE_RESET bool "Support bootloader entry on rapid double click of reset button" default y diff --git a/src/Makefile b/src/Makefile index 78c5711..f7ccb56 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ # Main code build rules -src-y += sched.c bootentry.c command.c flashcmd.c +src-y += sched.c bootentry.c command.c flashcmd.c initial_pins.c src-$(CONFIG_ENABLE_LED) += led.c diff --git a/src/initial_pins.c b/src/initial_pins.c new file mode 100644 index 0000000..cd47850 --- /dev/null +++ b/src/initial_pins.c @@ -0,0 +1,25 @@ +// Support setting gpio pins at mcu start +// +// Copyright (C) 2019 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_INITIAL_PINS +#include "board/gpio.h" // gpio_out_setup +#include "board/pgm.h" // READP +#include "ctr.h" // DECL_CTR +#include "initial_pins.h" // initial_pins +#include "sched.h" // DECL_INIT + +DECL_CTR("DECL_INITIAL_PINS " __stringify(CONFIG_INITIAL_PINS)); + +void +initial_pins_setup(void) +{ + int i; + for (i=0; ipin), READP(ip->flags) & IP_OUT_HIGH); + } +} +DECL_INIT(initial_pins_setup); diff --git a/src/initial_pins.h b/src/initial_pins.h new file mode 100644 index 0000000..95bb292 --- /dev/null +++ b/src/initial_pins.h @@ -0,0 +1,15 @@ +#ifndef __INITIAl_PINS_H +#define __INITIAl_PINS_H + +struct initial_pin_s { + int pin; + uint8_t flags; +}; + +enum { IP_OUT_HIGH = 1 }; + +// out/compile_time_request.c (auto generated file) +extern const struct initial_pin_s initial_pins[]; +extern const int initial_pins_size; + +#endif // initial_pins.h