From fe95ea221b2b88e9cb52a6378ff2018ee752094b Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Thu, 22 Dec 2016 23:47:46 -0500 Subject: [PATCH] build: Define DECL_CONSTANT mechanism for defining exported constants Add a DECL_CONSTANT macro to allow the firmware to define constants that are to be exported to the host during the "identify" phase. This replaces the existing hardcoded mechanism of scanning the Kconfig header file for certain constants. Signed-off-by: Kevin O'Connor --- Makefile | 2 +- docs/Protocol.md | 17 ++++++++++++++-- klippy/console.py | 2 +- klippy/serialhdl.py | 2 +- scripts/buildcommands.py | 43 ++++++++++++++-------------------------- src/avr/serial.c | 3 +++ src/avr/timer.c | 3 +++ src/command.h | 9 +++++++++ src/sam3x8e/Kconfig | 4 ---- src/sam3x8e/serial.c | 3 +++ src/sam3x8e/timer.c | 3 +++ 11 files changed, 54 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index b006d967..14b0c20e 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ $(OUT)klipper.o: $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)declfunc.lds $(OUT)compile_time_request.o: $(OUT)klipper.o ./scripts/buildcommands.py @echo " Building $@" $(Q)$(OBJCOPY) -j '.compile_time_request' -O binary $< $(OUT)klipper.o.compile_time_request - $(Q)$(PYTHON) ./scripts/buildcommands.py -d $(OUT)klipper.dict $(OUT)klipper.o.compile_time_request $(OUT)autoconf.h $(OUT)compile_time_request.c + $(Q)$(PYTHON) ./scripts/buildcommands.py -d $(OUT)klipper.dict $(OUT)klipper.o.compile_time_request $(OUT)compile_time_request.c $(Q)$(CC) $(CFLAGS) -c $(OUT)compile_time_request.c -o $@ $(OUT)klipper.elf: $(OUT)klipper.o $(OUT)compile_time_request.o diff --git a/docs/Protocol.md b/docs/Protocol.md index 12d5e1ce..bd11400f 100644 --- a/docs/Protocol.md +++ b/docs/Protocol.md @@ -109,6 +109,19 @@ to generate and format arbitrary messages for human consumption. It is a wrapper around sendf() and as with sendf() it should not be called from interrupts or timers. +Declaring constants +------------------- + +The firmware can also define constants to be exported. For example, +the following: + +``` +DECL_CONSTANT(SERIAL_BAUD, 250000); +``` + +would export a constant named "SERIAL_BAUD" with a value of 250000 +from the firmware to the host. + Low-level message encoding ========================== @@ -262,8 +275,8 @@ dictionary. Once all chunks are obtained the host will assemble the chunks, uncompress the data, and parse the contents. In addition to information on the communication protocol, the data -dictionary also contains firmware version, configuration, and other -useful information. +dictionary also contains firmware version, constants (as defined by +DECL_CONSTANT), and static strings. Static Strings -------------- diff --git a/klippy/console.py b/klippy/console.py index 94476007..1dd99ca9 100755 --- a/klippy/console.py +++ b/klippy/console.py @@ -27,7 +27,7 @@ class KeyboardReader: self.reactor.unregister_timer(self.connect_timer) return self.reactor.NEVER def update_evals(self, eventtime): - f = self.ser.msgparser.config.get('CLOCK_FREQ', 1) + f = int(self.ser.msgparser.config.get('CLOCK_FREQ', 1)) c = self.ser.get_clock(eventtime) self.eval_globals['freq'] = f self.eval_globals['clock'] = int(c) diff --git a/klippy/serialhdl.py b/klippy/serialhdl.py index 2a539cf1..2e4bc467 100644 --- a/klippy/serialhdl.py +++ b/klippy/serialhdl.py @@ -101,7 +101,7 @@ class SerialReader: self.msgparser.process_identify(dictionary, decompress=False) est_clock = 1000000000000. if pace: - est_clock = self.msgparser.config['CLOCK_FREQ'] + est_clock = float(self.msgparser.config['CLOCK_FREQ']) self.serialqueue = self.ffi_lib.serialqueue_alloc(self.ser.fileno(), 1) self.est_clock = est_clock self.last_ack_time = time.time() diff --git a/scripts/buildcommands.py b/scripts/buildcommands.py index 9b6acb45..c0584d15 100644 --- a/scripts/buildcommands.py +++ b/scripts/buildcommands.py @@ -21,25 +21,6 @@ def error(msg): sys.stderr.write(msg + "\n") sys.exit(-1) -# Parser for constants in simple C header files. -def scan_config(file): - f = open(file, 'r') - opts = {} - for l in f.readlines(): - parts = l.split() - if len(parts) != 3: - continue - if parts[0] != '#define': - continue - value = parts[2] - if value.isdigit() or (value.startswith('0x') and value[2:].isdigit()): - value = int(value, 0) - elif value.startswith('"'): - value = value[1:-1] - opts[parts[1]] = value - f.close() - return opts - ###################################################################### # Command and output parser generation @@ -145,7 +126,7 @@ const uint8_t command_index_size PROGMEM = ARRAY_SIZE(command_index); ###################################################################### def build_identify(cmd_by_id, msg_to_id, responses, static_strings - , config, version): + , constants, version): #commands, messages, static_strings messages = dict((msgid, msg) for msg, msgid in msg_to_id.items()) data = {} @@ -153,9 +134,7 @@ def build_identify(cmd_by_id, msg_to_id, responses, static_strings data['commands'] = sorted(cmd_by_id.keys()) data['responses'] = sorted(responses) data['static_strings'] = static_strings - configlist = ['MCU', 'CLOCK_FREQ', 'SERIAL_BAUD'] - data['config'] = dict((i, config['CONFIG_'+i]) for i in configlist - if 'CONFIG_'+i in config) + data['config'] = constants data['version'] = version # Format compressed info into C code @@ -223,7 +202,7 @@ def build_version(extra): ###################################################################### def main(): - usage = "%prog [options] " + usage = "%prog [options] " opts = optparse.OptionParser(usage) opts.add_option("-e", "--extra", dest="extra", default="", help="extra version string to append to version") @@ -233,9 +212,9 @@ def main(): help="enable debug messages") options, args = opts.parse_args() - if len(args) != 3: + if len(args) != 2: opts.error("Incorrect arguments") - incmdfile, inheader, outcfile = args + incmdfile, outcfile = args if options.verbose: logging.basicConfig(level=logging.DEBUG) @@ -245,6 +224,7 @@ def main(): for m in msgproto.DefaultMessages.values()) parsers = [] static_strings = [] + constants = {} # Parse request file f = open(incmdfile, 'rb') data = f.read() @@ -280,6 +260,14 @@ def main(): parsers.append((None, msg)) elif cmd == '_DECL_STATIC_STR': static_strings.append(req[17:]) + elif cmd == '_DECL_CONSTANT': + name, value = parts[1:] + value = value.strip() + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] + if name in constants and constants[name] != value: + error("Conflicting definition for constant '%s'" % name) + constants[name] = value else: error("Unknown build time command '%s'" % cmd) # Create unique ids for each message type @@ -299,13 +287,12 @@ def main(): cmdcode = build_commands(cmd_by_id, messages_by_name, all_param_types) paramcode = build_param_types(all_param_types) # Create identify information - config = scan_config(inheader) version = build_version(options.extra) sys.stdout.write("Version: %s\n" % (version,)) responses = [msg_to_id[msg] for msgname, msg in messages_by_name.items() if msgname not in commands] datadict, icode = build_identify(cmd_by_id, msg_to_id, responses - , static_strings, config, version) + , static_strings, constants, version) # Write output f = open(outcfile, 'wb') f.write(FILEHEADER + paramcode + parsercode + cmdcode + icode) diff --git a/src/avr/serial.c b/src/avr/serial.c index bd92f048..6bd88598 100644 --- a/src/avr/serial.c +++ b/src/avr/serial.c @@ -9,6 +9,7 @@ #include "autoconf.h" // CONFIG_SERIAL_BAUD #include "board/io.h" // readb #include "board/misc.h" // console_get_input +#include "command.h" // DECL_CONSTANT #include "sched.h" // DECL_INIT #include "irq.h" // irq_save @@ -22,6 +23,8 @@ static uint8_t transmit_pos, transmit_max; * Serial hardware ****************************************************************/ +DECL_CONSTANT(SERIAL_BAUD, CONFIG_SERIAL_BAUD); + static void serial_init(void) { diff --git a/src/avr/timer.c b/src/avr/timer.c index a7e832bc..3744351d 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -16,6 +16,9 @@ * Low level timer code ****************************************************************/ +DECL_CONSTANT(CLOCK_FREQ, F_CPU); +DECL_CONSTANT(MCU, CONFIG_MCU); + // Return the number of clock ticks for a given number of microseconds uint32_t timer_from_us(uint32_t us) diff --git a/src/command.h b/src/command.h index 2bbe37f8..c6d8a69c 100644 --- a/src/command.h +++ b/src/command.h @@ -15,6 +15,10 @@ // Flags for command handler declarations. #define HF_IN_SHUTDOWN 0x01 // Handler can run even when in emergency stop +// Declare a constant exported to the host +#define DECL_CONSTANT(NAME, VALUE) \ + _DECL_CONSTANT(NAME, VALUE) + // Send an output message (and declare a static message type for it) #define output(FMT, args...) \ _sendf(_DECL_OUTPUT(FMT) , ##args ) @@ -59,6 +63,11 @@ extern const uint32_t command_identify_size; = "_DECL_COMMAND " __stringify(FUNC) " " __stringify(FLAGS) " " MSG; \ void __visible FUNC(uint32_t*) +#define _DECL_CONSTANT(NAME, VALUE) \ + char __PASTE(_DECLC_ ## NAME ## _, __LINE__) [] \ + __visible __section(".compile_time_request") \ + = "_DECL_CONSTANT " __stringify(NAME) " " __stringify(VALUE) + // Create a compile time request and return a unique (incrementing id) // for that request. #define _DECL_REQUEST_ID(REQUEST, ID_SECTION) ({ \ diff --git a/src/sam3x8e/Kconfig b/src/sam3x8e/Kconfig index 2edc8f7c..00e1f06e 100644 --- a/src/sam3x8e/Kconfig +++ b/src/sam3x8e/Kconfig @@ -6,10 +6,6 @@ config BOARD_DIRECTORY string default "sam3x8e" -config MCU - string - default "sam3x8e" - config CLOCK_FREQ int default 42000000 # 84000000/2 diff --git a/src/sam3x8e/serial.c b/src/sam3x8e/serial.c index 42b92efe..d07fc734 100644 --- a/src/sam3x8e/serial.c +++ b/src/sam3x8e/serial.c @@ -9,6 +9,7 @@ #include "board/gpio.h" // gpio_peripheral #include "board/io.h" // readb #include "board/misc.h" // console_get_input +#include "command.h" // DECL_CONSTANT #include "sam3x8e.h" // UART #include "sched.h" // DECL_INIT #include "irq.h" // irq_save @@ -24,6 +25,8 @@ static uint32_t transmit_pos, transmit_max; * Serial hardware ****************************************************************/ +DECL_CONSTANT(SERIAL_BAUD, CONFIG_SERIAL_BAUD); + static void serial_init(void) { diff --git a/src/sam3x8e/timer.c b/src/sam3x8e/timer.c index ead9c90f..0d3728ed 100644 --- a/src/sam3x8e/timer.c +++ b/src/sam3x8e/timer.c @@ -16,6 +16,9 @@ * Low level timer code ****************************************************************/ +DECL_CONSTANT(CLOCK_FREQ, CONFIG_CLOCK_FREQ); +DECL_CONSTANT(MCU, "sam3x8e"); + // Return the number of clock ticks for a given number of microseconds uint32_t timer_from_us(uint32_t us)