zephyr/boards/posix/nrf52_bsim/argparse.c
Alberto Escolar Piedras ce12abd9e4 nrf52_bsim: Add support for dynamically registering cmd line args
With this change, drivers or components can register on runtime
their own command line arguments.
What this change does is to use the dynamic command line arguments
API from BabbleSim's libUtil and provides a function for the
drivers to add their own.

Note that this change requires v1.3 of the HW models (which remove
a dependency on the board command line arguments structure)

Signed-off-by: Alberto Escolar Piedras <alpi@oticon.com>
2019-01-07 10:27:09 -05:00

231 lines
5.6 KiB
C

/*
* Copyright (c) 2017 Oticon A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>
#include "soc.h"
#include "bs_tracing.h"
#include "bs_oswrap.h"
#include "bs_dump_files.h"
#include "argparse.h"
#include "bstests.h"
#include "NRF_hw_args.h"
#include "bs_cmd_line.h"
#include "bs_dynargs.h"
#include "bs_cmd_line_typical.h"
#include "NRF_HWLowL.h"
static bs_args_struct_t *args_struct;
char executable_name[] = "bs_nrf52_bsim_..";
void component_print_post_help(void)
{
fprintf(stdout, "\nZephyr and a given app compiled with models of the "
"NRF52 HW\n\n");
}
static struct NRF_bsim_args_t arg;
static char *testid;
const char *bogus_sim_id = "bogus";
static void cmd_trace_lvl_found(char *argv, int offset)
{
bs_trace_set_level(arg.verb);
}
static void cmd_gdev_nbr_found(char *argv, int offset)
{
bs_trace_set_prefix_dev(arg.global_device_nbr);
}
static void cmd_testid_found(char *argv, int offset)
{
bst_set_testapp_mode(testid);
}
static void cmd_testlist_found(char *argv, int offset)
{
bst_print_testslist();
exit(0);
}
static bool nosim;
static void cmd_nosim_found(char *argv, int offset)
{
hwll_set_nosim(true);
}
static void save_test_arg(struct NRF_bsim_args_t *args, char *argv)
{
if (args->test_case_argc >= MAXPARAMS_TESTCASES) {
bs_trace_error_line("Too many testcase arguments (at '%s'), "
"maximum is %i\n", argv,
MAXPARAMS_TESTCASES);
} else {
bs_trace_raw(9, "cmdarg: adding '%s' to testcase args[%i]\n",
argv, args->test_case_argc);
args->test_case_argv[args->test_case_argc++] = argv;
}
}
static void print_no_sim_warning(void)
{
bs_trace_warning("Neither simulation id or the device number "
"have been set. I assume you want to run "
"without a BabbleSim phy (-nosim)\n");
bs_trace_warning("If this is not what you wanted, check with "
"--help how to set them\n");
bs_trace_raw(3, "setting sim_id to 'bogus', device number to 0 "
"and nosim\n");
}
void nrfbsim_register_args(void)
{
#define args (&arg)
/* This define is quite ugly, but allows reusing the definitions
* provided by the utils library
*/
static bs_args_struct_t args_struct_toadd[] = {
ARG_TABLE_S_ID,
ARG_TABLE_P_ID_2G4,
ARG_TABLE_DEV_NBR,
ARG_TABLE_GDEV_NBR,
ARG_TABLE_VERB,
ARG_TABLE_SEED,
ARG_TABLE_COLOR,
ARG_TABLE_NOCOLOR,
ARG_TABLE_FORCECOLOR,
_NRF_HW_SUB_CMD_ARG_STRUCT,
/*
* Fields:
* manual, mandatory, switch,
* option_name, var_name, type,
* destination, callback,
* description
*/
{false, false, true,
"nosim", "", 'b',
(void *)&nosim, cmd_nosim_found,
"(debug feature) Do not connect to the phy"},
BS_DUMP_FILES_ARGS,
{false, false, false,
"testid", "testid", 's',
(void *)&testid, cmd_testid_found,
"Which of the tests shall be run. Run -testslist for more info"
},
{false, false, true,
"testslist", "", 'b',
NULL, cmd_testlist_found,
"Print information about the available FW application tests"},
{true, false, false,
"argstest", "arg", 'l',
NULL, NULL,
"The arguments that follow will be passed straight to the "
"testcase init function"},
{true, false, false,
"argsmain", "arg", 'l',
NULL, NULL,
"The arguments that follow will be passed to main (default)"},
ARG_TABLE_ENDMARKER
};
#undef args
bs_add_dynargs(&args_struct, args_struct_toadd);
}
void bs_add_extra_dynargs(bs_args_struct_t *args_struct_toadd)
{
bs_add_dynargs(&args_struct, args_struct_toadd);
}
/**
* Check the arguments provided in the command line: set args based on it or
* defaults, and check they are correct
*/
struct NRF_bsim_args_t *nrfbsim_argsparse(int argc, char *argv[])
{
bs_args_set_defaults(args_struct);
arg.verb = 2;
bs_trace_set_level(arg.verb);
arg.test_case_argv[0] = 0;
arg.test_case_argc = 0;
nrf_hw_sub_cmline_set_defaults(&arg.nrf_hw);
static const char default_phy[] = "2G4";
enum {Main = 0, Test = 1} parsing = Main;
for (int i = 1; i < argc; i++) {
if (bs_is_option(argv[i], "argstest", 0)) {
parsing = Test;
continue;
} else if (bs_is_option(argv[i], "argsmain", 0)) {
parsing = Main;
continue;
}
if (parsing == Main) {
if (!bs_args_parse_one_arg(argv[i], args_struct)) {
bs_args_print_switches_help(args_struct);
bs_trace_error_line("Incorrect option %s\n",
argv[i]);
}
} else if (parsing == Test) {
save_test_arg(&arg, argv[i]);
} else {
bs_trace_error_line("Bad error\n");
}
}
/**
* If the user did not set the simulation id or device number
* we assume he wanted to run with nosim (but warn him)
*/
if ((!nosim) && (arg.s_id == NULL) && (arg.device_nbr == UINT_MAX)) {
print_no_sim_warning();
nosim = true;
hwll_set_nosim(true);
}
if (nosim) {
if (arg.s_id == NULL) {
arg.s_id = (char *)bogus_sim_id;
}
if (arg.device_nbr == UINT_MAX) {
arg.device_nbr = 0;
}
}
if (arg.device_nbr == UINT_MAX) {
bs_args_print_switches_help(args_struct);
bs_trace_error_line("The command line option <device number> "
"needs to be set\n");
}
if (arg.global_device_nbr == UINT_MAX) {
arg.global_device_nbr = arg.device_nbr;
bs_trace_set_prefix_dev(arg.global_device_nbr);
}
if (!arg.s_id) {
bs_args_print_switches_help(args_struct);
bs_trace_error_line("The command line option <simulation ID> "
"needs to be set\n");
}
if (!arg.p_id) {
arg.p_id = (char *)default_phy;
}
if (arg.rseed == UINT_MAX) {
arg.rseed = 0x1000 + arg.device_nbr;
}
return &arg;
}
void nrfbsim_cleanup_args(void)
{
bs_cleanup_dynargs(&args_struct);
}
NATIVE_TASK(nrfbsim_register_args, PRE_BOOT_1, 0);
NATIVE_TASK(nrfbsim_cleanup_args, ON_EXIT, 10);