diff --git a/hw-tests/api-demo/api.h b/hw-tests/api-demo/api.h new file mode 100644 index 0000000000000000000000000000000000000000..295f59b2d45ea0c80c90a96188f0d510569e019c --- /dev/null +++ b/hw-tests/api-demo/api.h @@ -0,0 +1,24 @@ +#ifndef _API_H +#define _API_H +#include <stdint.h> + +#ifndef API +# define API(id, def) def +#endif + +#define API_BUZZER 0x35c3 +API(API_BUZZER, void api_set_buzzer(uint8_t state)); + +typedef struct { + uint8_t red; + uint8_t green; + uint8_t blue; +} led_color_t; + +#define API_LED 0xc0ffee +API(API_LED, void api_set_led(uint8_t led, led_color_t color)); + +#define API_TEST 0xdeadc0de +API(API_TEST, void api_test(char test0, short test1, int test2, long test3)); + +#endif /* _API_H */ diff --git a/hw-tests/api-demo/api/api_caller.c b/hw-tests/api-demo/api/api_caller.c new file mode 100644 index 0000000000000000000000000000000000000000..311dcc5561187cafd5b685988317ab5d8ee9a58b --- /dev/null +++ b/hw-tests/api-demo/api/api_caller.c @@ -0,0 +1,33 @@ +#include <stdlib.h> + +#include "api/api_caller.h" +#include "tmr_utils.h" + +void* api_call_start (uint32_t id, void* args, uint32_t size) +{ + // aquire semaphore + while (E_BUSY == SEMA_GetSema (API_CALL_SEMA)) ; + + ApiCallSpace->id = id; + ApiCallSpace->returning = 0; + return ApiCallSpace->buf; +} + +void* api_call_bother_dispatcher (void* buf) +{ + SEMA_FreeSema (API_CALL_SEMA); + // TODO: set event + + while(1) { + // aquire semaphore + while (E_BUSY == SEMA_GetSema (API_CALL_SEMA)) ; + if (ApiCallSpace->returning == 1) { + break; + } + SEMA_FreeSema(API_CALL_SEMA); + TMR_Delay(MXC_TMR2, MSEC(100), 0); + } + SEMA_FreeSema(API_CALL_SEMA); + + return NULL; +} diff --git a/hw-tests/api-demo/api/api_caller.h b/hw-tests/api-demo/api/api_caller.h new file mode 100644 index 0000000000000000000000000000000000000000..39f7d99a60ad527f189e9750fbe2e5de9931212d --- /dev/null +++ b/hw-tests/api-demo/api/api_caller.h @@ -0,0 +1,6 @@ +#include "mxc_errors.h" + +#include "api_common.h" + +void* api_call (uint32_t id, void *args, uint32_t size); +void* api_call_bother_dispatcher (void* buf); diff --git a/hw-tests/api-demo/api/api_common.h b/hw-tests/api-demo/api/api_common.h new file mode 100644 index 0000000000000000000000000000000000000000..2c4c79d8be627aee8c4fee3719a7d8c16410ecf4 --- /dev/null +++ b/hw-tests/api-demo/api/api_common.h @@ -0,0 +1,12 @@ +#include <stdint.h> + +#define API_CALL_SEMA 0 + +struct api_call +{ + uint32_t id; + uint8_t returning; + unsigned char buf[1]; +}; + +static struct api_call *ApiCallSpace = (struct api_call *)0x20080001; diff --git a/hw-tests/api-demo/api/api_dispatcher.c b/hw-tests/api-demo/api/api_dispatcher.c new file mode 100644 index 0000000000000000000000000000000000000000..1c9c73dd8b259e20f2b15e7d7eedebd3b43242b4 --- /dev/null +++ b/hw-tests/api-demo/api/api_dispatcher.c @@ -0,0 +1,33 @@ +#include "api_dispatcher.h" + +int api_init (sys_cfg_sema_t *sys_cfg) +{ + int ret; + + ret = SEMA_Init (sys_cfg); + /* Set the status of the flag to a valid initial state (right before + * api-calls are made) */ + ApiCallSpace->returning = 1; + + return ret; +} + +/* Generated function */ +void __api_dispatch_call(uint32_t id, void*buffer); + +void api_dispatcher() +{ + while (SEMA_GetSema(API_CALL_SEMA) == E_BUSY) {} + + if (ApiCallSpace->returning == 1) { + SEMA_FreeSema(API_CALL_SEMA); + return; + } + + printf("core1: Catched API CALL!\n"); + __api_dispatch_call(ApiCallSpace->id, ApiCallSpace->buf); + + ApiCallSpace->returning = 1; + + SEMA_FreeSema(API_CALL_SEMA); +} diff --git a/hw-tests/api-demo/api/api_dispatcher.h b/hw-tests/api-demo/api/api_dispatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..622c347961f3ed686696e7f714e54721b14475cc --- /dev/null +++ b/hw-tests/api-demo/api/api_dispatcher.h @@ -0,0 +1,6 @@ +#include "api_common.h" +#include "mxc_sys.h" + +int api_init (sys_cfg_sema_t *sys_cfg); +void api_dispatcher(); + diff --git a/hw-tests/api-demo/core1-dispatcher.c b/hw-tests/api-demo/core1-dispatcher.c new file mode 100644 index 0000000000000000000000000000000000000000..b0ad77431b5d0531f537efd37e577309b97f385a --- /dev/null +++ b/hw-tests/api-demo/core1-dispatcher.c @@ -0,0 +1,56 @@ +#include "board.h" +#include "gpio.h" +#include "mxc_delay.h" +#include "api.h" +#include "tmr_utils.h" +#include "leds.h" + +#include "api/api_dispatcher.h" + +static const gpio_cfg_t motor_pin = {PORT_0, PIN_8, GPIO_FUNC_OUT, GPIO_PAD_NONE}; + +void api_set_buzzer(uint8_t state) +{ + if (state) { + printf("API: Turning motor ON!\n"); + GPIO_OutSet(&motor_pin); + } else { + printf("API: Turning motor OFF!\n"); + GPIO_OutClr(&motor_pin); + } +} + +void api_set_led(uint8_t led, led_color_t color) +{ + printf("API: Changing color of led %d.\n", led); + printf("Color { r: %3d, g: %3d, b: %3d }\n", color.red, color.green, color.blue); + leds_set(led, color.red, color.green, color.blue); + leds_update(); +} + +void api_test(char test0, short test1, int test2, long test3) +{ + printf ("test0: %x, test1: %d, test2: %x, test3: %lx\n", + test0, (int)test1, test2, test3); +} + +int main(void) +{ + api_init(NULL); + leds_init(); + + while (1) { + api_dispatcher(); + TMR_Delay(MXC_TMR1, MSEC(100), 0); + } + + +#if 0 + // Enable rxev on core1 + MXC_GCR->evten |= 0x20; + for (int i = 0; 1; i++) { + __asm volatile("wfe"); + printf("core1: Hello! %d\n", i); + } +#endif +} diff --git a/hw-tests/api-demo/flash.gdb b/hw-tests/api-demo/flash.gdb new file mode 100644 index 0000000000000000000000000000000000000000..1b9e60c0a785f39ef897ef9aa2f9c9ae193f0449 --- /dev/null +++ b/hw-tests/api-demo/flash.gdb @@ -0,0 +1,13 @@ +source ../../.gdbinit + +set confirm off + +echo Loading core1 image ... +file ../../build/hw-tests/api-demo/api-demo-core1.elf +load +echo Loading core0 image ... +file ../../build/hw-tests/api-demo/api-demo-core0.elf +load + +reset +quit diff --git a/hw-tests/api-demo/genapi.py b/hw-tests/api-demo/genapi.py new file mode 100644 index 0000000000000000000000000000000000000000..40cf1099e357ef1198d9ef3a732a7915ba074ac5 --- /dev/null +++ b/hw-tests/api-demo/genapi.py @@ -0,0 +1,168 @@ +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+) \$ void (?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( + os.path.basename(args.header) + ), file=f_client) + + print("""\ +#include "{}" + +void __api_dispatch_call(uint32_t id, void*buffer) +{{ + switch (id) {{""".format( + os.path.basename(args.header) + ), file=f_server) + + 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} */ +void {cdecl}({cargs}) +{{ + const int size = {total_size}; + void*buffer; + + buffer = api_call_start({id}, size); + /* TODO: Check if buffer is no NULL */ +""".format( + id=api_id, + cdecl=api_decl, + cargs=api_args, + total_size=" + ".join(api_args_sizes), + ), + file=f_client, + ) + + print("""\ + case {id}: + {cdecl}(""".format(id=api_id, cdecl=api_decl), + file=f_server, + ) + + 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, + ), + file=f_client, + ) + + if i != 0: + print(",", file=f_server) + + print( + """\ + *({type}*)(buffer + {offset})""".format( + type=ty, + offset=" + ".join(api_args_sizes[:i]) if i > 0 else "0", + ), + file=f_server, + end="", + ) + + print(""" + ); + break;""".format( + cdecl=api_decl, + args=", ".join(api_args_names), + ), + file=f_server, + ) + + print( + """ + printf("Sending call {id}\\nBUF: "); + for (int i = 0; i < size; i++) {{ + printf("0x%02x ", ((char*)buffer)[i]); + }} + printf("\\n"); + + api_call_bother_dispatcher(buffer); +}} +""".format( + id=api_id + ), + file=f_client, + ) + + print("""\ + default: + printf("Error: API function %x is unknown!!\\n", {id}); + break; + }} +}}""".format( + id=api_id, + ), file=f_server) + + +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..ac615346537a6427e1e1a295347940bd807f8791 --- /dev/null +++ b/hw-tests/api-demo/main.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "card10.h" +#include "tmr_utils.h" +#include "api.h" + +void Core1_Start(void) { + //MXC_GCR->gp0 = (uint32_t)(&__isr_vector_core1); + MXC_GCR->gp0 = 0x10040000; + MXC_GCR->perckcn1 &= ~MXC_F_GCR_PERCKCN1_CPU1; +} + +void Core1_Stop(void) { + MXC_GCR->perckcn1 |= MXC_F_GCR_PERCKCN1_CPU1; +} + +int main(void) +{ + int count = 0; + led_color_t red = {0x10, 0, 0}; + + card10_init(); + card10_diag(); + + printf("API Test.\n"); + printf("core0: Starting dispatcher on core1\n"); + Core1_Start(); + TMR_Delay(MXC_TMR0, MSEC(100), 0); + + api_set_buzzer(1); + TMR_Delay(MXC_TMR0, MSEC(300), 0); + api_set_buzzer(0); + api_set_led(5, red); + api_test(0xAB, 0x7DEF, 0x01, 0x02); + + 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..d80efafa1514d4cfcdc6e37f4b30cb3c7fd8b193 --- /dev/null +++ b/hw-tests/api-demo/meson.build @@ -0,0 +1,41 @@ +api_stubs = custom_target( + 'api_*.c', + input: 'api.h', + output: ['api_client.c', 'api_server.c'], + command: [ + python3, + meson.current_source_dir() + '/genapi.py', + '-H', '@INPUT0@', + '-c', '@OUTPUT0@', '-s', '@OUTPUT1@', + ], + depend_files: 'genapi.py', +) + + +name = 'api-demo-core0' + +executable( + name + '.elf', + 'main.c', + './api/api_caller.c', + api_stubs[0], + dependencies: [libcard10, max32665_startup_core0], + link_whole: [max32665_startup_core0_lib, board_card10_lib], + link_args: [ + '-Wl,-Map=' + meson.current_build_dir() + '/' + name + '.map', + ], +) + +name = 'api-demo-core1' + +executable( + name + '.elf', + 'core1-dispatcher.c', + './api/api_dispatcher.c', + api_stubs[1], + dependencies: [libcard10, max32665_startup_core1], + link_whole: [max32665_startup_core1_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/') diff --git a/meson.build b/meson.build index e01f491ce24c50d83d478eacf28cde0f3dc18daa..0cb5a984fa08e582ef5ae817d5bac343a04e7213 100644 --- a/meson.build +++ b/meson.build @@ -27,5 +27,7 @@ add_global_link_arguments( language: 'c', ) +python3 = import('python').find_installation('python3') + subdir('lib/') subdir('hw-tests/')