Skip to content
Snippets Groups Projects
hardware.c 5.39 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "epicardium.h"
    
    #include "api/dispatcher.h"
    
    swym's avatar
    swym committed
    #include "usb/epc_usb.h"
    
    #include "modules/filesystem.h"
    #include "modules/log.h"
    
    #include "modules/modules.h"
    
    #include "modules/stream.h"
    
    
    #include "card10.h"
    
    #include "display.h"
    #include "leds.h"
    #include "pb.h"
    #include "pmic.h"
    #include "portexpander.h"
    
    #include "gpio.h"
    #include "i2c.h"
    
    #include "rtc.h"
    
    #include "trng.h"
    
    #include "wdt.h"
    
    
    /*
     * Early init is called at the very beginning and is meant for modules which
     * absolutely need to start as soon as possible.  hardware_early_init() blocks
     * which means code in here should be fast.
     */
    int hardware_early_init(void)
    {
    
    	/*
    	 * Watchdog timer
    	 */
    
    	/*
    	 * I2C bus for onboard peripherals (ie. PMIC, BMA400, BHI160, BME680,
    	 * ...)
    	 */
    	I2C_Shutdown(MXC_I2C1_BUS0);
    	I2C_Init(MXC_I2C1_BUS0, I2C_FAST_MODE, NULL);
    
    #ifndef CARD10_DEBUG_CORE1
    	/*
    	 * SAO I2C bus
    	 */
    	I2C_Shutdown(MXC_I2C0_BUS0);
    	I2C_Init(MXC_I2C0_BUS0, I2C_FAST_MODE, NULL);
    #endif
    
    	/*
    	 * GPIO peripheral.
    	 */
    	GPIO_Init();
    
    
    	/* Set the power hold pin, so the PMIC does not turn off again */
    	const gpio_cfg_t pwr_hold_pin = {
    		PORT_0, PIN_30, GPIO_FUNC_OUT, GPIO_PAD_NONE
    	};
    	GPIO_Config(&pwr_hold_pin);
    	GPIO_OutSet(&pwr_hold_pin);
    
    
    	/*
    	 * PMIC (MAX77650)
    	 */
    	pmic_init();
    	pmic_set_led(0, 0);
    	pmic_set_led(1, 0);
    	pmic_set_led(2, 0);
    
    	/*
    	 * Harmonic Board Portexpander
    	 */
    	portexpander_init();
    
    
    	/*
    	 * RNG
    	 */
    	TRNG_Init(NULL);
    
    
    	/* Enable 32 kHz output */
    	while (RTC_SquareWave(
    		       MXC_RTC,
    		       SQUARE_WAVE_ENABLED,
    		       F_32KHZ,
    		       NOISE_IMMUNE_MODE,
    		       NULL) == E_BUSY
    	)
    		;
    
    	/* If we don't have a valid time yet, set it to 2019-01-01 */
    
    	if (RTC_GetSecond() < 1546300800L) {
    
    		epic_rtc_set_milliseconds(1546300800UL * 1000);
    	}
    
    
    	/*
    	 * SPI for ECG
    	 */
    	const sys_cfg_spi_t spi17y_master_cfg = {
    		.map = MAP_A,
    		.ss0 = Enable,
    		.ss1 = Disable,
    		.ss2 = Disable,
    	};
    
    	if (SPI_Init(SPI0, 0, SPI_SPEED, spi17y_master_cfg) != 0) {
    		LOG_ERR("init", "Error configuring SPI");
    		while (1)
    			;
    	}
    
    
    	/*
    	 * The bootloader has already initialized the display, so we only need
    	 * to do the bare minimum here (mostly the gfx datastructures).
    	 */
    	display_init_slim();
    
    
    #ifdef CARD10_DEBUG_CORE1
    	/*
    	 * The SAO pins can be reconfigured for SWCLK2 and SWDIO2 which allows
    	 * debugging core 1.  This feature can optionally be enabled at
    	 * compile-time.
    	 */
    	LOG_WARN("init", "Core 1 Debugger Mode");
    	static const gpio_cfg_t swclk = {
    		PORT_0,
    		PIN_7,
    		GPIO_FUNC_ALT3,
    		GPIO_PAD_NONE,
    	};
    	static const gpio_cfg_t swdio = {
    		PORT_0,
    		PIN_6,
    		GPIO_FUNC_ALT3,
    		GPIO_PAD_NONE,
    	};
    
    	GPIO_Config(&swclk);
    	GPIO_Config(&swdio);
    #endif /* CARD10_DEBUG_CORE1 */
    
    	/*
    	 * Enable SEV-ON-PEND which is needed for proper working of the FreeRTOS
    	 * tickless idle sleep in Epicardium.
    	 */
    	SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
    
    	/*
    	 * USB-Serial
    	 */
    
    swym's avatar
    swym committed
    	if (epic_usb_cdcacm() < 0) {
    		LOG_ERR("startup", "USB-Serial unavailable");
    
    	}
    
    	/*
    	 * Flash & FatFS
    	 */
    	fatfs_init();
    
    	/*
    	 * API Dispatcher & API Interrupts
    	 */
    
    	api_dispatcher_init();
    
    	/*
    	 * Sensor streams
    	 */
    	stream_init();
    
    
    	/*
    	 * Hardware/Peripheral Locks
    	 */
    	hwlock_init();
    
    
    	/*
    	 * API Dispatcher Mutex
    	 */
    	dispatcher_mutex_init();
    
    
    	/*
    	 * MAX30001 mutex init
    	 */
    	max30001_mutex_init();
    
    
    	/*
    	 * max86150 mutex init
    	 */
    	max86150_mutex_init();
    
    
    	/* Allow user space to trigger interrupts.
    	 * Used for BLE, not sure if needed. */
    	SCB->CCR |= SCB_CCR_USERSETMPEND_Msk;
    
    	return 0;
    }
    
    /*
     * hardware_init() is called after the core has been bootstrapped and is meant
     * for less critical initialization steps.  Modules which initialize here should
     * be robust against a l0dable using their API before initialization is done.
     *
     * Ideally, acquire a lock in hardware_early_init() and release it in
     * hardware_init() once initialization is done.
     */
    int hardware_init(void)
    {
    
    	/* Watchdog clearer software timer */
    	watchdog_clearer_init();
    
    
    	/* Light Sensor */
    
    	LOG_DEBUG("init", "Starting light sensor ...");
    
    	epic_light_sensor_run();
    
    
    	return 0;
    }
    
    /*
     * hardware_reset() is called whenever a new l0dable is started.  hardware_reset()
     * should bring all peripherals back into a known initial state.  This does not
     * necessarily mean resetting the peripheral entirely but hardware_reset()
     * should at least bring the API facing part of a peripheral back into the state
     * a fresh booted l0dable expects.
     */
    int hardware_reset(void)
    {
    
    	/*
    	 * API Dispatcher & API Interrupts
    	 */
    
    	api_dispatcher_init();
    
    
    	/*
    	 * close all FDs currently owned by core1
    	 */
    	fatfs_close_all(EPICARDIUM_COREMASK_1);
    
    
    	/* Personal State */
    	const int personal_state_is_persistent =
    		epic_personal_state_is_persistent();
    
    	if (personal_state_is_persistent == 0) {
    		epic_personal_state_set(STATE_NONE, 0);
    	}
    
    
    	if (personal_state_is_persistent) {
    		epic_leds_clear_all(0, 0, 0);
    	} else {
    		leds_init();
    	}
    
    	epic_leds_set_rocket(0, 0);
    	epic_leds_set_rocket(1, 0);
    	epic_leds_set_rocket(2, 0);
    
    	/*
    	 * Display
    	 */
    	display_init_slim();
    
    	epic_disp_backlight(20);
    
    	/*
    	 * Vibration Motor
    	 */
    	epic_vibra_set(false);
    
    	/*
    	 * BHI160
    	 */
    	epic_bhi160_disable_all_sensors();
    
    
    	/*
    	 * BME680 Sensor
    	 */
    	epic_bme680_deinit();
    
    
    	epic_max30001_disable_sensor();
    
    
    	epic_max86150_disable_sensor();
    
    
    	/*
    	 * BLE
    	 */
    	epic_ble_set_bondable(false);