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 <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-12-22 23:47:46 -05:00
parent 4e8674d5df
commit fe95ea221b
11 changed files with 54 additions and 37 deletions

View File

@ -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

View File

@ -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
--------------

View File

@ -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)

View File

@ -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()

View File

@ -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] <cmd section file> <autoconf.h> <output.c>"
usage = "%prog [options] <cmd section file> <output.c>"
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)

View File

@ -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)
{

View File

@ -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)

View File

@ -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) ({ \

View File

@ -6,10 +6,6 @@ config BOARD_DIRECTORY
string
default "sam3x8e"
config MCU
string
default "sam3x8e"
config CLOCK_FREQ
int
default 42000000 # 84000000/2

View File

@ -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)
{

View File

@ -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)