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)