/***** Initialisation *****/
void init()							
{
	unsigned char i ;
	cli();							// Désactiver toutes les interruptions

	sDDR(DDRD,1);					// mettre port TX en sortie
	sbiBF(PORTD,0); 				// mettre pull-up sur RX

	for(i=0;i<=4;i++)				// Initialiser les demandes à 0 qui signifie qu'il n'y a pas de demande de la part de la FoxBoard
	{
		data[i]=0x00;
	}

    i2c_init();              		// Initialisation interface I2C

	init_3964r();					// Initialisation de la communication en protocole 3964 avec la FoxBoard
	ENABLE_RX_INT_USART;			// Autoriser les interruption série RX
	fonctionnement_RX = 1;			// mode de réception

	init_watchdog();				// Initilise les reset

	InitADC();						// Initialise les ADC

	sei();							// Activer toutes les interruptions	
}
Exemple #2
0
static void plug_devices(void) {
    /* Port ranges 0x0 -> 0xF */
    port_map[0x0] = init_control();
    port_map[0x1] = init_flash();
    port_map[0x2] = init_sha256();
    port_map[0x3] = init_usb();
    port_map[0x4] = init_lcd();
    port_map[0x5] = init_intrpt();
    port_map[0x6] = init_watchdog();
    port_map[0x7] = init_gpt();
    port_map[0x8] = init_rtc();
    port_map[0x9] = init_protected();
    port_map[0xA] = init_keypad();
    port_map[0xB] = init_backlight();
    port_map[0xC] = init_cxxx();
    port_map[0xD] = init_dxxx();
    port_map[0xE] = init_exxx();
    port_map[0xF] = init_fxxx();

    reset_proc_count = 0;

    /* Populate reset callbacks */
    add_reset_proc(lcd_reset);
    add_reset_proc(keypad_reset);
    add_reset_proc(gpt_reset);
    add_reset_proc(rtc_reset);
    add_reset_proc(watchdog_reset);
    add_reset_proc(cpu_reset);

    gui_console_printf("[CEmu] Initialized APB...\n");
}
Exemple #3
0
int main(void)
{
    laser_off(); 
	bootloaderSwitcher();

  init_serial_number();
	USB_Start();
  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

	setupJP5();
	setupJP6();
	setupLeds();
  init_watchdog();
  setup_interlock();

	//debug: flas the light on boot, to watch for watchdog resets
	setCoilLed(1);

	initialize_led_override();
	if (LED_OVERRIDES_EN){
		play_long_spin(); //Spin the led's while we load the rest of this stuff
	}

  initialize_pwm();
  initialize_dripper();

	setCornerLed(0);
	setInLed(0);
	setCoilLed(0);
	setUSBLed(0);

  SysTick_Config(SystemCoreClock / 2000); //48MHz/2000 gives us 2000 ticks per second (2KHz)

  int last_drip_count = g_dripcount;

  while(1) {
    serialio_feed();
    updateADC();
    if (move_count!=0){
      g_twig_coils=0;
      g_key_coil_gate=0;
    }
    if (g_dripcount != last_drip_count) {
      last_drip_count = g_dripcount;
      send_updated_drip_count();
    }
    if ((tick % 500) == 0) {
      send_printer_status();
    } 
  }
}
t_nmf_error METH(construct)(void)
{
	t_uint16 i;

	/* Initialize internal private data */
	for (i=0; i<RESOURCE_MAX; i++) {
		rm_fifo_flush(i);
	}
  init_watchdog();
	rmDebugMode = DBG_MODE_NORMAL;
	hwInitDone  = FALSE;
	return NMF_OK;
} /* end of construct() function */
int Sentinel::start() {
    if (!load_config()) {
        logging::error("Error opening config file: " + config_path_);
        return -1;
    }

    if (watchdog_path_.length() == 0)
        logging::info("Watchdog disabled.");
    else if (!init_watchdog())
        // watchdog not available
        logging::info("Watchdog not available. Continuing without it.");

    return watch();
}
Exemple #6
0
int main (void){
    
        init_watchdog();
        init_leds();
        init_pushbutton();
  
        while(1){
                if ((P1IN & BUTTON) == BUTTON){
                        P1OUT |= 0x01;                  // LED0 on
                        P1OUT &= 0xBF;                  // LED1 off
                }
                else{
                        P1OUT &= 0xFE;                  // LED0 off
                        P1OUT |= 0x40;                  // LED on
                }        
        }
        return 0;
}
/******************************************************************************
** Function name:   main
**
** Description:     Program entry point. Contains initializations and menu loop
**
** Parameters:      None
** Returned value:  Program exit value
**
******************************************************************************/
int main(void)
{
	SystemInit();
	SystemCoreClockUpdate();

	setCANBUS1();

	load_nonpersistent();

	SysTick_Config(SystemCoreClock / 10);	// 100mS Systicker.

	I2C1Init();

	ADCInit(ADC_CLK);

	init_GPIO();

	init_watchdog();

	while(1){shunt_read();}

	return 0;
}
Exemple #8
0
int main(int argc, char* argv[])
{
	int ret = EXIT_SUCCESS;
	int childstatus;
	pid_t pid;
	const char taskname[13]="trinity-main";

	outputstd("Trinity " VERSION "  Dave Jones <*****@*****.**>\n");

	progname = argv[0];

	initpid = getpid();

	page_size = getpagesize();
	num_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
	max_children = num_online_cpus;	/* possibly overridden in params. */

	if (init_random() == FALSE)
		exit(EXIT_FAILURE);

	set_seed(0);

	select_syscall_tables();

	create_shm();

	/* We do this before the parse_args because --fds will need to
	 * operate on it when implemented.
	 */
	setup_fd_providers();

	parse_args(argc, argv);

	init_uids();

	change_tmp_dir();

	init_logging();

	init_shm();

	kernel_taint_initial = check_tainted();
	if (kernel_taint_initial != 0)
		output(0, "Kernel was tainted on startup. Will ignore flags that are already set.\n");

	if (munge_tables() == FALSE) {
		ret = EXIT_FAILURE;
		goto out;
	}

	if (show_syscall_list == TRUE) {
		dump_syscall_tables();
		goto out;
	}

	init_syscalls();

	if (show_ioctl_list == TRUE) {
		dump_ioctls();
		goto out;
	}

	do_uid0_check();

	if (do_specific_domain == TRUE)
		find_specific_domain(specific_domain_optarg);

	setup_initial_mappings();

	parse_devices();

	pids_init();

	setup_main_signals();

	/* check if we ctrl'c or something went wrong during init. */
	if (shm->exit_reason != STILL_RUNNING)
		goto cleanup_fds;

	init_watchdog();

	/* do an extra fork so that the watchdog and the children don't share a common parent */
	fflush(stdout);
	pid = fork();
	if (pid == 0) {
		shm->mainpid = getpid();

		setup_main_signals();

		no_bind_to_cpu = RAND_BOOL();

		output(0, "Main thread is alive.\n");
		prctl(PR_SET_NAME, (unsigned long) &taskname);
		set_seed(0);

		if (open_fds() == FALSE) {
			if (shm->exit_reason != STILL_RUNNING)
				panic(EXIT_FD_INIT_FAILURE);	// FIXME: Later, push this down to multiple EXIT's.

			exit_main_fail();
		}

		if (dropprivs == TRUE)	//FIXME: Push down into child processes later.
			drop_privs();

		main_loop();

		shm->mainpid = 0;
		_exit(EXIT_SUCCESS);
	}

	/* wait for main loop process to exit. */
	(void)waitpid(pid, &childstatus, 0);

	/* wait for watchdog to exit. */
	waitpid(watchdog_pid, &childstatus, 0);

	output(0, "Ran %ld syscalls. Successes: %ld  Failures: %ld\n",
		shm->stats.total_syscalls_done - 1, shm->stats.successes, shm->stats.failures);

cleanup_fds:

	close_sockets();

	destroy_initial_mappings();

	shutdown_logging();

	ret = set_exit_code(shm->exit_reason);
out:

	exit(ret);
}
Exemple #9
0
/**
 * Main system entry point
 */
int main (void) {
  SystemInit();

  /* Initialise Pins */
  CUTDOWN_OFF();
  HEATER_OFF();
  MBED_OFF();
  GREEN_OFF();

  /* Update the value of SystemCoreClock */
  SystemCoreClockUpdate();

  /* Initialise Interfaces */
  i2c_init();
  spi_init(process_imu_frame); // IMU
  sd_spi_init(); // SD
  uart_init(); // GPS
  pwrmon_init(); // ADC

  /* Initialise Sensors */
  init_barometer();

  /* SD Card */
  if (initialise_card()) { // Initialised to something
    if (disk_initialize() == 0) { // Disk initialisation was successful
      sd_good = 1;
    }
  }

  GREEN_ON();

  /* Configure the SysTick */
  NVIC_SetPriority(SysTick_IRQn, 0); // Highest Priority Interrupt
  SysTick_Config(SystemCoreClock / RTTY_BAUD);

  /* Watchdog - Disabled for debugging */
#ifndef WATCHDOG_DISABLED
  init_watchdog();
#endif

  struct barometer* b;
  struct imu_raw ir;
  struct gps_data gd;
  struct gps_time gt;
  double alt, ext_temp;
  int tx_length; // The length of the built tx string

  char tx_string[TX_STRING_LENGTH];

  while (1) {
    /* Grab Data */
    pwrmon_start(pwrmon_callback);
    b = get_barometer();
    get_imu_raw_data(&ir);
    get_gps_data(&gd);
    get_gps_time(&gt);
    ext_temp = get_temperature();

    /* Data Processing */
    if (b->valid) {
      alt = pressure_to_altitude(b->pressure);
    } else {
      alt = -1;
      b->temperature = -1;
    }

    /* Act on the data */
    control_gsm(alt);
    control_cutdown(ticks_until_cutdown, alt);
    control_heater(b->temperature);

    /* Create a protocol string */
    int cutstat;
    if (ticks_until_cutdown == 0) {
      cutstat = -1;
    } else {
      cutstat = ticks_until_cutdown / (RTTY_BAUD*60);
    }
    tx_length = build_communications_frame(tx_string, TX_STRING_LENGTH,
					   &gt, b, &gd, alt, ext_temp, &ir,
					   cutstat,  cutdown_voltage);

    /* Transmit - Quietly fails if another transmission is ongoing */
    rtty_set_string(tx_string, tx_length);

    /* Store */
    if (sd_good) {
      tx_length -= 2; // Remove \n\0
      tx_length += communications_frame_add_extra(tx_string + tx_length,
				     TX_STRING_LENGTH - tx_length, &ir);

      disk_write_next_block((uint8_t*)tx_string, tx_length+1); // Include null terminator
    }

    /* Housekeeping */
    GREEN_TOGGLE();
    feed_watchdog();
  }
}
Exemple #10
0
int main(int argc, char* argv[])
{
	int ret = EXIT_SUCCESS;
	int childstatus;
	unsigned int i;

	outputstd("Trinity v" __stringify(VERSION) "  Dave Jones <*****@*****.**>\n");

	progname = argv[0];

	initpid = getpid();

	page_size = getpagesize();
	num_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);

	select_syscall_tables();

	if (create_shm())
		exit(EXIT_FAILURE);

	parse_args(argc, argv);
	outputstd("Done parsing arguments.\n");

	if (kernel_taint_mask != (int)0xFFFFFFFF) {
		outputstd("Custom kernel taint mask has been specified: 0x%08x (%d).\n", kernel_taint_mask, kernel_taint_mask);
	}

	if (user_specified_children != 0)
		max_children = user_specified_children;
	else
		max_children = sysconf(_SC_NPROCESSORS_ONLN);

	if (max_children > MAX_NR_CHILDREN) {
		outputerr("Increase MAX_NR_CHILDREN!\n");
		exit(EXIT_FAILURE);
	}

	setup_shm_postargs();

	if (logging == TRUE)
		open_logfiles();

	if (munge_tables() == FALSE) {
		ret = EXIT_FAILURE;
		goto out;
	}

	if (show_syscall_list == TRUE) {
		dump_syscall_tables();
		goto out;
	}

	init_syscalls();

	if (show_ioctl_list == TRUE) {
		dump_ioctls();
		goto out;
	}

	if (getuid() == 0) {
		if (dangerous == TRUE) {
			outputstd("DANGER: RUNNING AS ROOT.\n");
			outputstd("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
			outputstd("or similar which could potentially make this machine unbootable without a firmware reset.\n\n");
			outputstd("ctrl-c now unless you really know what you are doing.\n");
			for (i = 10; i > 0; i--) {
				outputstd("Continuing in %d seconds.\r", i);
				(void)fflush(stdout);
				sleep(1);
			}
		} else {
			outputstd("Don't run as root (or pass --dangerous if you know what you are doing).\n");
			exit(EXIT_FAILURE);
		}
	}

	if (do_specific_proto == TRUE)
		find_specific_proto(specific_proto_optarg);

	init_buffers();

	parse_devices();

	pids_init();

	setup_main_signals();

	kernel_taint_initial = check_tainted();
	if (kernel_taint_initial != 0) {
		output(0, "Kernel was tainted on startup. Will ignore flags that are already set.\n");
	}

	change_tmp_dir();

	/* check if we ctrl'c or something went wrong during init. */
	if (shm->exit_reason != STILL_RUNNING)
		goto cleanup_fds;

	init_watchdog();

	do_main_loop();

	/* Shutting down. */
	waitpid(watchdog_pid, &childstatus, 0);

	output(0, "\nRan %ld syscalls. Successes: %ld  Failures: %ld\n",
		shm->total_syscalls_done - 1, shm->successes, shm->failures);

	ret = EXIT_SUCCESS;

cleanup_fds:

	close_sockets();

	destroy_global_mappings();

	if (logging == TRUE)
		close_logfiles();

out:

	exit(ret);
}
Exemple #11
0
/* Main function */
int main(void) {
  sc_time_t     my_timer;  
  int32_t value; 

  dint();

#if USE_WATCHDOG
    init_watchdog(); 
#else
    WDTCTL = WDTCTL_INIT;               //Init watchdog timer
#endif
    
  init_ports();
  init_clock();
  sc_init_timer();

  scandal_init(); 

  config_read(); 

  {volatile int i; 
    for(i=0; i<100; i++)
      ;
  }

  /* Below here, we assume we have a config */ 

  /* Send out the error that we've reset -- it's not fatal obviously, 
     but we want to know when it happens, and it really is an error, 
     since something that's solar powered should be fairly constantly 
     powered */ 
  scandal_do_user_err(UNSWMPPTNG_ERROR_WATCHDOG_RESET); 
    
    /* Make sure our variables are set up properly */ 
    tracker_status = 0;     
    
  /* Initialise FPGA (or, our case, CPLD) stuff */ 
  fpga_init(); 

  /* Starts the ADC and control loop interrupt */
  control_init(); 

  /* Initialise the PV tracking mechanism */ 
  pv_track_init(); 

  eint();

  my_timer = sc_get_timer(); 

  while (1) {
    sc_time_t timeval; 

    timeval = sc_get_timer();

    handle_scandal(); 
    
    /* pv_track sends data when it feels like it */ 
    pv_track_send_data(); 

    /* Periodically send out the values recorded by the ADC */ 
    if(timeval >= my_timer + TELEMETRY_UPDATE_PERIOD){
        my_timer = timeval;
        toggle_yellow_led();
#if USE_WATCHDOG
	kick_watchdog(); 
#endif
        
        mpptng_do_errors(); 

        pv_track_send_telemetry(); 
        /* We send the Input current and voltage from 
            within the pvtrack module */ 

        /*  scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_IN_VOLTAGE, 
                        sample_adc(MEAS_VIN1));
            scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_IN_CURRENT, 
                        sample_adc(MEAS_IIN1));*/ 

        scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_OUT_VOLTAGE, 
                    sample_adc(MEAS_VOUT));
        scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_HEATSINK_TEMP, 
                    sample_adc(MEAS_THEATSINK));
        scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_15V, 
                    sample_adc(MEAS_15V));
        scandal_send_channel(TELEM_LOW, UNSWMPPTNG_STATUS, 
                    tracker_status); 

        /* Pre-scale for the temperature */ 
        {
            int32_t degC = sample_adc(MEAS_TAMBIENT); 
            degC = (((degC - 1615)*704*1000)/4095);
            scandal_send_scaled_channel(TELEM_LOW, UNSWMPPTNG_AMBIENT_TEMP, 
                                        degC);
        }

#if DEBUG >= 1
        scandal_send_channel(TELEM_LOW, 134, output);	
        scandal_send_channel(TELEM_LOW, 136, fpga_nFS()); 
#endif
    } 

    /*  If we're not tracking, 
        check to see that our start-up criteria are satisfied, and then
        initialise the control loops and restart tracking */ 
    if((tracker_status & STATUS_TRACKING) == 0){
        /* Check the input voltage */
        value = sample_adc(MEAS_VIN1); 
        scandal_get_scaled_value(UNSWMPPTNG_IN_VOLTAGE, &value);
        if(value < config.min_vin)
            continue; 

        /* Check the output voltage */
        value = sample_adc(MEAS_VOUT);
        scandal_get_scaled_value(UNSWMPPTNG_OUT_VOLTAGE, &value); 
        if(value > config.max_vout)
            continue; 

        tracker_status |= STATUS_TRACKING; 

        /* Initialise the tracking algorithm */ 
        //      pv_track_init(); 

        /* Reset the FPGA */ 	 
        fs_reset(); 

        /* Initialise the control loop */ 
        control_start(); 

        /* Enable the FPGA */ 
        fpga_enable(FPGA_ON); 
    }
  }
}
Exemple #12
0
int main(int argc, char* argv[])
{
	int ret = EXIT_SUCCESS;
	unsigned int i;

	printf("Trinity v" __stringify(VERSION) "  Dave Jones <*****@*****.**> 2012\n");

	progname = argv[0];

	setup_syscall_tables();

	parse_args(argc, argv);

	/* If we didn't pass -c or -x, mark all syscalls active. */
	if ((do_specific_syscall == FALSE) && (do_exclude_syscall == FALSE))
		mark_all_syscalls_active();

	if (getuid() == 0) {
		if (dangerous == TRUE) {
			printf("DANGER: RUNNING AS ROOT.\n");
			printf("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
			printf("or similar which could potentially make this machine unbootable without a firmware reset.\n\n");
			printf("ctrl-c now unless you really know what you are doing.\n");
			for (i = 10; i > 0; i--) {
				printf("Continuing in %d seconds.\r", i);
				(void)fflush(stdout);
				sleep(1);
			}
		} else {
			printf("Don't run as root (or pass --dangerous if you know what you are doing).\n");
			exit(EXIT_FAILURE);
		}
	}

	if (create_shm())
		exit(EXIT_FAILURE);

	/* Set seed in parent thread*/
	set_seed(0);

	if (desired_group != GROUP_NONE) {
		ret = setup_syscall_group(desired_group);
		if (ret == FALSE) {
			ret = EXIT_FAILURE;
			goto cleanup_shm;
		}
	}

	if (show_syscall_list == TRUE) {
		dump_syscall_tables();
		goto cleanup_shm;
	}

	if (validate_syscall_tables() == FALSE) {
		printf("No syscalls were enabled!\n");
		printf("Use 32bit:%d 64bit:%d\n", use_32bit, use_64bit);
		goto cleanup_shm;
	}

	sanity_check_tables();

	if (logging == TRUE)
		open_logfiles();


	if (do_specific_syscall == FALSE) {
		if (biarch == TRUE)
			output(0, "Fuzzing %d 32-bit syscalls & %d 64-bit syscalls.\n",
				max_nr_32bit_syscalls, max_nr_64bit_syscalls);
		else
			output(0, "Fuzzing %d syscalls.\n", max_nr_syscalls);
	}

	if (do_specific_proto == TRUE)
		find_specific_proto(specific_proto_optarg);

	page_size = getpagesize();

	init_buffers();

	mask_signals();

	if (check_tainted() != 0) {
		output(0, "Kernel was tainted on startup. Will keep running if trinity causes an oops.\n");
		do_check_tainted = TRUE;
	}

	/* just in case we're not using the test.sh harness. */
	chmod("tmp/", 0755);
	ret = chdir("tmp/");
	if (!ret) {
		/* nothing right now */
	}

	if (shm->exit_reason != STILL_RUNNING)
		goto cleanup_fds;

	init_watchdog();

	do_main_loop();

	printf("\nRan %ld syscalls. Successes: %ld  Failures: %ld\n",
		shm->total_syscalls_done - 1, shm->successes, shm->failures);

	ret = EXIT_SUCCESS;

cleanup_fds:

	for (i = 0; i < nr_sockets; i++) {
		struct linger ling;

		ling.l_onoff = FALSE;	/* linger active */
		setsockopt(shm->socket_fds[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));
		shutdown(shm->socket_fds[i], SHUT_RDWR);
		close(shm->socket_fds[i]);
	}

	destroy_maps();

	if (logging == TRUE)
		close_logfiles();

cleanup_shm:

	if (shm != NULL)
		munmap(shm, sizeof(struct shm_s));

	exit(ret);
}
Exemple #13
0
int main(int argc, char* argv[])
{
	int ret = EXIT_SUCCESS;
	int childstatus;
	unsigned int i;

	printf("Trinity v" __stringify(VERSION) "  Dave Jones <*****@*****.**>\n");

	progname = argv[0];

	page_size = getpagesize();

	select_syscall_tables();

	if (create_shm())
		exit(EXIT_FAILURE);

	parse_args(argc, argv);
	printf("Done parsing arguments.\n");

	setup_shm_postargs();

	if (logging == TRUE)
		open_logfiles();

	if (munge_tables() == FALSE) {
		ret = EXIT_FAILURE;
		goto out;
	}

	if (show_syscall_list == TRUE) {
		dump_syscall_tables();
		goto out;
	}

	if (show_ioctl_list == TRUE) {
		dump_ioctls();
		goto out;
	}

	if (getuid() == 0) {
		if (dangerous == TRUE) {
			printf("DANGER: RUNNING AS ROOT.\n");
			printf("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
			printf("or similar which could potentially make this machine unbootable without a firmware reset.\n\n");
			printf("ctrl-c now unless you really know what you are doing.\n");
			for (i = 10; i > 0; i--) {
				printf("Continuing in %d seconds.\r", i);
				(void)fflush(stdout);
				sleep(1);
			}
		} else {
			printf("Don't run as root (or pass --dangerous if you know what you are doing).\n");
			exit(EXIT_FAILURE);
		}
	}

	if (do_specific_proto == TRUE)
		find_specific_proto(specific_proto_optarg);

	init_buffers();

	parse_devices();

	pids_init();

	setup_main_signals();

	if (check_tainted() != 0) {
		output(0, "Kernel was tainted on startup. Will keep running if trinity causes an oops.\n");
		ignore_tainted = TRUE;
	}

	/* just in case we're not using the test.sh harness. */
	chmod("tmp/", 0755);
	ret = chdir("tmp/");
	if (!ret) {
		/* nothing right now */
	}

	if (shm->exit_reason != STILL_RUNNING)
		goto cleanup_fds;

	init_watchdog();

	do_main_loop();

	waitpid(shm->watchdog_pid, &childstatus, 0);

	printf("\nRan %ld syscalls. Successes: %ld  Failures: %ld\n",
		shm->total_syscalls_done - 1, shm->successes, shm->failures);

	ret = EXIT_SUCCESS;

cleanup_fds:

	for (i = 0; i < nr_sockets; i++) {
		struct linger ling;

		ling.l_onoff = FALSE;	/* linger active */
		setsockopt(shm->socket_fds[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));
		shutdown(shm->socket_fds[i], SHUT_RDWR);
		close(shm->socket_fds[i]);
	}

	destroy_maps();

	if (logging == TRUE)
		close_logfiles();

out:

	exit(ret);
}
Exemple #14
0
/**  This is where it all starts ++++++++++++++++++++++++++++++++++++++++++ 
 main is entered as a result of one of SEVERAL events:
  - Normal startup from press of reset button.
  - Battery inserted.
  - After DFU (Device Firmware Upgrade) at manufacturing Quality Assurance or user DFU.
  - WatchDogTimer expiration and its interrupt handler didn't feed new value.
  - Some error occured and
  - Spontenous unknown reset.
 All subsystems are initalized and any failures are noted and available later in init_status
 Since some events occur after tag is deployed and no one can see the LEDs the system continues operating.

 After initalizition (including setting up interrupts)
    we loop here calling app_sched_execute and sd_app_evt_wait 
*/
int main(void)
{
   // LEDs first (they're easy and cannot fail)  drivers/init/init.c
  init_leds();
  RED_LED_ON;

  if( init_log() ) { init_status |=LOG_FAILED_INIT; }
  else { NRF_LOG_INFO("LOG initalized \r\n"); } // subsequent initalizations assume log is working

  // start watchdog now in case program hangs up.
  // watchdog_default_handler logs error and resets the tag.
  init_watchdog(NULL);

  // Battery voltage initialization cannot fail under any reasonable circumstance.
  battery_voltage_init(); 
  vbat = getBattery();

  if( vbat < BATTERY_MIN_V ) { init_status |=BATTERY_FAILED_INIT; }
  else NRF_LOG_INFO("BATTERY initalized \r\n"); 

  if(init_sensors() == NRF_SUCCESS )
  {
    model_plus = true;
    NRF_LOG_INFO("Sensors initialized \r\n");  
  }

  // Init NFC ASAP in case we're waking from deep sleep via NFC (todo)
  // outputs ID:DEVICEID ,MAC:DEVICEADDR, SW:REVision
  set_nfc_callback(app_nfc_callback);
  if( init_nfc() ) { init_status |= NFC_FAILED_INIT; } 
  else { NRF_LOG_INFO("NFC init \r\n"); }

  pin_interrupt_init(); 

  if( pin_interrupt_enable(BSP_BUTTON_0, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIO_PIN_PULLUP, button_press_handler) ) 
  {
    init_status |= BUTTON_FAILED_INIT;
  }

  // Initialize BLE Stack. Starts LFCLK required for timer operation.
  if( init_ble() ) { init_status |= BLE_FAILED_INIT; }
  bluetooth_configure_advertisement_type(STARTUP_ADVERTISEMENT_TYPE);
  bluetooth_tx_power_set(BLE_TX_POWER);
  bluetooth_configure_advertising_interval(ADVERTISING_INTERVAL_STARTUP);
  advertisement_delay = NRF_FICR->DEVICEID[0]&0x0F;

  // Priorities 2 and 3 are after SD timing critical events. 
  // 6, 7 after SD non-critical events.
  // Triggers ADC, so use 3. 
  ble_radio_notification_init(3,
                              NRF_RADIO_NOTIFICATION_DISTANCE_800US,
                              on_radio_evt);

  // If GATT is enabled BLE init inits peer manager which uses flash.
  // BLE init should handle insufficient space gracefully (i.e. erase flash and proceed). 
  // Flash must be initialized after softdevice. 
  if(flash_init())
  {
    NRF_LOG_ERROR("Failed to init flash \r\n");
  }
  size_t flash_space_remaining = 0;
  flash_free_size_get(&flash_space_remaining);
  NRF_LOG_INFO("Largest continuous space remaining %d bytes\r\n", flash_space_remaining);
  if(4000 > flash_space_remaining)
  {
    NRF_LOG_INFO("Flash space is almost used, running gc\r\n")
    flash_gc_run();
    flash_free_size_get(&flash_space_remaining);
    NRF_LOG_INFO("Continuous space remaining after gc %d bytes\r\n", flash_space_remaining);
  }
  else if (flash_record_get(FDS_FILE_ID, FDS_RECORD_ID, sizeof(tag_mode), &tag_mode))
  {
   NRF_LOG_INFO("Did not find mode in flash, is this first boot? \r\n");
  }
  else 
  {
    NRF_LOG_INFO("Loaded mode %d from flash\r\n", tag_mode);
  }

  if( init_rtc() ) { init_status |= RTC_FAILED_INIT; }
  else { NRF_LOG_INFO("RTC initialized \r\n"); }

  // Initialize lis2dh12 and BME280 - TODO: Differentiate LIS2DH12 and BME280 
  if (model_plus)    
  {
    lis2dh12_reset(); // Clear memory.
    
    // Enable Low-To-Hi rising edge trigger interrupt on nRF52 to detect acceleration events.
    if (pin_interrupt_enable(INT_ACC2_PIN, NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIO_PIN_NOPULL, lis2dh12_int2_handler) )
    {
      init_status |= ACC_INT_FAILED_INIT;
    }
    
    nrf_delay_ms(10); // Wait for LIS reboot.
    // Enable XYZ axes.
    lis2dh12_enable();
    lis2dh12_set_scale(LIS2DH12_SCALE);
    lis2dh12_set_sample_rate(LIS2DH12_SAMPLERATE_RAWv1);
    lis2dh12_set_resolution(LIS2DH12_RESOLUTION);

    lis2dh12_set_activity_interrupt_pin_2(LIS2DH12_ACTIVITY_THRESHOLD);
    NRF_LOG_INFO("Accelerometer configuration done \r\n");

    // oversampling must be set for each used sensor.
    bme280_set_oversampling_hum  (BME280_HUMIDITY_OVERSAMPLING);
    bme280_set_oversampling_temp (BME280_TEMPERATURE_OVERSAMPLING);
    bme280_set_oversampling_press(BME280_PRESSURE_OVERSAMPLING);
    bme280_set_iir(BME280_IIR);
    bme280_set_interval(BME280_DELAY);
    bme280_set_mode(BME280_MODE_NORMAL);
    NRF_LOG_INFO("BME280 configuration done \r\n");
  }

  // Enter stored mode after boot - or default mode if store mode was not found
  app_sched_event_put (&tag_mode, sizeof(&tag_mode), change_mode);
  
  // Initialize repeated timer for sensor read and single-shot timer for button reset
  if( init_timer(main_timer_id, APP_TIMER_MODE_REPEATED, MAIN_LOOP_INTERVAL_RAW, main_timer_handler) )
  {
    init_status |= TIMER_FAILED_INIT;
  }
  
  if( init_timer(reset_timer_id, APP_TIMER_MODE_SINGLE_SHOT, BUTTON_RESET_TIME, reboot) )
  {
    init_status |= TIMER_FAILED_INIT;
  }
  // Init starts timers, stop the reset
  app_timer_stop(reset_timer_id);

  // Log errors, add a note to NFC, blink RED to visually indicate the problem
  if (init_status)
  { 
    snprintf((char* )NFC_message, NFC_message_length, "Error: %X", init_status);
    NRF_LOG_WARNING (" -- Initalization error :  %X \r\n", init_status);
    for ( int16_t i=0; i<13; i++)
    { 
      RED_LED_ON;
      nrf_delay_ms(500u);
      RED_LED_OFF;
      nrf_delay_ms(500u); 
    }
  }
  
  // Turn green led on if model+ with no errors.
  // Power manage turns led off
  if (model_plus & !init_status)
  {
    GREEN_LED_ON;
  }

  // Turn off red led, leave green on to signal model+ without errors
  RED_LED_OFF;

  // Wait for sensors to take first sample
  nrf_delay_ms(1000);
  // Get first sample from sensors
  app_sched_event_put (NULL, 0, main_sensor_task);
  app_sched_execute();

  // Start advertising 
  bluetooth_advertising_start(); 
  NRF_LOG_INFO("Advertising started\r\n");

  // Enter main loop. Executes tasks scheduled by timers and interrupts.
  for (;;)
  {
    app_sched_execute();
    // Sleep until next event.
    power_manage();
  }
}