diff --git a/hw-tests/api-demo/api.h b/hw-tests/api-demo/api.h new file mode 100644 index 0000000000000000000000000000000000000000..7283a779edf9a1d2325cab3c937b74e0330ba53e --- /dev/null +++ b/hw-tests/api-demo/api.h @@ -0,0 +1,23 @@ +#ifndef _API_H +#define _API_H + +#ifndef API +# define API(id, def) def +#endif + +#define API_FOO 0x35c3 +API(API_FOO, void foo(short x, int y, char z, int w)); + +#define API_BAR 0xc0ffee +API(API_BAR, void bar(char*astr)); + +typedef struct { + int foo; + int bar; + int baz; +} qux_t; + +#define API_QUX 0xCCC +API(API_QUX, void qux(qux_t q)); + +#endif /* _API_H */ diff --git a/hw-tests/api-demo/genapi.py b/hw-tests/api-demo/genapi.py new file mode 100644 index 0000000000000000000000000000000000000000..3316875efbb86241ed2ee2884518bd196ebbc2a5 --- /dev/null +++ b/hw-tests/api-demo/genapi.py @@ -0,0 +1,111 @@ +import argparse +import contextlib +import os +import re +import subprocess + + +def main(): + parser = argparse.ArgumentParser( + description="Generate the API stubs from a header file." + ) + parser.add_argument( + "-H", "--header", required=True, help="The header to base the definitions on." + ) + parser.add_argument( + "-c", "--client", required=True, help="The output client-side c source file." + ) + parser.add_argument( + "-s", "--server", required=True, help="The output server-side c source file." + ) + args = parser.parse_args() + + with contextlib.ExitStack() as cx: + # Run the preprocessor on the header file to get the API definitions. + # + # For this, we first need a source to include the header which contains + # an alternative definition of the `API` macro that marks definitions in + # a way we can find later on. + api_src = """\ +#define API(id, def) __GENERATE_API $ __GEN_ID_##id $ def $ +#include "{header}" +""".format( + header=os.path.relpath(args.header) + ) + + # Evaluate the preprocessor + source = subprocess.check_output( + ["gcc", "-E", "-"], input=api_src.encode() + ).decode() + + # Parse the header for API definitions + matcher = re.compile( + r"__GENERATE_API \$ __GEN_ID_(?P<id>\w+) \$ (?P<decl>.+?)\((?P<args>.*?)\) \$", + re.DOTALL | re.MULTILINE, + ) + + args_matcher = re.compile(r"(?P<type>\w+(?:\*+|\s+))(?P<name>\w+),") + + # Open output files + f_client = cx.enter_context(open(args.client, "w")) + f_server = cx.enter_context(open(args.server, "w")) + + print('#include "{}"\n'.format(args.header)) + + for match in matcher.finditer(source): + api_id = match.group("id") + api_decl = match.group("decl") + api_args = match.group("args") + + api_args_names = [] + api_args_types = [] + api_args_sizes = [] + + # Destructure args + for match in args_matcher.finditer(api_args + ","): + arg_type = match.group("type").strip() + arg_name = match.group("name") + + api_args_names.append(arg_name) + api_args_types.append(arg_type) + api_args_sizes.append("sizeof({})".format(arg_type)) + + print( + """\ +/* Autogenerated stub for {id} */ +{cdecl}({cargs}) {{ + const int size = {total_size}; + unsigned char buffer[size]; +""".format( + id=api_id, + cdecl=api_decl, + cargs=api_args, + total_size=" + ".join(api_args_sizes), + ) + ) + + for i, (arg, ty) in enumerate(zip(api_args_names, api_args_types)): + print( + """ *({type}*)(buffer + {offset}) = {arg};""".format( + type=ty, + offset=" + ".join(api_args_sizes[:i]) if i > 0 else "0", + arg=arg, + ) + ) + + print( + """ + printf("{id}: "); + for (int i = 0; i < size; i++) {{ + printf("0x%02x ", buffer[i]); + }} + printf("\\n"); +}} +""".format( + id=api_id + ) + ) + + +if __name__ == "__main__": + main() diff --git a/hw-tests/api-demo/main.c b/hw-tests/api-demo/main.c new file mode 100644 index 0000000000000000000000000000000000000000..41cb01232c5dc181263ad040b01544926687f2ae --- /dev/null +++ b/hw-tests/api-demo/main.c @@ -0,0 +1,22 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "card10.h" +#include "tmr_utils.h" + +int main(void) +{ + int count = 0; + + card10_init(); + card10_diag(); + + printf("API Test.\n"); + + while(1) { + printf("count = %d\n", count++); + + TMR_Delay(MXC_TMR0, SEC(1), 0); + } +} diff --git a/hw-tests/api-demo/meson.build b/hw-tests/api-demo/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..071241b1f7f56b781f75f8e1519fdd9300729e1c --- /dev/null +++ b/hw-tests/api-demo/meson.build @@ -0,0 +1,11 @@ +name = 'api-demo' + +executable( + name + '.elf', + 'main.c', + dependencies: [libcard10, max32665_startup], + link_whole: [max32665_startup_lib, board_card10_lib], + link_args: [ + '-Wl,-Map=' + meson.current_build_dir() + '/' + name + '.map', + ], +) diff --git a/hw-tests/meson.build b/hw-tests/meson.build index 757dccd1a4e6773bf3aa7b909cf3cf427085922b..1c04f9e686ffbd17c7c3023fc443b3309beb379f 100644 --- a/hw-tests/meson.build +++ b/hw-tests/meson.build @@ -1,3 +1,4 @@ +subdir('api-demo/') subdir('bmatest/') subdir('bmetest/') subdir('dual-core/')