Пример #1
0
static int amg88xx_init_device(struct device *dev)
{
	struct amg88xx_data *drv_data = dev->driver_data;
	u8_t tmp;

	if (amg88xx_reg_read(drv_data, AMG88XX_PCLT, &tmp)) {
		SYS_LOG_ERR("Failed to read Power mode");
		return -EIO;
	}

	SYS_LOG_DBG("Power mode 0x%02x", tmp);
	if (tmp != AMG88XX_PCLT_NORMAL_MODE) {
		if (amg88xx_reg_write(drv_data, AMG88XX_PCLT,
				       AMG88XX_PCLT_NORMAL_MODE)) {
			return -EIO;
		}
		k_busy_wait(AMG88XX_WAIT_MODE_CHANGE_US);
	}

	if (amg88xx_reg_write(drv_data, AMG88XX_RST,
			      AMG88XX_RST_INITIAL_RST)) {
		return -EIO;
	}

	k_busy_wait(AMG88XX_WAIT_INITIAL_RESET_US);

	if (amg88xx_reg_write(drv_data, AMG88XX_FPSC, AMG88XX_FPSC_10FPS)) {
		return -EIO;
	}

	SYS_LOG_DBG("");

	return 0;
}
Пример #2
0
void start_arc(unsigned int reset_vector)
{

	if (reset_vector != 0) {
		curie_shared_data->arc_start = reset_vector;
	}

	curie_shared_data->flags = 0;
	k_busy_wait(ARCSTART_DELAY);

	*SCSS_SS_CFG_REG |= ARC_RUN_REQ_A;

	k_busy_wait(ARCSTART_DELAY);
}
Пример #3
0
static int lps25hb_init_chip(struct device *dev)
{
	struct lps25hb_data *data = dev->driver_data;
	const struct lps25hb_config *config = dev->config->config_info;
	u8_t chip_id;

	lps25hb_power_ctrl(dev, 0);
	k_busy_wait(50 * USEC_PER_MSEC);

	if (lps25hb_power_ctrl(dev, 1) < 0) {
		SYS_LOG_DBG("failed to power on device");
		return -EIO;
	}

	k_busy_wait(20 * USEC_PER_MSEC);

	if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
			      LPS25HB_REG_WHO_AM_I, &chip_id) < 0) {
		SYS_LOG_DBG("failed reading chip id");
		goto err_poweroff;
	}
	if (chip_id != LPS25HB_VAL_WHO_AM_I) {
		SYS_LOG_DBG("invalid chip id 0x%x", chip_id);
		goto err_poweroff;
	}

	SYS_LOG_DBG("chip id 0x%x", chip_id);

	if (lps25hb_set_odr_raw(dev, LPS25HB_DEFAULT_SAMPLING_RATE)
				< 0) {
		SYS_LOG_DBG("failed to set sampling rate");
		goto err_poweroff;
	}

	if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
				LPS25HB_REG_CTRL_REG1,
				LPS25HB_MASK_CTRL_REG1_BDU,
				(1 << LPS25HB_SHIFT_CTRL_REG1_BDU)) < 0) {
		SYS_LOG_DBG("failed to set BDU");
		goto err_poweroff;
	}

	return 0;

err_poweroff:
	lps25hb_power_ctrl(dev, 0);
	return -EIO;
}
Пример #4
0
/* a thread busy waits, then reports through a fifo */
static void test_busy_wait(void *mseconds, void *arg2, void *arg3)
{
	u32_t usecs;

	ARG_UNUSED(arg2);
	ARG_UNUSED(arg3);

	usecs = (int)mseconds * 1000;

	TC_PRINT("Thread busy waiting for %d usecs\n", usecs);
	k_busy_wait(usecs);
	TC_PRINT("Thread busy waiting completed\n");

	/*
	 * Ideally the test should verify that the correct number of ticks
	 * have elapsed. However, when running under QEMU, the tick interrupt
	 * may be processed on a very irregular basis, meaning that far
	 * fewer than the expected number of ticks may occur for a given
	 * number of clock cycles vs. what would ordinarily be expected.
	 *
	 * Consequently, the best we can do for now to test busy waiting is
	 * to invoke the API and verify that it returns. (If it takes way
	 * too long, or never returns, the main test task may be able to
	 * time out and report an error.)
	 */

	k_sem_give(&reply_timeout);
}
Пример #5
0
static int ak8975_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct ak8975_data *drv_data = dev->driver_data;
	u8_t buf[6];

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);

	if (i2c_reg_write_byte(drv_data->i2c, CONFIG_AK8975_I2C_ADDR,
			       AK8975_REG_CNTL, AK8975_MODE_MEASURE) < 0) {
		LOG_ERR("Failed to start measurement.");
		return -EIO;
	}

	k_busy_wait(AK8975_MEASURE_TIME_US);

	if (i2c_burst_read(drv_data->i2c, CONFIG_AK8975_I2C_ADDR,
			   AK8975_REG_DATA_START, buf, 6) < 0) {
		LOG_ERR("Failed to read sample data.");
		return -EIO;
	}

	drv_data->x_sample = sys_le16_to_cpu(buf[0] | (buf[1] << 8));
	drv_data->y_sample = sys_le16_to_cpu(buf[2] | (buf[3] << 8));
	drv_data->z_sample = sys_le16_to_cpu(buf[4] | (buf[5] << 8));

	return 0;
}
Пример #6
0
int bmg160_init(struct device *dev)
{
	const struct bmg160_device_config *cfg = dev->config->config_info;
	struct bmg160_device_data *bmg160 = dev->driver_data;
	u8_t chip_id = 0;
	u16_t range_dps;

	bmg160->i2c = device_get_binding((char *)cfg->i2c_port);
	if (!bmg160->i2c) {
		SYS_LOG_DBG("I2C master controller not found!");
		return -EINVAL;
	}

	k_sem_init(&bmg160->sem, 1, UINT_MAX);

	if (bmg160_read_byte(dev, BMG160_REG_CHIPID, &chip_id) < 0) {
		SYS_LOG_DBG("Failed to read chip id.");
		return -EIO;
	}

	if (chip_id != BMG160_CHIP_ID) {
		SYS_LOG_DBG("Unsupported chip detected (0x%x)!", chip_id);
		return -ENODEV;
	}

	/* reset the chip */
	bmg160_write_byte(dev, BMG160_REG_BGW_SOFTRESET, BMG160_RESET);

	k_busy_wait(1000); /* wait for the chip to come up */

	if (bmg160_write_byte(dev, BMG160_REG_RANGE,
			      BMG160_DEFAULT_RANGE) < 0) {
		SYS_LOG_DBG("Failed to set range.");
		return -EIO;
	}

	range_dps = bmg160_gyro_range_map[BMG160_DEFAULT_RANGE];

	bmg160->scale = BMG160_RANGE_TO_SCALE(range_dps);

	if (bmg160_write_byte(dev, BMG160_REG_BW, BMG160_DEFAULT_ODR) < 0) {
		SYS_LOG_DBG("Failed to set sampling frequency.");
		return -EIO;
	}

	/* disable interrupts */
	if (bmg160_write_byte(dev, BMG160_REG_INT_EN0, 0) < 0) {
		SYS_LOG_DBG("Failed to disable all interrupts.");
		return -EIO;
	}

#ifdef CONFIG_BMG160_TRIGGER
	bmg160_trigger_init(dev);
#endif

	dev->driver_api = &bmg160_api;

	return 0;
}
Пример #7
0
void main(void)
{
	struct device *rtc_dev;
	struct rtc_config config;
	u32_t now;

	printk("LMT: Quark SE PM Multicore Demo\n");

	k_fifo_init(&fifo);

	build_suspend_device_list();

	ipm = device_get_binding("alarm_notification");
	if (!ipm) {
		printk("Error: Failed to get IPM device\n");
		return;
	}

	rtc_dev = device_get_binding("RTC_0");
	if (!rtc_dev) {
		printk("Error: Failed to get RTC device\n");
		return;
	}

	rtc_enable(rtc_dev);

	/* In QMSI, in order to save the alarm callback we must set
	 * 'alarm_enable = 1' during configuration. However, this
	 * automatically triggers the alarm underneath. So, to avoid
	 * the alarm being fired any time soon, we set the 'init_val'
	 * to 1 and the 'alarm_val' to 0.
	 */
	config.init_val = 1;
	config.alarm_val = 0;
	config.alarm_enable = 1;
	config.cb_fn = alarm_handler;
	rtc_set_config(rtc_dev, &config);

	while (1) {
		/* Simulate some task handling by busy waiting. */
		printk("LMT: busy\n");
		k_busy_wait(TASK_TIME_IN_SEC * 1000 * 1000);

		now = rtc_read(rtc_dev);
		rtc_set_alarm(rtc_dev,
			      now + (RTC_ALARM_SECOND * IDLE_TIME_IN_SEC));

		printk("LMT: idle\n");
		k_fifo_get(&fifo, K_FOREVER);
	}
}
Пример #8
0
static inline int lsm6dsl_reboot(struct device *dev)
{
	struct lsm6dsl_data *data = dev->driver_data;

	if (data->hw_tf->update_reg(data, LSM6DSL_REG_CTRL3_C,
				    LSM6DSL_MASK_CTRL3_C_BOOT,
				    1 << LSM6DSL_SHIFT_CTRL3_C_BOOT) < 0) {
		return -EIO;
	}

	/* Wait sensor turn-on time as per datasheet */
	k_busy_wait(USEC_PER_MSEC * 35U);

	return 0;
}
Пример #9
0
static inline int lsm6ds0_reboot(struct device *dev)
{
	struct lsm6ds0_data *data = dev->driver_data;
	const struct lsm6ds0_config *config = dev->config->config_info;

	if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
				LSM6DS0_REG_CTRL_REG8,
				LSM6DS0_MASK_CTRL_REG8_BOOT,
				1 << LSM6DS0_SHIFT_CTRL_REG8_BOOT) < 0) {
		return -EIO;
	}

	k_busy_wait(50 * USEC_PER_MSEC);

	return 0;
}
static int rtc_qmsi_set_alarm(struct device *dev, u8_t chan_id,
				const struct counter_alarm_cfg *alarm_cfg)
{
	qm_rtc_config_t qm_cfg;
	int result = 0;

	qm_cfg.init_val = 0;
	qm_cfg.alarm_en = 1;
	qm_cfg.alarm_val = alarm_cfg->ticks;

	user_cb = alarm_cfg->callback;
	/* Casting callback type due different input parameter from QMSI
	 * compared aganst the Zephyr callback from void cb(struct device *dev)
	 * to void cb(void *)
	 */
	qm_cfg.callback = rtc_callback;
	qm_cfg.callback_data = (void *)alarm_cfg;

	/* Set prescaler value. Ideally, the divider should come from struct
	 * rtc_config instead. It's safe to use RTC_DIVIDER here for now since
	 * values defined by clk_rtc_div and by QMSI's clk_rtc_div_t match for
	 * both D2000 and SE.
	 */
	qm_cfg.prescaler = (clk_rtc_div_t)CONFIG_RTC_PRESCALER - 1;

	if (IS_ENABLED(CONFIG_RTC_QMSI_API_REENTRANCY)) {
		k_sem_take(RP_GET(dev), K_FOREVER);
	}

	if (qm_rtc_set_config(QM_RTC_0, &qm_cfg)) {
		result = -EIO;
	}

	if (IS_ENABLED(CONFIG_RTC_QMSI_API_REENTRANCY)) {
		k_sem_give(RP_GET(dev));
	}

	k_busy_wait(60);

	qm_rtc_set_alarm(QM_RTC_0, alarm_cfg->ticks);

	return result;
}
Пример #11
0
/**
 *
 * @brief Initialize one UART as the console/debug port
 *
 * @return 0 if successful, otherwise failed.
 */
static int uart_console_init(struct device *arg)
{

	ARG_UNUSED(arg);

	uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);

#if defined(CONFIG_USB_UART_CONSOLE) && defined(CONFIG_USB_UART_DTR_WAIT)
	while (1) {
		u32_t dtr = 0;

		uart_line_ctrl_get(uart_console_dev, LINE_CTRL_DTR, &dtr);
		if (dtr) {
			break;
		}
	}
	k_busy_wait(1000000);
#endif

	uart_console_hook_install();

	return 0;
}
Пример #12
0
static int fxos8700_init(struct device *dev)
{
	const struct fxos8700_config *config = dev->config->config_info;
	struct fxos8700_data *data = dev->driver_data;
	struct sensor_value odr = {.val1 = 6, .val2 = 250000};

	/* Get the I2C device */
	data->i2c = device_get_binding(config->i2c_name);
	if (data->i2c == NULL) {
		LOG_ERR("Could not find I2C device");
		return -EINVAL;
	}

	/*
	 * Read the WHOAMI register to make sure we are talking to FXOS8700 or
	 * compatible device and not some other type of device that happens to
	 * have the same I2C address.
	 */
	if (i2c_reg_read_byte(data->i2c, config->i2c_address,
			      FXOS8700_REG_WHOAMI, &data->whoami)) {
		LOG_ERR("Could not get WHOAMI value");
		return -EIO;
	}

	switch (data->whoami) {
	case WHOAMI_ID_MMA8451:
	case WHOAMI_ID_MMA8652:
	case WHOAMI_ID_MMA8653:
		if (config->mode != FXOS8700_MODE_ACCEL) {
			LOG_ERR("Device 0x%x supports only "
				    "accelerometer mode",
				    data->whoami);
			return -EIO;
		}
	case WHOAMI_ID_FXOS8700:
		LOG_DBG("Device ID 0x%x", data->whoami);
		break;
	default:
		LOG_ERR("Unknown Device ID 0x%x", data->whoami);
		return -EIO;
	}

	/* Reset the sensor. Upon issuing a software reset command over the I2C
	 * interface, the sensor immediately resets and does not send any
	 * acknowledgment (ACK) of the written byte to the master. Therefore,
	 * do not check the return code of the I2C transaction.
	 */
	i2c_reg_write_byte(data->i2c, config->i2c_address,
			   FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK);

	/* The sensor requires us to wait 1 ms after a software reset before
	 * attempting further communications.
	 */
	k_busy_wait(USEC_PER_MSEC);

	if (fxos8700_set_odr(dev, &odr)) {
		LOG_ERR("Could not set default data rate");
		return -EIO;
	}

	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_CTRLREG2,
				FXOS8700_CTRLREG2_MODS_MASK,
				config->power_mode)) {
		LOG_ERR("Could not set power scheme");
		return -EIO;
	}

	/* Set the mode (accel-only, mag-only, or hybrid) */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG1,
				FXOS8700_M_CTRLREG1_MODE_MASK,
				config->mode)) {
		LOG_ERR("Could not set mode");
		return -EIO;
	}

	/* Set hybrid autoincrement so we can read accel and mag channels in
	 * one I2C transaction.
	 */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG2,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK)) {
		LOG_ERR("Could not set hybrid autoincrement");
		return -EIO;
	}

	/* Set the full-scale range */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_XYZ_DATA_CFG,
				FXOS8700_XYZ_DATA_CFG_FS_MASK,
				config->range)) {
		LOG_ERR("Could not set range");
		return -EIO;
	}

	k_sem_init(&data->sem, 0, UINT_MAX);

#if CONFIG_FXOS8700_TRIGGER
	if (fxos8700_trigger_init(dev)) {
		LOG_ERR("Could not initialize interrupts");
		return -EIO;
	}
#endif

	/* Set active */
	if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) {
		LOG_ERR("Could not set active");
		return -EIO;
	}
	k_sem_give(&data->sem);

	LOG_DBG("Init complete");

	return 0;
}

static const struct sensor_driver_api fxos8700_driver_api = {
	.sample_fetch = fxos8700_sample_fetch,
	.channel_get = fxos8700_channel_get,
	.attr_set = fxos8700_attr_set,
#if CONFIG_FXOS8700_TRIGGER
	.trigger_set = fxos8700_trigger_set,
#endif
};

static const struct fxos8700_config fxos8700_config = {
	.i2c_name = CONFIG_FXOS8700_I2C_NAME,
	.i2c_address = CONFIG_FXOS8700_I2C_ADDRESS,
#ifdef CONFIG_FXOS8700_MODE_ACCEL
	.mode = FXOS8700_MODE_ACCEL,
	.start_addr = FXOS8700_REG_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_ACCEL_X,
	.num_channels = FXOS8700_NUM_ACCEL_CHANNELS,
#elif CONFIG_FXOS8700_MODE_MAGN
	.mode = FXOS8700_MODE_MAGN,
	.start_addr = FXOS8700_REG_M_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_MAGN_X,
	.num_channels = FXOS8700_NUM_MAG_CHANNELS,
#else
	.mode = FXOS8700_MODE_HYBRID,
	.start_addr = FXOS8700_REG_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_ACCEL_X,
	.num_channels = FXOS8700_NUM_HYBRID_CHANNELS,
#endif
#if CONFIG_FXOS8700_PM_NORMAL
	.power_mode = FXOS8700_PM_NORMAL,
#elif CONFIG_FXOS8700_PM_LOW_NOISE_LOW_POWER
	.power_mode = FXOS8700_PM_LOW_NOISE_LOW_POWER,
#elif CONFIG_FXOS8700_PM_HIGH_RESOLUTION
	.power_mode = FXOS8700_PM_HIGH_RESOLUTION,
#else
	.power_mode = FXOS8700_PM_LOW_POWER,
#endif
#if CONFIG_FXOS8700_RANGE_8G
	.range = FXOS8700_RANGE_8G,
#elif CONFIG_FXOS8700_RANGE_4G
	.range = FXOS8700_RANGE_4G,
#else
	.range = FXOS8700_RANGE_2G,
#endif
#ifdef CONFIG_FXOS8700_TRIGGER
	.gpio_name = CONFIG_FXOS8700_GPIO_NAME,
	.gpio_pin = CONFIG_FXOS8700_GPIO_PIN,
#endif
#ifdef CONFIG_FXOS8700_PULSE
	.pulse_cfg = CONFIG_FXOS8700_PULSE_CFG,
	.pulse_ths[0] = CONFIG_FXOS8700_PULSE_THSX,
	.pulse_ths[1] = CONFIG_FXOS8700_PULSE_THSY,
	.pulse_ths[2] = CONFIG_FXOS8700_PULSE_THSZ,
	.pulse_tmlt = CONFIG_FXOS8700_PULSE_TMLT,
	.pulse_ltcy = CONFIG_FXOS8700_PULSE_LTCY,
	.pulse_wind = CONFIG_FXOS8700_PULSE_WIND,
#endif
};

static struct fxos8700_data fxos8700_data;

DEVICE_AND_API_INIT(fxos8700, CONFIG_FXOS8700_NAME, fxos8700_init,
		    &fxos8700_data, &fxos8700_config,
		    POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
		    &fxos8700_driver_api);
Пример #13
0
static int fxas21002_init(struct device *dev)
{
	const struct fxas21002_config *config = dev->config->config_info;
	struct fxas21002_data *data = dev->driver_data;
	u32_t transition_time;
	u8_t whoami;
	u8_t ctrlreg1;

	/* Get the I2C device */
	data->i2c = device_get_binding(config->i2c_name);
	if (data->i2c == NULL) {
		SYS_LOG_ERR("Could not find I2C device");
		return -EINVAL;
	}

	/* Read the WHOAMI register to make sure we are talking to FXAS21002
	 * and not some other type of device that happens to have the same I2C
	 * address.
	 */
	if (i2c_reg_read_byte(data->i2c, config->i2c_address,
			      FXAS21002_REG_WHOAMI, &whoami)) {
		SYS_LOG_ERR("Could not get WHOAMI value");
		return -EIO;
	}

	if (whoami != config->whoami) {
		SYS_LOG_ERR("WHOAMI value received 0x%x, expected 0x%x",
			    whoami, config->whoami);
		return -EIO;
	}

	/* Reset the sensor. Upon issuing a software reset command over the I2C
	 * interface, the sensor immediately resets and does not send any
	 * acknowledgment (ACK) of the written byte to the master. Therefore,
	 * do not check the return code of the I2C transaction.
	 */
	i2c_reg_write_byte(data->i2c, config->i2c_address,
			   FXAS21002_REG_CTRLREG1, FXAS21002_CTRLREG1_RST_MASK);

	/* Wait for the reset sequence to complete */
	do {
		if (i2c_reg_read_byte(data->i2c, config->i2c_address,
				      FXAS21002_REG_CTRLREG1, &ctrlreg1)) {
			SYS_LOG_ERR("Could not get ctrlreg1 value");
			return -EIO;
		}
	} while (ctrlreg1 & FXAS21002_CTRLREG1_RST_MASK);

	/* Set the full-scale range */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXAS21002_REG_CTRLREG0,
				FXAS21002_CTRLREG0_FS_MASK,
				config->range)) {
		SYS_LOG_ERR("Could not set range");
		return -EIO;
	}

	/* Set the output data rate */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXAS21002_REG_CTRLREG1,
				FXAS21002_CTRLREG1_DR_MASK,
				config->dr << FXAS21002_CTRLREG1_DR_SHIFT)) {
		SYS_LOG_ERR("Could not set output data rate");
		return -EIO;
	}

	k_sem_init(&data->sem, 0, UINT_MAX);

#if CONFIG_FXAS21002_TRIGGER
	if (fxas21002_trigger_init(dev)) {
		SYS_LOG_ERR("Could not initialize interrupts");
		return -EIO;
	}
#endif

	/* Set active */
	if (fxas21002_set_power(dev, FXAS21002_POWER_ACTIVE)) {
		SYS_LOG_ERR("Could not set active");
		return -EIO;
	}

	/* Wait the transition time from standby to active mode */
	transition_time = fxas21002_get_transition_time(FXAS21002_POWER_STANDBY,
							FXAS21002_POWER_ACTIVE,
							config->dr);
	k_busy_wait(transition_time);
	k_sem_give(&data->sem);

	SYS_LOG_DBG("Init complete");

	return 0;
}
Пример #14
0
unsigned int alt_busy_sleep (unsigned int us)
{
	k_busy_wait(us);
	return 0;
}
Пример #15
0
static int ataes132a_send_command(struct device *dev, u8_t opcode,
				  u8_t mode, u8_t *params,
				  u8_t nparams, u8_t *response,
				  u8_t *nresponse)
{
	int retry_count = 0;
	struct ataes132a_device_data *data = dev->driver_data;
	const struct ataes132a_device_config *cfg = dev->config->config_info;
	u8_t count;
	u8_t status;
	u8_t crc[2];
	int i, i2c_return;

	count = nparams + 5;
	if (count > 64) {
		SYS_LOG_ERR("command too large for command buffer");
		return -EDOM;
	}

	/* If there is a command in progress, idle wait until it is available.
	 * If there is concurrency protection around the driver, this should
	 * never happen.
	 */
	read_reg_i2c(data->i2c, cfg->i2c_addr, ATAES_STATUS_REG, &status);

	while (status & ATAES_STATUS_WIP) {
		k_busy_wait(D10D24S);
		read_reg_i2c(data->i2c, cfg->i2c_addr,
			     ATAES_STATUS_REG, &status);
	}

	data->command_buffer[0] = count;
	data->command_buffer[1] = opcode;
	data->command_buffer[2] = mode;
	for (i = 0; i < nparams; i++) {
		data->command_buffer[i + 3] = params[i];
	}

	/*Calculate command CRC*/
	ataes132a_atmel_crc(data->command_buffer, nparams + 3, crc);
	data->command_buffer[nparams + 3] = crc[0];
	data->command_buffer[nparams + 4] = crc[1];

	/*Reset i/O address start before sending a command*/
	write_reg_i2c(data->i2c, cfg->i2c_addr,
		      ATAES_COMMAND_ADDRR_RESET, 0x0);

	/*Send a command through the command buffer*/
	i2c_return = burst_write_i2c(data->i2c, cfg->i2c_addr,
				     ATAES_COMMAND_MEM_ADDR,
				     data->command_buffer, count);

	SYS_LOG_DBG("BURST WRITE RETURN: %d", i2c_return);

	/* Idle-waiting for the command completion*/
	do {
		k_busy_wait(D10D24S);
		read_reg_i2c(data->i2c, cfg->i2c_addr,
			     ATAES_STATUS_REG, &status);
	} while (status & ATAES_STATUS_WIP);

	if (status & ATAES_STATUS_CRC) {
		SYS_LOG_ERR("incorrect CRC command");
		return -EINVAL;
	}

	if (!(status & ATAES_STATUS_RDY)) {
		SYS_LOG_ERR("expected response is not in place");
		return -EINVAL;
	}

	/* Read the response */
	burst_read_i2c(data->i2c, cfg->i2c_addr,
		       ATAES_COMMAND_MEM_ADDR,
		       data->command_buffer, 64);

	count = data->command_buffer[0];

	/* Calculate and validate response CRC */
	ataes132a_atmel_crc(data->command_buffer, count - 2, crc);

	SYS_LOG_DBG("COMMAND CRC %x%x", data->command_buffer[count - 2],
		     data->command_buffer[count - 1]);
	SYS_LOG_DBG("CALCULATED CRC %x%x", crc[0], crc[1]);

	/* If CRC fails retry reading MAX RETRIES times */
	while (crc[0] != data->command_buffer[count - 2] ||
	       crc[1] != data->command_buffer[count - 1]) {
		if (retry_count > MAX_RETRIES - 1) {
			SYS_LOG_ERR("response crc validation rebase"
				    " max retries");
			return -EINVAL;
		}

		burst_read_i2c(data->i2c, cfg->i2c_addr,
			       ATAES_COMMAND_MEM_ADDR,
			       data->command_buffer, 64);

		count = data->command_buffer[0];

		ataes132a_atmel_crc(data->command_buffer, count -  2, crc);
		retry_count++;

		SYS_LOG_DBG("COMMAND RETRY %d", retry_count);
		SYS_LOG_DBG("COMMAND CRC %x%x",
			    data->command_buffer[count - 2],
			    data->command_buffer[count - 1]);
		SYS_LOG_DBG("CALCULATED CRC %x%x", crc[0], crc[1]);
		}

	if ((status & ATAES_STATUS_ERR) || data->command_buffer[1] != 0x00) {
		SYS_LOG_ERR("command execution error %x",
			    data->command_buffer[1]);
		return -EIO;
	}

	SYS_LOG_DBG("Read the response count: %d", count);

	for (i = 0; i < count - 3; i++) {
		response[i] = data->command_buffer[i + 1];
	}

	*nresponse = count - 3;

	return 0;
}
Пример #16
0
static int dht_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct dht_data *drv_data = dev->driver_data;
	int ret = 0;
	s8_t signal_duration[DHT_DATA_BITS_NUM];
	s8_t max_duration, min_duration, avg_duration;
	u8_t buf[5];
	unsigned int i, j;

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);

	/* send start signal */
	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 0);

	k_busy_wait(DHT_START_SIGNAL_DURATION);

	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);

	/* switch to DIR_IN to read sensor signals */
	gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
			   GPIO_DIR_IN);

	/* wait for sensor response */
	if (dht_measure_signal_duration(drv_data, 1) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* read sensor response */
	if (dht_measure_signal_duration(drv_data, 0) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* wait for sensor data */
	if (dht_measure_signal_duration(drv_data, 1) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* read sensor data */
	for (i = 0; i < DHT_DATA_BITS_NUM; i++) {
		/* LOW signal to indicate a new bit */
		if (dht_measure_signal_duration(drv_data, 0) == -1) {
			ret = -EIO;
			goto cleanup;
		}

		/* HIGH signal duration indicates bit value */
		signal_duration[i] = dht_measure_signal_duration(drv_data, 1);
		if (signal_duration[i] == -1) {
			ret = -EIO;
			goto cleanup;
		}
	}

	/*
	 * the datasheet says 20-40us HIGH signal duration for a 0 bit and
	 * 80us for a 1 bit; however, since dht_measure_signal_duration is
	 * not very precise, compute the threshold for deciding between a
	 * 0 bit and a 1 bit as the average between the minimum and maximum
	 * if the durations stored in signal_duration
	 */
	min_duration = signal_duration[0];
	max_duration = signal_duration[0];
	for (i = 1; i < DHT_DATA_BITS_NUM; i++) {
		if (min_duration > signal_duration[i]) {
			min_duration = signal_duration[i];
		}
		if (max_duration < signal_duration[i]) {
			max_duration = signal_duration[i];
		}
	}
	avg_duration = ((s16_t)min_duration + (s16_t)max_duration) / 2;

	/* store bits in buf */
	j = 0;
	memset(buf, 0, sizeof(buf));
	for (i = 0; i < DHT_DATA_BITS_NUM; i++) {
		if (signal_duration[i] >= avg_duration) {
			buf[j] = (buf[j] << 1) | 1;
		} else {
			buf[j] = buf[j] << 1;
		}

		if (i % 8 == 7) {
			j++;
		}
	}

	/* verify checksum */
	if (((buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF) != buf[4]) {
		SYS_LOG_DBG("Invalid checksum in fetched sample");
		ret = -EIO;
	} else {
		memcpy(drv_data->sample, buf, 4);
	}

cleanup:
	/* switch to DIR_OUT and leave pin to HIGH until next fetch */
	gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
			   GPIO_DIR_OUT);
	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);

	return ret;
}
Пример #17
0
static int fxos8700_init(struct device *dev)
{
	const struct fxos8700_config *config = dev->config->config_info;
	struct fxos8700_data *data = dev->driver_data;
	u8_t whoami;

	/* Get the I2C device */
	data->i2c = device_get_binding(config->i2c_name);
	if (data->i2c == NULL) {
		SYS_LOG_ERR("Could not find I2C device");
		return -EINVAL;
	}

	/* Read the WHOAMI register to make sure we are talking to FXOS8700 and
	 * not some other type of device that happens to have the same I2C
	 * address.
	*/
	if (i2c_reg_read_byte(data->i2c, config->i2c_address,
			      FXOS8700_REG_WHOAMI, &whoami)) {
		SYS_LOG_ERR("Could not get WHOAMI value");
		return -EIO;
	}

	if (whoami != config->whoami) {
		SYS_LOG_ERR("WHOAMI value received 0x%x, expected 0x%x",
			    whoami, FXOS8700_REG_WHOAMI);
		return -EIO;
	}

	/* Reset the sensor. Upon issuing a software reset command over the I2C
	 * interface, the sensor immediately resets and does not send any
	 * acknowledgment (ACK) of the written byte to the master. Therefore,
	 * do not check the return code of the I2C transaction.
	 */
	i2c_reg_write_byte(data->i2c, config->i2c_address,
			   FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK);

	/* The sensor requires us to wait 1 ms after a software reset before
	 * attempting further communications.
	 */
	k_busy_wait(USEC_PER_MSEC);

	/* Set the mode (accel-only, mag-only, or hybrid) */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG1,
				FXOS8700_M_CTRLREG1_MODE_MASK,
				config->mode)) {
		SYS_LOG_ERR("Could not set mode");
		return -EIO;
	}

	/* Set hybrid autoincrement so we can read accel and mag channels in
	 * one I2C transaction.
	 */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG2,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK)) {
		SYS_LOG_ERR("Could not set hybrid autoincrement");
		return -EIO;
	}

	/* Set the full-scale range */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_XYZ_DATA_CFG,
				FXOS8700_XYZ_DATA_CFG_FS_MASK,
				config->range)) {
		SYS_LOG_ERR("Could not set range");
		return -EIO;
	}

#if CONFIG_FXOS8700_TRIGGER
	if (fxos8700_trigger_init(dev)) {
		SYS_LOG_ERR("Could not initialize interrupts");
		return -EIO;
	}
#endif

	/* Set active */
	if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) {
		SYS_LOG_ERR("Could not set active");
		return -EIO;
	}

	k_sem_init(&data->sem, 1, UINT_MAX);

	SYS_LOG_DBG("Init complete");

	return 0;
}
Пример #18
0
static int adc_stm32_init(struct device *dev)
{
	struct adc_stm32_data *data = dev->driver_data;
	const struct adc_stm32_cfg *config = dev->config->config_info;
	struct device *clk =
		device_get_binding(STM32_CLOCK_CONTROL_NAME);
	ADC_TypeDef *adc = (ADC_TypeDef *)config->base;

	LOG_DBG("Initializing....");

	data->dev = dev;
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
	/*
	 * All conversion time for all channels on one ADC instance for F0 and
	 * L0 series chips has to be the same. This additional variable is for
	 * checking if the conversion time selection of all channels on one ADC
	 * instance is the same.
	 */
	data->acq_time_index = -1;
#endif

	if (clock_control_on(clk,
		(clock_control_subsys_t *) &config->pclken) != 0) {
		return -EIO;
	}

#if defined(CONFIG_SOC_SERIES_STM32L4X)
	/*
	 * L4 series STM32 needs to be awaken from deep sleep mode, and restore
	 * its calibration parameters if there are some previously stored
	 * calibration parameters.
	 */
	LL_ADC_DisableDeepPowerDown(adc);
#endif
	/*
	 * F3 and L4 ADC modules need some time to be stabilized before
	 * performing any enable or calibration actions.
	 */
#if defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	LL_ADC_EnableInternalRegulator(adc);
	k_busy_wait(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X)
	LL_ADC_SetClock(adc, LL_ADC_CLOCK_SYNC_PCLK_DIV4);
#elif defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(),
			LL_ADC_CLOCK_SYNC_PCLK_DIV4);
#endif

#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \
	!defined(CONFIG_SOC_SERIES_STM32F4X) && \
	!defined(CONFIG_SOC_SERIES_STM32F7X) && \
	!defined(CONFIG_SOC_SERIES_STM32F1X)
	/*
	 * Calibration of F1 series has to be started after ADC Module is
	 * enabled.
	 */
	adc_stm32_calib(dev);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X)
	if (LL_ADC_IsActiveFlag_ADRDY(adc)) {
		LL_ADC_ClearFlag_ADRDY(adc);
	}

	/*
	 * These two series STM32 has one internal voltage reference source
	 * to be enabled.
	 */
	LL_ADC_SetCommonPathInternalCh(ADC, LL_ADC_PATH_INTERNAL_VREFINT);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	/*
	 * ADC modules on these series have to wait for some cycles to be
	 * enabled.
	 */
	u32_t adc_rate, wait_cycles;

	if (clock_control_get_rate(clk,
		(clock_control_subsys_t *) &config->pclken, &adc_rate) < 0) {
		LOG_ERR("ADC clock rate get error.");
	}

	wait_cycles = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / adc_rate *
		      LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES;

	for (int i = wait_cycles; i >= 0; i--)
		;
#endif

	LL_ADC_Enable(adc);

#ifdef CONFIG_SOC_SERIES_STM32L4X
	/*
	 * Enabling ADC modules in L4 series may fail if they are still not
	 * stabilized, this will wait for a short time to ensure ADC modules
	 * are properly enabled.
	 */
	u32_t countTimeout = 0;

	while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) {
		if (LL_ADC_IsEnabled(adc) == 0UL) {
			LL_ADC_Enable(adc);
			countTimeout++;
			if (countTimeout == 10) {
				return -ETIMEDOUT;
			}
		}
	}
#endif

	config->irq_cfg_func();

#ifdef CONFIG_SOC_SERIES_STM32F1X
	/* Calibration of F1 must starts after two cycles after ADON is set. */
	LL_ADC_StartCalibration(adc);
	LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE);
#endif
	adc_context_unlock_unconditionally(&data->ctx);

	return 0;
}