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; }
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); }
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; }
/* 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); }
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; }
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; }
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); } }
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; }
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; }
/** * * @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; }
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);
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; }
unsigned int alt_busy_sleep (unsigned int us) { k_busy_wait(us); return 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; }
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; }
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; }
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; }