blob: 879e8e89d49f7eb43ff00c94acc642c2ac9cee10 [file] [log] [blame]
/*
* 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);
}
char *get_simid(void)
{
return arg.s_id;
}
unsigned int get_device_nbr(void)
{
return arg.global_device_nbr;
}
NATIVE_TASK(nrfbsim_register_args, PRE_BOOT_1, 0);
NATIVE_TASK(nrfbsim_cleanup_args, ON_EXIT, 10);