Esempio n. 1
0
static int test_request(void)
{
	uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH);

	plug_in_source(0, 0);
	task_wake(PD_PORT_TO_TASK_ID(0));
	task_wait_event(2 * PD_T_CC_DEBOUNCE + 100 * MSEC);
	TEST_ASSERT(pd_port[0].polarity == 0);

	/* We're in SNK_DISCOVERY now. Let's send the source cap. */
	simulate_source_cap(0);
	task_wait_event(30 * MSEC);
	TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[0].msg_rx_id));

	/* Wait for the power request */
	task_wake(PD_PORT_TO_TASK_ID(0));
	task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */
	inc_rx_id(0);

	/* Process the request */
	TEST_ASSERT(pd_test_tx_msg_verify_sop(0));
	TEST_ASSERT(pd_test_tx_msg_verify_short(0,
			PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
				  pd_port[0].msg_tx_id, 1)));
	TEST_ASSERT(pd_test_tx_msg_verify_word(0, expected_rdo));
	TEST_ASSERT(pd_test_tx_msg_verify_crc(0));
	TEST_ASSERT(pd_test_tx_msg_verify_eop(0));
	inc_tx_id(0);

	/* We're done */
	unplug(0);
	return EC_SUCCESS;
}
Esempio n. 2
0
static int test_sink(void)
{
	int i;

	plug_in_sink(1, 1);
	task_wake(PD_PORT_TO_TASK_ID(1));
	task_wait_event(250 * MSEC); /* tTypeCSinkWaitCap: 210~250 ms */
	TEST_ASSERT(pd_port[1].polarity == 1);

	/* The source cap should be sent */
	TEST_ASSERT(pd_test_tx_msg_verify_sop(1));
	TEST_ASSERT(pd_test_tx_msg_verify_short(1,
			PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
				  PD_ROLE_DFP, pd_port[1].msg_tx_id,
				  pd_src_pdo_cnt)));
	for (i = 0; i < pd_src_pdo_cnt; ++i)
		TEST_ASSERT(pd_test_tx_msg_verify_word(1, pd_src_pdo[i]));
	TEST_ASSERT(pd_test_tx_msg_verify_crc(1));
	TEST_ASSERT(pd_test_tx_msg_verify_eop(1));

	/* Looks good. Ack the source cap. */
	simulate_goodcrc(1, PD_ROLE_SINK, pd_port[1].msg_tx_id);
	task_wake(PD_PORT_TO_TASK_ID(1));
	usleep(30 * MSEC);
	inc_tx_id(1);

	/* We're done */
	unplug(1);
	return EC_SUCCESS;
}
Esempio n. 3
0
static int test_partial_load(void)
{
	/* We have a 3A charger, but we just want 1.5A */
	system_load_current_ma = 1500;
	plug_charger(CHARGE_SUPPLIER_TEST4, 0, 500, 3000, 2500);

	/* We should end up with a little bit more than 1.5A */
	TEST_ASSERT(wait_stable_no_overcurrent());
	TEST_ASSERT(is_in_range(charge_limit_ma, 1500, 1600));

	/* Ok someone just started watching YouTube */
	system_load_current_ma = 2000;
	TEST_ASSERT(wait_stable_no_overcurrent());
	TEST_ASSERT(is_in_range(charge_limit_ma, 2000, 2100));

	/* Somehow the system load increases again */
	system_load_current_ma = 2600;
	while (task_wait_event(RAMP_STABLE_DELAY) == TASK_EVENT_OVERCURRENT) {
		/* Charger goes away but comes back after 0.6 seconds */
		unplug_charger();
		usleep(MSEC * 600);
		plug_charger(CHARGE_SUPPLIER_TEST4, 0, 500, 3000, 2500);
		usleep(CHARGE_DETECT_DELAY_TEST);
		/* Ramp restarts at 500 mA */
		TEST_ASSERT(is_in_range(charge_limit_ma, 500, 700));
	}

	/* Alright the charger isn't powerful enough, so we'll stop at 2.5A */
	TEST_ASSERT(is_in_range(charge_limit_ma, 2300, 2500));

	TEST_ASSERT(unplug_charger_and_check());
	return EC_SUCCESS;
}
Esempio n. 4
0
void power_button_task(void)
{
	uint64_t t;
	uint64_t tsleep;

	while (1) {
		t = get_time().val;

		/* Update state machine */
		CPRINTS("PB task %d = %s", pwrbtn_state,
			state_names[pwrbtn_state]);

		state_machine(t);

		/* Sleep until our next timeout */
		tsleep = -1;
		if (tnext_state && tnext_state < tsleep)
			tsleep = tnext_state;
		t = get_time().val;
		if (tsleep > t) {
			unsigned d = tsleep == -1 ? -1 : (unsigned)(tsleep - t);
			/*
			 * (Yes, the conversion from uint64_t to unsigned could
			 * theoretically overflow if we wanted to sleep for
			 * more than 2^32 us, but our timeouts are small enough
			 * that can't happen - and even if it did, we'd just go
			 * back to sleep after deciding that we woke up too
			 * early.)
			 */
			CPRINTS("PB task %d = %s, wait %d", pwrbtn_state,
			state_names[pwrbtn_state], d);
			task_wait_event(d);
		}
	}
}
Esempio n. 5
0
File: spi.c Progetto: longsleep/ec
void usb_spi_task(void)
{
	/* Remap SPI2 to DMA channels 6 and 7 */
	STM32_SYSCFG_CFGR1 |= (1 << 24);

	gpio_config_module(MODULE_SPI_MASTER, 1);

	/* Set all four SPI pins to high speed */
	STM32_GPIO_OSPEEDR(GPIO_B) |= 0xff000000;

	/* Enable clocks to SPI2 module */
	STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2;

	/* Reset SPI2 */
	STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2;
	STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2;

	spi_enable(1);

	while (1) {
		task_wait_event(-1);

		while (usb_spi_service_request(&usb_spi))
			;
	}
}
Esempio n. 6
0
static enum power_state power_wait_s5_rtc_reset(void)
{
	static int s5_exit_tries;

	/* Wait for S5 exit and then attempt RTC reset */
	while ((power_get_signals() & IN_PCH_SLP_S4_DEASSERTED) == 0) {
		/* Handle RSMRST passthru event while waiting */
		handle_rsmrst(POWER_S5);
		if (task_wait_event(SECOND*4) == TASK_EVENT_TIMER) {
			CPRINTS("timeout waiting for S5 exit");
			chipset_force_g3();

			/* Assert RTCRST# and retry 5 times */
			board_rtc_reset();

			if (++s5_exit_tries > 4) {
				s5_exit_tries = 0;
				return POWER_G3; /* Stay off */
			}

			udelay(10 * MSEC);
			return POWER_G3S5; /* Power up again */
		}
	}

	s5_exit_tries = 0;
	return POWER_S5S3; /* Power up to next state */
}
Esempio n. 7
0
uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us)
{
	uint64_t deadline = get_time().val + timeout_us;
	uint32_t events = 0;
	int time_remaining_us = timeout_us;

	/* Add the timer event to the mask so we can indicate a timeout */
	event_mask |= TASK_EVENT_TIMER;

	while (!(events & event_mask)) {
		/* Collect events to re-post later */
		events |= task_wait_event(time_remaining_us);

		time_remaining_us = deadline - get_time().val;
		if (timeout_us > 0 && time_remaining_us <= 0) {
			/* Ensure we return a TIMER event if we timeout */
			events |= TASK_EVENT_TIMER;
			break;
		}
	}

	/* Re-post any other events collected */
	if (events & ~event_mask)
		tasks[task_get_current()].event |= events & ~event_mask;

	return events & event_mask;
}
Esempio n. 8
0
static int command_accel_read_xyz(int argc, char **argv)
{
	char *e;
	int id, n = 1, ret;
	struct motion_sensor_t *sensor;
	vector_3_t v;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	/* First argument is sensor id. */
	id = strtoi(argv[1], &e, 0);

	if (*e || id < 0 || id >= motion_sensor_count)
		return EC_ERROR_PARAM1;

	if (argc >= 3)
		n = strtoi(argv[2], &e, 0);

	sensor = &motion_sensors[id];

	while ((n == -1) || (n-- > 0)) {
		ret = sensor->drv->read(sensor, v);
		if (ret == 0)
			ccprintf("Current data %d: %-5d %-5d %-5d\n",
				 id, v[X], v[Y], v[Z]);
		else
			ccprintf("vector not ready\n");
		ccprintf("Last calib. data %d: %-5d %-5d %-5d\n",
			 id, sensor->xyz[X], sensor->xyz[Y], sensor->xyz[Z]);
		task_wait_event(MIN_MOTION_SENSE_WAIT_TIME);
	}
	return EC_SUCCESS;
}
Esempio n. 9
0
uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait)
{
	tasks[tskid].event = event;
	if (wait)
		return task_wait_event(-1);
	return 0;
}
Esempio n. 10
0
void usb_charger_task(void)
{
	int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
	uint32_t evt;

	/* Initialize chip and enable interrupts */
	pi3usb9281_init(port);

	usb_charger_bc12_detect(port);

	while (1) {
		/* Wait for interrupt */
		evt = task_wait_event(-1);

		/* Interrupt from the Pericom chip, determine charger type */
		if (evt & USB_CHG_EVENT_BC12)
			usb_charger_bc12_detect(port);

		/*
		 * Re-enable interrupts on pericom charger detector since the
		 * chip may periodically reset itself, and come back up with
		 * registers in default state. TODO(crosbug.com/p/33823): Fix
		 * these unwanted resets.
		 */
		if (evt & USB_CHG_EVENT_VBUS) {
			pi3usb9281_enable_interrupts(port);
#ifndef CONFIG_USB_PD_TCPM_VBUS
			CPRINTS("VBUS p%d %d", port,
				pd_snk_is_vbus_provided(port));
#endif
		}
	}
}
Esempio n. 11
0
static enum cts_rc timer_calibration_test(void)
{
	/* Error margin: +/-2 msec (0.2% for one second) */
	const int32_t margin = 2 * MSEC;
	int32_t elapsed, delta;
	timestamp_t t0, t1;

	gpio_enable_interrupt(GPIO_CTS_NOTIFY);
	interrupt_enable();

	sync();
	t0 = get_time();
	/* Wait for interrupt */
	task_wait_event(-1);
	t1 = get_time();

	elapsed = (int32_t)(t1.val - t0.val);
	delta = elapsed - SECOND;
	if (delta < -margin) {
		CPRINTS("DUT clock runs too fast: %+d usec", delta);
		return CTS_RC_FAILURE;
	}
	if (margin < delta) {
		CPRINTS("DUT clock runs too slow: %+d usec", delta);
		return CTS_RC_FAILURE;
	}

	return CTS_RC_SUCCESS;
}
Esempio n. 12
0
enum cts_rc test_task_priority(void)
{
	uint32_t event;

	repeat_count = 2;

	task_wake(TASK_ID_A);
	task_wake(TASK_ID_C);

	event = task_wait_event(5 * SECOND);

	if (event != TASK_EVENT_WAKE) {
		CPRINTS("Woken up by unexpected event: 0x%08x", event);
		return CTS_RC_FAILURE;
	}

	if (wake_count[0] != repeat_count - 1
			|| wake_count[1] != repeat_count - 1) {
		CPRINTS("Unexpected counter values: %d %d %d",
			wake_count[0], wake_count[1], wake_count[2]);
		return CTS_RC_FAILURE;
	}

	/* TODO: Verify no tasks are ready, no events are pending. */
	if (*task_get_event_bitmap(TASK_ID_A)
			|| *task_get_event_bitmap(TASK_ID_B)
			|| *task_get_event_bitmap(TASK_ID_C)) {
		CPRINTS("Events are pending");
		return CTS_RC_FAILURE;
	}

	return CTS_RC_SUCCESS;
}
Esempio n. 13
0
static int test_overcurrent_after_switch_outlet(void)
{
	system_load_current_ma = 3000;
	/* Here's a less powerful charger */
	plug_charger(CHARGE_SUPPLIER_TEST5, 0, 500, 3000, 1500);
	usleep(SECOND * 5);

	/* Now the user decides to move it to a nearby outlet */
	unplug_charger();
	usleep(SECOND * 1.5);
	plug_charger(CHARGE_SUPPLIER_TEST5, 0, 500, 3000, 1500);

	/* Okay the user is satisified */
	while (task_wait_event(RAMP_STABLE_DELAY) == TASK_EVENT_OVERCURRENT) {
		/* Charger goes away but comes back after 0.6 seconds */
		unplug_charger();
		usleep(MSEC * 600);
		plug_charger(CHARGE_SUPPLIER_TEST5, 0, 500, 3000, 1500);
		usleep(CHARGE_DETECT_DELAY_TEST);
		/* Ramp restarts at 500 mA */
		TEST_ASSERT(is_in_range(charge_limit_ma, 500, 700));
	}

	TEST_ASSERT(is_in_range(charge_limit_ma, 1300, 1500));

	TEST_ASSERT(unplug_charger_and_check());
	return EC_SUCCESS;
}
Esempio n. 14
0
void *_task_start_impl(void *a)
{
	long tid = (long)a;
	struct task_args *arg = task_info + tid;
	my_task_id = tid;
	pthread_mutex_lock(&run_lock);

	/* Wait for scheduler */
	task_wait_event(1);
	tasks[tid].event = 0;

	/* Start the task routine */
	(arg->routine)(arg->d);

	/* Catch exited routine */
	while (1)
		task_wait_event(-1);
}
Esempio n. 15
0
void task_tick(void *data)
{
	task_wait_event(-1);
	ccprintf("\n[starting Task T]\n");

	/* Wake up every tick */
	while (1)
		/* Wait for timer interrupt message */
		usleep(3000);
}
Esempio n. 16
0
static void key_test(va_list args)
  {
  word c;
  do
     {
     c = *(word *)task_wait_event(E_KEYBOARD);
     }
  while ((c & 0xff) !='!');
  puts("\x7");
  }
Esempio n. 17
0
CONFIG_TASK_LIST
CONFIG_TEST_TASK_LIST
#undef TASK

/* Idle task */
void __idle(void *d)
{
	while (1)
		task_wait_event(-1);
}
Esempio n. 18
0
void elan_tp_task(void)
{
	elan_tp_init();

	gpio_enable_interrupt(GPIO_TOUCHPAD_INT);

	while (1) {
		task_wait_event(-1);

		elan_tp_read_report();
	}
}
Esempio n. 19
0
/**
 * Wait for the power button to be released
 *
 * @param timeout_us Timeout in microseconds, or -1 to wait forever
 * @return EC_SUCCESS if ok, or
 *         EC_ERROR_TIMEOUT if power button failed to release
 */
int power_button_wait_for_release(int timeout_us)
{
	timestamp_t deadline;
	timestamp_t now = get_time();

	deadline.val = now.val + timeout_us;

	while (!power_button_is_stable || power_button_is_pressed()) {
		now = get_time();
		if (timeout_us < 0) {
			task_wait_event(-1);
		} else if (timestamp_expired(deadline, &now) ||
			(task_wait_event(deadline.val - now.val) ==
			TASK_EVENT_TIMER)) {
			CPRINTS("power button not released in time");
			return EC_ERROR_TIMEOUT;
		}
	}

	CPRINTS("power button released in time");
	return EC_SUCCESS;
}
Esempio n. 20
0
/*
 *  This is for NOT having enough hibernate (more precisely, the stand-by mode)
 *  wake-up source pin. STM32L100 supports 3 wake-up source pins:
 *
 *     WKUP1 (PA0)  -- used for ACOK_PMU
 *     WKUP2 (PC13) -- used for LID_OPEN
 *     WKUP3 (PE6)  -- cannot be used due to IC package.
 *
 *  However, we need the power button as a wake-up source as well and there is
 *  no available pin for us (we don't want to move the ACOK_PMU pin).
 *
 *  Fortunately, the STM32L is low-power enough so that we don't need the
 *  super-low-power mode. So, we fake this hibernate mode and accept the
 *  following wake-up source.
 *
 *     RTC alarm  (faked as well).
 *     Power button
 *     Lid open
 *     AC detected
 *
 *  The original issue is here: crosbug.com/p/25435.
 */
void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
{
	int i;
	fake_hibernate = 1;

#ifdef CONFIG_POWER_COMMON
	/*
	 * A quick hack to stop annoying messages from charger task.
	 *
	 * When the battery is under 3%, the power task would call
	 * power_off() to shutdown AP. However, the power_off() would
	 * notify the HOOK_CHIPSET_SHUTDOWN, where the last hook is
	 * charge_shutdown() and it hibernates the power task (infinite
	 * loop -- not real CPU hibernate mode). Unfortunately, the
	 * charger task is still running. It keeps generating annoying
	 * log message.
	 *
	 * Thus, the hack is to set the power state machine (before we
	 * enter infinite loop) so that the charger task thinks the AP
	 * is off and stops generating messages.
	 */
	power_set_state(POWER_G3);
#endif

	/*
	 * Change keyboard outputs to high-Z to reduce power draw.
	 * We don't need corresponding code to change them back,
	 * because fake hibernate is always exited with a reboot.
	 *
	 * A little hacky to do this here.
	 */
	for (i = GPIO_KB_OUT00; i < GPIO_KB_OUT00 + KEYBOARD_COLS; i++)
		gpio_set_flags(i, GPIO_INPUT);

	ccprints("fake hibernate. waits for power button/lid/RTC/AC");
	cflush();

	if (seconds || microseconds) {
		if (seconds)
			sleep(seconds);
		if (microseconds)
			usleep(microseconds);
	} else {
		while (1)
			task_wait_event(-1);
	}

	ccprints("fake RTC alarm fires. resets EC");
	cflush();
	system_reset(SYSTEM_RESET_HARD);
}
Esempio n. 21
0
void gesture_calc(void)
{
	/* Only check for gesture if lid is closed and tap detection is on */
	if (!tap_detection || lid_is_open())
		return;

	if (gesture_tap_for_battery()) {
		CPRINTS("Double Tap!");
		lightbar_sequence(LIGHTBAR_TAP);

		/* Don't need to run motion sense task for a while */
		task_wait_event(500 * MSEC);
	}
}
Esempio n. 22
0
void pd_command_task(void)
{
	/* On startup exchange status with the PD */
	pd_exchange_status();

	while (1) {
		/* Wait for the next command event */
		int evt = task_wait_event(-1);

		/* Process event to send status to PD */
		if (evt & TASK_EVENT_EXCHANGE_PD_STATUS)
			pd_exchange_status();
	}
}
Esempio n. 23
0
void als_task(void)
{
	int i, val;
	uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_ALS);
	uint16_t als_data;

	while (1) {
		for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++) {
			als_data = als_read(i, &val) == EC_SUCCESS ? val : 0;
			mapped[i] = als_data;
		}

		task_wait_event(SECOND);
	}
}
void host_command_task(void)
{
	host_command_init();

	while (1) {
		/* Wait for the next command event */
		int evt = task_wait_event(-1);

		/* Process it */
		if ((evt & TASK_EVENT_CMD_PENDING) && pending_args) {
			pending_args->result =
					host_command_process(pending_args);
			host_send_response(pending_args);
		}
	}
}
Esempio n. 25
0
enum cts_rc test_task_disable_irq(void)
{
	uint32_t event;

	wake_me_up = 1;

	task_disable_irq(CTS_IRQ_NUMBER);
	/* Sleep and wait for interrupt. This should time out. */
	event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 2);
	if (event != TASK_EVENT_TIMER) {
		CPRINTS("Woken up by unexpected event: 0x%08x", event);
		return CTS_RC_FAILURE;
	}
	task_enable_irq(CTS_IRQ_NUMBER);

	return CTS_RC_SUCCESS;
}
Esempio n. 26
0
enum cts_rc test_nested_interrupt_high_low(void)
{
	uint32_t event;

	event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 4);
	if (event != TASK_EVENT_TIMER) {
		CPRINTS("Woken up by unexpected event: 0x%08x", event);
		return CTS_RC_FAILURE;
	}

	if (memcmp(state, "BCAD", sizeof(state))) {
		CPRINTS("State transition differs from expectation");
		return CTS_RC_FAILURE;
	}

	return CTS_RC_SUCCESS;
}
Esempio n. 27
0
enum cts_rc test_task_wait_event(void)
{
	uint32_t event;

	wake_me_up = 1;

	/* Sleep and wait for interrupt. This shouldn't time out. */
	event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 2);
	if (event != TASK_EVENT_WAKE) {
		CPRINTS("Woken up by unexpected event: 0x%08x", event);
		return CTS_RC_FAILURE;
	}
	if (!got_interrupt) {
		CPRINTS("Interrupt context not detected");
		return CTS_RC_TIMEOUT;
	}

	return CTS_RC_SUCCESS;
}
Esempio n. 28
0
static int i2c_write_raw_slave(int port, void *buf, int len)
{
	stm32_dma_chan_t *chan;
	int rv;

	/* we don't want to race with TxE interrupt event */
	disable_i2c_interrupt(port);

	/* Configuring DMA1 channel DMAC_SLAVE_TX */
	enable_ack(port);
	chan = dma_get_channel(DMAC_SLAVE_TX);
	dma_prepare_tx(dma_tx_option + port, len, buf);

	/* Start the DMA */
	dma_go(chan);

	/* Configuring i2c to use DMA */
	STM32_I2C_CR2(port) |= (1 << 11);

	if (in_interrupt_context()) {
		/* Poll for the transmission complete flag */
		dma_wait(DMAC_SLAVE_TX);
		dma_clear_isr(DMAC_SLAVE_TX);
	} else {
		/* Wait for the transmission complete Interrupt */
		dma_enable_tc_interrupt(DMAC_SLAVE_TX);
		rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
		dma_disable_tc_interrupt(DMAC_SLAVE_TX);

		if (!(rv & TASK_EVENT_WAKE)) {
			CPRINTS("Slave timeout, resetting i2c");
			i2c_init_port(port);
		}
	}

	dma_disable(DMAC_SLAVE_TX);
	STM32_I2C_CR2(port) &= ~(1 << 11);

	enable_i2c_interrupt(port);

	return len;
}
Esempio n. 29
0
void cts_task(void)
{
	enum cts_rc rc;
	int i;

	task_wake(TASK_ID_TICK);

	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		clear_state();
		rc = tests[i].run();
		CPRINTF("\n%s %d\n", tests[i].name, rc);
		cflush();
	}

	CPRINTS("Task test suite finished");
	cflush();

	/* Sleep forever */
	task_wait_event(-1);
}
Esempio n. 30
0
void task_abc(void *data)
{
	int task_id = task_get_current();
	int id = task_id - TASK_ID_A;
	task_id_t next = task_id + 1;

	if (next > TASK_ID_C)
		next = TASK_ID_A;

	task_wait_event(-1);

	CPRINTS("%c Starting", 'A' + id);
	cflush();

	while (1) {
		wake_count[id]++;
		if (id == 2 && wake_count[id] == repeat_count)
			task_set_event(TASK_ID_CTS, TASK_EVENT_WAKE, 1);
		else
			task_set_event(next, TASK_EVENT_WAKE, 1);
	}
}