aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile21
-rw-r--r--scripts/buildcommands.py84
-rw-r--r--src/command.c13
-rw-r--r--src/command.h51
-rw-r--r--src/ctr.h17
-rw-r--r--src/declfunc.lds.S7
6 files changed, 120 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index be5d3774..39535898 100644
--- a/Makefile
+++ b/Makefile
@@ -75,21 +75,24 @@ $(OUT)board-link: $(KCONFIG_CONFIG)
$(Q)mkdir -p $(OUT)board-generic
$(Q)ln -Tsf $(PWD)/src/generic $(OUT)board-generic/board
+$(OUT)%.o.ctr: $(OUT)%.o
+ $(Q)$(OBJCOPY) -j '.compile_time_request' -O binary $^ $@
+
+$(OUT)compile_time_request.o: $(patsubst %.c, $(OUT)src/%.o.ctr,$(src-y)) ./scripts/buildcommands.py
+ @echo " Building $@"
+ $(Q)cat $(patsubst %.c, $(OUT)src/%.o.ctr,$(src-y)) > $(OUT)klipper.compile_time_request
+ $(Q)$(PYTHON) ./scripts/buildcommands.py -d $(OUT)klipper.dict $(OUT)klipper.compile_time_request $(OUT)compile_time_request.c
+ $(Q)$(CC) $(CFLAGS) -c $(OUT)compile_time_request.c -o $@
+
$(OUT)declfunc.lds: src/declfunc.lds.S
@echo " Precompiling $@"
$(Q)$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $@
-$(OUT)klipper.o: $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)declfunc.lds
+$(OUT)klipper.o: $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)compile_time_request.o $(OUT)declfunc.lds
@echo " Linking $@"
- $(Q)$(CC) $(CFLAGS_klipper.o) -Wl,-T,$(OUT)declfunc.lds $(patsubst %.c, $(OUT)src/%.o,$(src-y)) -o $@
-
-$(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)compile_time_request.c
- $(Q)$(CC) $(CFLAGS) -c $(OUT)compile_time_request.c -o $@
+ $(Q)$(CC) $(CFLAGS_klipper.o) -Wl,-T,$(OUT)declfunc.lds $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)compile_time_request.o -o $@
-$(OUT)klipper.elf: $(OUT)klipper.o $(OUT)compile_time_request.o
+$(OUT)klipper.elf: $(OUT)klipper.o
@echo " Linking $@"
$(Q)$(CC) $(CFLAGS_klipper.elf) $^ -o $@
diff --git a/scripts/buildcommands.py b/scripts/buildcommands.py
index a831f52b..54a01caa 100644
--- a/scripts/buildcommands.py
+++ b/scripts/buildcommands.py
@@ -58,22 +58,66 @@ def build_parser(parser, iscmd, all_param_types):
out += " .max_size=%d," % (max_size,)
return out
-def build_parsers(parsers, msg_to_id, all_param_types):
- pcode = []
- for msgname, msg in parsers:
+def build_encoders(encoders, msg_to_id, all_param_types):
+ encoder_defs = []
+ output_code = []
+ encoder_code = []
+ did_output = {}
+ for msgname, msg in encoders:
msgid = msg_to_id[msg]
+ if msgid in did_output:
+ continue
+ s = msg
+ if s == '#empty':
+ s = ''
+ did_output[msgid] = True
+ code = (' if (__builtin_strcmp(str, "%s") == 0)\n'
+ ' return &command_encoder_%s;\n' % (s, msgid))
if msgname is None:
parser = msgproto.OutputFormat(msgid, msg)
+ output_code.append(code)
else:
parser = msgproto.MessageFormat(msgid, msg)
+ encoder_code.append(code)
parsercode = build_parser(parser, 0, all_param_types)
- pcode.append("{%s\n}, " % (parsercode,))
+ encoder_defs.append(
+ "const struct command_encoder command_encoder_%s PROGMEM = {"
+ " %s\n};\n" % (
+ msgid, parsercode))
fmt = """
-const struct command_encoder command_encoders[] PROGMEM __visible = {
%s
-};
+
+const __always_inline struct command_encoder *
+ctr_lookup_encoder(const char *str)
+{
+ %s
+ return NULL;
+}
+
+const __always_inline struct command_encoder *
+ctr_lookup_output(const char *str)
+{
+ %s
+ return NULL;
+}
"""
- return fmt % ("".join(pcode).strip(),)
+ return fmt % ("".join(encoder_defs).strip(), "".join(encoder_code).strip(),
+ "".join(output_code).strip())
+
+def build_static_strings(static_strings):
+ code = []
+ for i, s in enumerate(static_strings):
+ code.append(' if (__builtin_strcmp(str, "%s") == 0)\n'
+ ' return %d;\n' % (s, i))
+ fmt = """
+uint8_t __always_inline
+ctr_lookup_static_string(const char *str)
+{
+ %s
+ return 0xff;
+}
+"""
+ return fmt % ("".join(code).strip(),)
def build_param_types(all_param_types):
sorted_param_types = sorted([(i, a) for a, i in all_param_types.items()])
@@ -102,7 +146,7 @@ def build_commands(cmd_by_id, messages_by_name, all_param_types):
index.append(" &%s," % (parsername,))
parser = msgproto.MessageFormat(msgid, msg)
parsercode = build_parser(parser, 1, all_param_types)
- parsers.append("const struct command_parser %s PROGMEM __visible = {"
+ parsers.append("const struct command_parser %s PROGMEM = {"
" %s\n .flags=%s,\n .func=%s\n};" % (
parsername, parsercode, flags, funcname))
index = "\n".join(index)
@@ -113,11 +157,11 @@ def build_commands(cmd_by_id, messages_by_name, all_param_types):
%s
-const struct command_parser * const command_index[] PROGMEM __visible = {
+const struct command_parser * const command_index[] PROGMEM = {
%s
};
-const uint8_t command_index_size PROGMEM __visible = ARRAY_SIZE(command_index);
+const uint8_t command_index_size PROGMEM = ARRAY_SIZE(command_index);
"""
return fmt % (externs, '\n'.join(parsers), index)
@@ -147,11 +191,11 @@ def build_identify(cmd_by_id, msg_to_id, responses, static_strings
out.append('\n ')
out.append(" 0x%02x," % (ord(zdata[i]),))
fmt = """
-const uint8_t command_identify_data[] PROGMEM __visible = {%s
+const uint8_t command_identify_data[] PROGMEM = {%s
};
// Identify size = %d (%d uncompressed)
-const uint32_t command_identify_size PROGMEM __visible
+const uint32_t command_identify_size PROGMEM
= ARRAY_SIZE(command_identify_data);
"""
return data, fmt % (''.join(out), len(zdata), len(data))
@@ -224,7 +268,7 @@ def main():
commands = {}
messages_by_name = dict((m.split()[0], m)
for m in msgproto.DefaultMessages.values())
- parsers = []
+ encoders = []
static_strings = []
constants = {}
# Parse request file
@@ -248,7 +292,7 @@ def main():
if m is not None and m != msg:
error("Conflicting definition for command '%s'" % msgname)
messages_by_name[msgname] = msg
- elif cmd == '_DECL_PARSER':
+ elif cmd == '_DECL_ENCODER':
if len(parts) == 1:
msgname = msg = "#empty"
else:
@@ -257,9 +301,9 @@ def main():
if m is not None and m != msg:
error("Conflicting definition for message '%s'" % msgname)
messages_by_name[msgname] = msg
- parsers.append((msgname, msg))
+ encoders.append((msgname, msg))
elif cmd == '_DECL_OUTPUT':
- parsers.append((None, msg))
+ encoders.append((None, msg))
elif cmd == '_DECL_STATIC_STR':
static_strings.append(req[17:])
elif cmd == '_DECL_CONSTANT':
@@ -275,14 +319,15 @@ def main():
# Create unique ids for each message type
msgid = max(msgproto.DefaultMessages.keys())
msg_to_id = dict((m, i) for i, m in msgproto.DefaultMessages.items())
- for msgname in commands.keys() + [m for n, m in parsers]:
+ for msgname in commands.keys() + [m for n, m in encoders]:
msg = messages_by_name.get(msgname, msgname)
if msg not in msg_to_id:
msgid += 1
msg_to_id[msg] = msgid
# Create message definitions
all_param_types = {}
- parsercode = build_parsers(parsers, msg_to_id, all_param_types)
+ parsercode = build_encoders(encoders, msg_to_id, all_param_types)
+ static_strings_code = build_static_strings(static_strings)
# Create command definitions
cmd_by_id = dict((msg_to_id[messages_by_name.get(msgname, msgname)], cmd)
for msgname, cmd in commands.items())
@@ -297,7 +342,8 @@ def main():
, static_strings, constants, version)
# Write output
f = open(outcfile, 'wb')
- f.write(FILEHEADER + paramcode + parsercode + cmdcode + icode)
+ f.write(FILEHEADER + paramcode + parsercode + static_strings_code
+ + cmdcode + icode)
f.close()
# Write data dictionary
diff --git a/src/command.c b/src/command.c
index 44de070d..f96cee62 100644
--- a/src/command.c
+++ b/src/command.c
@@ -112,7 +112,7 @@ static uint8_t in_sendf;
// Encode a message and transmit it
void
-_sendf(uint8_t parserid, ...)
+_sendf(const struct command_encoder *ce, ...)
{
if (readb(&in_sendf))
// This sendf call was made from an irq handler while the main
@@ -120,8 +120,7 @@ _sendf(uint8_t parserid, ...)
return;
writeb(&in_sendf, 1);
- const struct command_encoder *cp = &command_encoders[parserid];
- uint8_t max_size = READP(cp->max_size);
+ uint8_t max_size = READP(ce->max_size);
char *buf = console_get_output(max_size + MESSAGE_MIN);
if (!buf)
goto done;
@@ -129,10 +128,10 @@ _sendf(uint8_t parserid, ...)
if (max_size) {
char *maxend = &p[max_size];
va_list args;
- va_start(args, parserid);
- uint8_t num_params = READP(cp->num_params);
- const uint8_t *param_types = READP(cp->param_types);
- *p++ = READP(cp->msg_id);
+ va_start(args, ce);
+ uint8_t num_params = READP(ce->num_params);
+ const uint8_t *param_types = READP(ce->param_types);
+ *p++ = READP(ce->msg_id);
while (num_params--) {
if (p > maxend)
goto error;
diff --git a/src/command.h b/src/command.h
index 180031e5..609becd9 100644
--- a/src/command.h
+++ b/src/command.h
@@ -1,10 +1,9 @@
#ifndef __COMMAND_H
#define __COMMAND_H
-#include <stdarg.h> // va_list
-#include <stddef.h> // size_t
+#include <stddef.h>
#include <stdint.h> // uint8_t
-#include "compiler.h" // __section
+#include "ctr.h" // DECL_CTR
// Declare a function to run when the specified command is received
#define DECL_COMMAND(FUNC, MSG) \
@@ -25,7 +24,7 @@
// Declare a message type and transmit it.
#define sendf(FMT, args...) \
- _sendf(_DECL_PARSER(FMT) , ##args)
+ _sendf(_DECL_ENCODER(FMT) , ##args )
// Shut down the machine (also declares a static string to transmit)
#define shutdown(msg) \
@@ -34,7 +33,8 @@
sched_try_shutdown(_DECL_STATIC_STR(msg))
// command.c
-void _sendf(uint8_t parserid, ...);
+struct command_encoder;
+void _sendf(const struct command_encoder *ce, ...);
// out/compile_time_request.c (auto generated file)
struct command_encoder {
@@ -50,41 +50,30 @@ enum {
PT_uint32, PT_int32, PT_uint16, PT_int16, PT_byte,
PT_string, PT_progmem_buffer, PT_buffer,
};
-extern const struct command_encoder command_encoders[];
extern const struct command_parser * const command_index[];
extern const uint8_t command_index_size;
extern const uint8_t command_identify_data[];
extern const uint32_t command_identify_size;
+const struct command_encoder *ctr_lookup_encoder(const char *str);
+const struct command_encoder *ctr_lookup_output(const char *str);
+uint8_t ctr_lookup_static_string(const char *str);
-// Compiler glue for DECL_COMMAND macros above.
#define _DECL_COMMAND(FUNC, FLAGS, MSG) \
- char __PASTE(_DECLS_ ## FUNC ## _, __LINE__) [] \
- __visible __section(".compile_time_request") \
- = "_DECL_COMMAND " __stringify(FUNC) " " __stringify(FLAGS) " " MSG; \
- void __visible FUNC(uint32_t*)
+ DECL_CTR("_DECL_COMMAND " __stringify(FUNC) " " __stringify(FLAGS) " " MSG)
-#define _DECL_CONSTANT(NAME, VALUE) \
- char __PASTE(_DECLC_ ## NAME ## _, __LINE__) [] \
- __visible __section(".compile_time_request") \
- = "_DECL_CONSTANT " __stringify(NAME) " " __stringify(VALUE)
+#define _DECL_CONSTANT(NAME, VALUE) \
+ DECL_CTR("_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) ({ \
- static char __PASTE(_DECLS_, __LINE__)[] \
- __section(".compile_time_request") = REQUEST; \
- asm volatile("" : : "i"(__PASTE(_DECLS_, __LINE__))); \
- static char __PASTE(_DECLI_, __LINE__) \
- __section(".compile_time_request." ID_SECTION); \
- (size_t)&__PASTE(_DECLI_, __LINE__); })
+#define _DECL_ENCODER(FMT) ({ \
+ DECL_CTR("_DECL_ENCODER " FMT); \
+ ctr_lookup_encoder(FMT); })
-#define _DECL_PARSER(FMT) \
- _DECL_REQUEST_ID("_DECL_PARSER " FMT, "parsers")
+#define _DECL_OUTPUT(FMT) ({ \
+ DECL_CTR("_DECL_OUTPUT " FMT); \
+ ctr_lookup_output(FMT); })
-#define _DECL_OUTPUT(FMT) \
- _DECL_REQUEST_ID("_DECL_OUTPUT " FMT, "parsers")
-
-#define _DECL_STATIC_STR(FMT) \
- _DECL_REQUEST_ID("_DECL_STATIC_STR " FMT, "static_strings")
+#define _DECL_STATIC_STR(MSG) ({ \
+ DECL_CTR("_DECL_STATIC_STR " MSG); \
+ ctr_lookup_static_string(MSG); })
#endif // command.h
diff --git a/src/ctr.h b/src/ctr.h
new file mode 100644
index 00000000..3396644c
--- /dev/null
+++ b/src/ctr.h
@@ -0,0 +1,17 @@
+#ifndef __CTR_H
+#define __CTR_H
+// Definitions for creating compile time requests. The DECL_CTR macro
+// produces requests (text strings) that are placed in a special
+// section of the intermediate object files. The requests are then
+// extracted during the build and passed to scripts/buildcommand.py.
+// The scripts/buildcommand.py code then generates
+// out/compile_time_request.c from these requests.
+
+#include "compiler.h" // __section
+
+// Declare a compile time request
+#define DECL_CTR(REQUEST) \
+ static char __PASTE(_DECLS_, __LINE__)[] __attribute__((used)) \
+ __section(".compile_time_request") = (REQUEST)
+
+#endif // ctr.h
diff --git a/src/declfunc.lds.S b/src/declfunc.lds.S
index 1f178643..ba564bbf 100644
--- a/src/declfunc.lds.S
+++ b/src/declfunc.lds.S
@@ -24,11 +24,4 @@ SECTIONS
DECLWRAPPER(taskfuncs)
DECLWRAPPER(initfuncs)
DECLWRAPPER(shutdownfuncs)
-
- .compile_time_request.static_strings 0 (INFO) : {
- *( .compile_time_request.static_strings )
- }
- .compile_time_request.parsers 0 (INFO) : {
- *( .compile_time_request.parsers )
- }
}