mirror of
https://github.com/andreili/katapult.git
synced 2025-08-23 19:34:06 +02:00
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 <kevin@koconnor.net>
This commit is contained in:
parent
1ae63dfbd8
commit
24d4eb16c9
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
# Script to handle build time requests embedded in C code.
|
# Script to handle build time requests embedded in C code.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2021 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import sys, optparse, logging
|
import sys, optparse, logging
|
||||||
@ -11,7 +11,9 @@ FILEHEADER = """
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "board/irq.h"
|
#include "board/irq.h"
|
||||||
|
#include "board/pgm.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
#include "initial_pins.h"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def error(msg):
|
def error(msg):
|
||||||
@ -98,7 +100,6 @@ class HandleEnumerations:
|
|||||||
def generate_code(self, options):
|
def generate_code(self, options):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
HandlerEnumerations = HandleEnumerations()
|
HandlerEnumerations = HandleEnumerations()
|
||||||
Handlers.append(HandlerEnumerations)
|
Handlers.append(HandlerEnumerations)
|
||||||
|
|
||||||
@ -136,13 +137,63 @@ class HandleConstants:
|
|||||||
rpins = [v.strip() for v in val.split(',') if v.strip()]
|
rpins = [v.strip() for v in val.split(',') if v.strip()]
|
||||||
reserved_pins.extend(rpins)
|
reserved_pins.extend(rpins)
|
||||||
return reserved_pins
|
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):
|
def generate_code(self, options):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
HandlerConstants = HandleConstants()
|
HandlerConstants = HandleConstants()
|
||||||
Handlers.append(HandlerConstants)
|
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
|
# ARM IRQ vector table generation
|
||||||
######################################################################
|
######################################################################
|
||||||
@ -182,9 +233,9 @@ const void *VectorTable[] __visible __section(".vector_table") = {
|
|||||||
"""
|
"""
|
||||||
return fmt % (''.join(defs), ''.join(table))
|
return fmt % (''.join(defs), ''.join(table))
|
||||||
|
|
||||||
|
|
||||||
Handlers.append(Handle_arm_irq())
|
Handlers.append(Handle_arm_irq())
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Status LED Functionality
|
# Status LED Functionality
|
||||||
######################################################################
|
######################################################################
|
||||||
@ -206,21 +257,15 @@ class HandleStatusLED:
|
|||||||
if pin[0] == "!":
|
if pin[0] == "!":
|
||||||
led_gpio_high = 0
|
led_gpio_high = 0
|
||||||
pin = pin[1:].strip()
|
pin = pin[1:].strip()
|
||||||
avail_pins = HandlerEnumerations.get_available_pins()
|
led_gpio = HandlerConstants.lookup_pin(pin)
|
||||||
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)
|
|
||||||
fmt = """
|
fmt = """
|
||||||
uint32_t led_gpio = %d, led_gpio_high = %d; // "%s"
|
uint32_t led_gpio = %d, led_gpio_high = %d; // "%s"
|
||||||
"""
|
"""
|
||||||
return fmt % (led_gpio, led_gpio_high, self.pin)
|
return fmt % (led_gpio, led_gpio_high, self.pin)
|
||||||
|
|
||||||
|
|
||||||
Handlers.append(HandleStatusLED())
|
Handlers.append(HandleStatusLED())
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Button entry functionality
|
# Button entry functionality
|
||||||
######################################################################
|
######################################################################
|
||||||
@ -247,21 +292,15 @@ class HandleButton:
|
|||||||
if pin[0] == "!":
|
if pin[0] == "!":
|
||||||
button_high = 0
|
button_high = 0
|
||||||
pin = pin[1:].strip()
|
pin = pin[1:].strip()
|
||||||
avail_pins = HandlerEnumerations.get_available_pins()
|
button_gpio = HandlerConstants.lookup_pin(pin)
|
||||||
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)
|
|
||||||
fmt = """
|
fmt = """
|
||||||
int32_t button_gpio = %d, button_high = %d, button_pullup = %d; // "%s"
|
int32_t button_gpio = %d, button_high = %d, button_pullup = %d; // "%s"
|
||||||
"""
|
"""
|
||||||
return fmt % (button_gpio, button_high, button_pullup, self.pin)
|
return fmt % (button_gpio, button_high, button_pullup, self.pin)
|
||||||
|
|
||||||
|
|
||||||
Handlers.append(HandleButton())
|
Handlers.append(HandleButton())
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Main code
|
# Main code
|
||||||
######################################################################
|
######################################################################
|
||||||
@ -271,6 +310,7 @@ def main():
|
|||||||
opts = optparse.OptionParser(usage)
|
opts = optparse.OptionParser(usage)
|
||||||
opts.add_option("-v", action="store_true", dest="verbose",
|
opts.add_option("-v", action="store_true", dest="verbose",
|
||||||
help="enable debug messages")
|
help="enable debug messages")
|
||||||
|
|
||||||
options, args = opts.parse_args()
|
options, args = opts.parse_args()
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
opts.error("Incorrect arguments")
|
opts.error("Incorrect arguments")
|
||||||
@ -280,7 +320,7 @@ def main():
|
|||||||
|
|
||||||
# Parse request file
|
# Parse request file
|
||||||
ctr_dispatch = { k: v for h in Handlers for k, v in h.ctr_dispatch.items() }
|
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()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
for req in data.split('\n'):
|
for req in data.split('\n'):
|
||||||
@ -294,7 +334,7 @@ def main():
|
|||||||
|
|
||||||
# Write output
|
# Write output
|
||||||
code = "".join([FILEHEADER] + [h.generate_code(options) for h in Handlers])
|
code = "".join([FILEHEADER] + [h.generate_code(options) for h in Handlers])
|
||||||
f = open(outcfile, 'wb')
|
f = open(outcfile, 'w')
|
||||||
f.write(code)
|
f.write(code)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
11
src/Kconfig
11
src/Kconfig
@ -44,6 +44,17 @@ config USB_SERIAL_NUMBER
|
|||||||
string "USB serial number" if !USB_SERIAL_NUMBER_CHIPID
|
string "USB serial number" if !USB_SERIAL_NUMBER_CHIPID
|
||||||
endmenu
|
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
|
config ENABLE_DOUBLE_RESET
|
||||||
bool "Support bootloader entry on rapid double click of reset button"
|
bool "Support bootloader entry on rapid double click of reset button"
|
||||||
default y
|
default y
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Main code build rules
|
# 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
|
src-$(CONFIG_ENABLE_LED) += led.c
|
||||||
|
25
src/initial_pins.c
Normal file
25
src/initial_pins.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Support setting gpio pins at mcu start
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
||||||
|
//
|
||||||
|
// 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; i<initial_pins_size; i++) {
|
||||||
|
const struct initial_pin_s *ip = &initial_pins[i];
|
||||||
|
gpio_out_setup(READP(ip->pin), READP(ip->flags) & IP_OUT_HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DECL_INIT(initial_pins_setup);
|
15
src/initial_pins.h
Normal file
15
src/initial_pins.h
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user