int I2C::transfer(i2c_msg_s *msgv, unsigned msgs) { int ret; unsigned retry_count = 0; /* force the device address into the message vector */ for (unsigned i = 0; i < msgs; i++) msgv[i].addr = _address; do { /* * I2C architecture means there is an unavoidable race here * if there are any devices on the bus with a different frequency * preference. Really, this is pointless. */ I2C_SETFREQUENCY(_dev, _frequency); ret = I2C_TRANSFER(_dev, msgv, msgs); /* success */ if (ret == OK) break; /* if we have already retried once, or we are going to give up, then reset the bus */ if ((retry_count >= 1) || (retry_count >= _retries)) up_i2creset(_dev); } while (retry_count++ < _retries); return ret; }
static void at24xxx_attach(void) { /* find the right I2C */ struct i2c_dev_s *i2c = up_i2cinitialize(PX4_I2C_BUS_ONBOARD); /* this resets the I2C bus, set correct bus speed again */ I2C_SETFREQUENCY(i2c, 400000); if (i2c == NULL) errx(1, "failed to locate I2C bus"); /* start the MTD driver, attempt 5 times */ for (int i = 0; i < 5; i++) { mtd_dev = at24c_initialize(i2c); if (mtd_dev) { /* abort on first valid result */ if (i > 0) { warnx("warning: EEPROM needed %d attempts to attach", i+1); } break; } } /* if last attempt is still unsuccessful, abort */ if (mtd_dev == NULL) errx(1, "failed to initialize EEPROM driver"); attached = true; }
int kxtj9_driver_init(){ int ret = 0; if (g_data != NULL) goto init_done; g_data = kmm_malloc(sizeof(struct kxtj9_data)); memset(g_data, 0, sizeof(struct kxtj9_data)); g_data->i2c = up_i2cinitialize(CONFIG_SENSOR_KXTJ9_I2C_BUS); if (!g_data->i2c) { dbg("failed to init i2c\n"); ret = -ENODEV; goto init_done; } ret = I2C_SETADDRESS(g_data->i2c, KXTJ9_I2C_ADDR, 7); if (ret) { dbg("failed to set i2c address\n"); goto init_done; } I2C_SETFREQUENCY(g_data->i2c, CONFIG_SENSOR_KXTJ9_I2C_BUS_SPEED); init_done: return ret; }
FAR struct battery_charger_dev_s *bq2425x_initialize(FAR struct i2c_dev_s *i2c, uint8_t addr, uint32_t frequency) { FAR struct bq2425x_dev_s *priv; int ret; /* Initialize the BQ2425x device structure */ priv = (FAR struct bq2425x_dev_s *)kmm_zalloc(sizeof(struct bq2425x_dev_s)); if (priv) { /* Initialize the BQ2425x device structure */ sem_init(&priv->batsem, 0, 1); priv->ops = &g_bq2425xops; priv->i2c = i2c; priv->addr = addr; priv->frequency = frequency; /* Set the I2C frequency (ignoring the returned, actual frequency) */ (void)I2C_SETFREQUENCY(i2c, priv->frequency); /* Reset the BQ2425x */ ret = bq2425x_reset(priv); if (ret < 0) { batdbg("Failed to reset the BQ2425x: %d\n", ret); kmm_free(priv); return NULL; } /* Disable watchdog otherwise BQ2425x returns to StandAlone mode */ ret = bq2425x_watchdog(priv, false); if (ret < 0) { batdbg("Failed to disable BQ2425x watchdog: %d\n", ret); kmm_free(priv); return NULL; } /* Define that our power supply can offer 2000mA to the charger */ ret = bq2425x_powersupply(priv, 2000); if (ret < 0) { batdbg("Failed to set BQ2425x power supply current: %d\n", ret); kmm_free(priv); return NULL; } } return (FAR struct battery_charger_dev_s *)priv; }
int I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len) { struct i2c_msg_s msgv[2]; unsigned msgs; int ret; unsigned retry_count = 0; do { // debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len); msgs = 0; if (send_len > 0) { msgv[msgs].addr = _address; msgv[msgs].flags = 0; msgv[msgs].buffer = const_cast<uint8_t *>(send); msgv[msgs].length = send_len; msgs++; } if (recv_len > 0) { msgv[msgs].addr = _address; msgv[msgs].flags = I2C_M_READ; msgv[msgs].buffer = recv; msgv[msgs].length = recv_len; msgs++; } if (msgs == 0) return -EINVAL; /* * I2C architecture means there is an unavoidable race here * if there are any devices on the bus with a different frequency * preference. Really, this is pointless. */ I2C_SETFREQUENCY(_dev, _frequency); ret = I2C_TRANSFER(_dev, &msgv[0], msgs); /* success */ if (ret == OK) break; /* if we have already retried once, or we are going to give up, then reset the bus */ if ((retry_count >= 1) || (retry_count >= _retries)) up_i2creset(_dev); } while (retry_count++ < _retries); return ret; }
int i2c_writeread(FAR struct i2c_dev_s *dev, FAR const struct i2c_config_s *config, FAR const uint8_t *wbuffer, int wbuflen, FAR uint8_t *rbuffer, int rbuflen) { struct i2c_msg_s msg[2]; unsigned int flags; int ret = -1; /* 7- or 10-bit address? */ DEBUGASSERT(config->addrlen == 10 || config->addrlen == 7); flags = (config->addrlen == 10) ? I2C_M_TEN : 0; /* Format two messages: The first is a write */ msg[0].addr = config->address; msg[0].flags = flags; msg[0].buffer = (FAR uint8_t *)wbuffer; /* Override const */ msg[0].length = wbuflen; /* The second is either a read (rbuflen > 0) or a write (rbuflen < 0) with * no restart. */ if (rbuflen > 0) { msg[1].flags = (flags | I2C_M_READ); } else { msg[1].flags = (flags | I2C_M_NORESTART); rbuflen = -rbuflen; } msg[1].addr = config->address; msg[1].buffer = rbuffer; msg[1].length = rbuflen; /* Then perform the transfer * * REVISIT: The following two operations must become atomic in order to * assure thread safety. */ if (dev != 0x0) { I2C_SETFREQUENCY(dev, config->frequency); ret = I2C_TRANSFER(dev, msg, 2); } return ret; }
static int transfer(uint8_t address, uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len) { struct i2c_msg_s msgv[2]; unsigned msgs; int ret; // debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len); msgs = 0; if (send_len > 0) { msgv[msgs].addr = address; msgv[msgs].flags = 0; msgv[msgs].buffer = send; msgv[msgs].length = send_len; msgs++; } if (recv_len > 0) { msgv[msgs].addr = address; msgv[msgs].flags = I2C_M_READ; msgv[msgs].buffer = recv; msgv[msgs].length = recv_len; msgs++; } if (msgs == 0) return -1; /* * I2C architecture means there is an unavoidable race here * if there are any devices on the bus with a different frequency * preference. Really, this is pointless. */ I2C_SETFREQUENCY(i2c, 400000); ret = I2C_TRANSFER(i2c, &msgv[0], msgs); // reset the I2C bus to unwedge on error if (ret != OK) up_i2creset(i2c); return ret; }
FAR struct battery_dev_s *max1704x_initialize(FAR struct i2c_dev_s *i2c, uint8_t addr, uint32_t frequency) { FAR struct max1704x_dev_s *priv; #if 0 int ret; #endif /* Initialize the MAX1704x device structure */ priv = (FAR struct max1704x_dev_s *)kzalloc(sizeof(struct max1704x_dev_s)); if (priv) { /* Initialize the MAX1704x device structure */ sem_init(&priv->batsem, 0, 1); priv->ops = &g_max1704xops; priv->i2c = i2c; priv->addr = addr; priv->frequency = frequency; /* Set the I2C frequency (ignoring the returned, actual frequency) */ (void)I2C_SETFREQUENCY(i2c, priv->frequency); /* Reset the MAX1704x (mostly just to make sure that we can talk to it) */ #if 0 ret = max1704x_reset(priv); if (ret < 0) { batdbg("Failed to reset the MAX1704x: %d\n", ret); kfree(priv); return NULL; } #endif } return (FAR struct battery_dev_s *)priv; }
int pca9635pw_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, uint8_t const pca9635pw_i2c_addr) { /* Sanity check */ DEBUGASSERT(i2c != NULL); /* Initialize the PCA9635PW device structure */ FAR struct pca9635pw_dev_s *priv = (FAR struct pca9635pw_dev_s *)kmm_malloc(sizeof(struct pca9635pw_dev_s)); if (priv == NULL) { dbg("Failed to allocate instance of pca9635pw_dev_s\n"); return -ENOMEM; } priv->i2c = i2c; priv->i2c_addr = pca9635pw_i2c_addr; /* Register the character driver */ int const ret = register_driver(devpath, &g_pca9635pw_fileops, 666, priv); if (ret != OK) { dbg("Failed to register driver: %d\n", ret); kmm_free(priv); return ret; } /* setup i2c frequency */ I2C_SETFREQUENCY(priv->i2c, I2C_BUS_FREQ_HZ); return OK; }
STMPE811_HANDLE stmpe811_instantiate(FAR struct i2c_dev_s *dev, FAR struct stmpe811_config_s *config) #endif { FAR struct stmpe811_dev_s *priv; uint8_t regval; int ret; /* Allocate the device state structure */ #ifdef CONFIG_STMPE811_MULTIPLE priv = (FAR struct stmpe811_dev_s *)kmm_zalloc(sizeof(struct stmpe811_dev_s)); if (!priv) { return NULL; } /* And save the device structure in the list of STMPE811 so that we can find it later */ priv->flink = g_stmpe811list; g_stmpe811list = priv; #else /* Use the one-and-only STMPE811 driver instance */ priv = &g_stmpe811; #endif /* Initialize the device state structure */ sem_init(&priv->exclsem, 0, 1); priv->config = config; #ifdef CONFIG_STMPE811_SPI priv->spi = dev; #else priv->i2c = dev; /* Set the I2C address and frequency. REVISIT: This logic would be * insufficient if we share the I2C bus with any other devices that also * modify the address and frequency. */ I2C_SETADDRESS(dev, config->address, 7); I2C_SETFREQUENCY(dev, config->frequency); #endif /* Read and verify the STMPE811 chip ID */ ret = stmpe811_checkid(priv); if (ret < 0) { #ifdef CONFIG_STMPE811_MULTIPLE g_stmpe811list = priv->flink; kmm_free(priv); #endif return NULL; } /* Generate STMPE811 Software reset */ stmpe811_reset(priv); /* Configure the interrupt output pin to generate interrupts on high or low level. */ regval = stmpe811_getreg8(priv, STMPE811_INT_CTRL); #ifdef CONFIG_STMPE811_ACTIVELOW regval &= ~INT_CTRL_INT_POLARITY; /* Pin polarity: Active low / falling edge */ #else regval |= INT_CTRL_INT_POLARITY; /* Pin polarity: Active high / rising edge */ #endif #ifdef CONFIG_STMPE811_EDGE regval |= INT_CTRL_INT_TYPE; /* Edge interrupt */ #else regval &= ~INT_CTRL_INT_TYPE; /* Level interrupt */ #endif stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval); /* Attach the STMPE811 interrupt handler. */ config->attach(config, stmpe811_interrupt); /* Clear any pending interrupts */ stmpe811_putreg8(priv, STMPE811_INT_STA, INT_ALL); config->clear(config); config->enable(config, true); /* Enable global interrupts */ regval = stmpe811_getreg8(priv, STMPE811_INT_CTRL); regval |= INT_CTRL_GLOBAL_INT; stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval); /* Return our private data structure as an opaque handle */ return (STMPE811_HANDLE)priv; }
int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) { FAR struct i2c_dev_s *dev; FAR char *ptr; uint16_t result; uint8_t regaddr; long repititions; int nargs; int argndx; int ret; int i; /* Parse any command line arguments */ for (argndx = 1; argndx < argc; ) { /* Break out of the look when the last option has been parsed */ ptr = argv[argndx]; if (*ptr != '-') { break; } /* Otherwise, check for common options */ nargs = common_args(i2ctool, &argv[argndx]); if (nargs < 0) { return ERROR; } argndx += nargs; } /* There may be one more thing on the command line: The repitition * count. */ repititions = 1; if (argndx < argc) { repititions = strtol(argv[argndx], NULL, 16); if (repititions < 1) { i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); return ERROR; } argndx++; } if (argndx != argc) { i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); return ERROR; } /* Get a handle to the I2C bus */ dev = up_i2cinitialize(i2ctool->bus); if (!dev) { i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); return ERROR; } /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */ I2C_SETFREQUENCY(dev, i2ctool->freq); I2C_SETADDRESS(dev, i2ctool->addr, 7); /* Loop for the requested number of repititions */ regaddr = i2ctool->regaddr; ret = OK; for (i = 0; i < repititions; i++) { /* Read from the I2C bus */ ret = i2ctool_get(i2ctool, dev, regaddr, &result); /* Display the result */ if (ret == OK) { i2ctool_printf(i2ctool, "READ Bus: %d Addr: %02x Subaddr: %02x Value: ", i2ctool->bus, i2ctool->addr, i2ctool->regaddr); if (i2ctool->width == 8) { i2ctool_printf(i2ctool, "%02x\n", result); } else { i2ctool_printf(i2ctool, "%04x\n", result); } } else { i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); break; } /* Auto-increment the address if so configured */ if (i2ctool->autoincr) { regaddr++; } } (void)up_i2cuninitialize(dev); return ret; }
int nsh_archinitialize(void) { int result; /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */ /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */ /* configure the high-resolution time/callout interface */ #ifdef CONFIG_HRT_TIMER hrt_init(); #endif /* configure CPU load estimation */ #ifdef CONFIG_SCHED_INSTRUMENTATION cpuload_initialize_once(); #endif /* set up the serial DMA polling */ #ifdef SERIAL_HAVE_DMA { static struct hrt_call serial_dma_call; struct timespec ts; /* * Poll at 1ms intervals for received bytes that have not triggered * a DMA event. */ ts.tv_sec = 0; ts.tv_nsec = 1000000; hrt_call_every(&serial_dma_call, ts_to_abstime(&ts), ts_to_abstime(&ts), (hrt_callout)stm32_serial_dma_poll, NULL); } #endif message("\r\n"); up_ledoff(LED_BLUE); up_ledoff(LED_AMBER); up_ledon(LED_BLUE); /* Configure user-space led driver */ px4fmu_led_init(); /* Configure SPI-based devices */ spi1 = up_spiinitialize(1); if (!spi1) { message("[boot] FAILED to initialize SPI port 1\r\n"); up_ledon(LED_AMBER); return -ENODEV; } // Setup 10 MHz clock (maximum rate the BMA180 can sustain) SPI_SETFREQUENCY(spi1, 10000000); SPI_SETBITS(spi1, 8); SPI_SETMODE(spi1, SPIDEV_MODE3); SPI_SELECT(spi1, PX4_SPIDEV_GYRO, false); SPI_SELECT(spi1, PX4_SPIDEV_ACCEL, false); SPI_SELECT(spi1, PX4_SPIDEV_MPU, false); up_udelay(20); message("[boot] Successfully initialized SPI port 1\r\n"); /* initialize SPI peripherals redundantly */ int gyro_attempts = 0; int gyro_fail = 0; while (gyro_attempts < 5) { gyro_fail = l3gd20_attach(spi1, PX4_SPIDEV_GYRO); gyro_attempts++; if (gyro_fail == 0) break; up_udelay(1000); } if (gyro_fail) message("[boot] FAILED to attach L3GD20 gyro\r\n"); int acc_attempts = 0; int acc_fail = 0; while (acc_attempts < 5) { acc_fail = bma180_attach(spi1, PX4_SPIDEV_ACCEL); acc_attempts++; if (acc_fail == 0) break; up_udelay(1000); } if (acc_fail) message("[boot] FAILED to attach BMA180 accelerometer\r\n"); int mpu_attempts = 0; int mpu_fail = 0; while (mpu_attempts < 1) { mpu_fail = mpu6000_attach(spi1, PX4_SPIDEV_MPU); mpu_attempts++; if (mpu_fail == 0) break; up_udelay(200); } if (mpu_fail) message("[boot] FAILED to attach MPU 6000 gyro/acc\r\n"); /* initialize I2C2 bus */ i2c2 = up_i2cinitialize(2); if (!i2c2) { message("[boot] FAILED to initialize I2C bus 2\r\n"); up_ledon(LED_AMBER); return -ENODEV; } /* set I2C2 speed */ I2C_SETFREQUENCY(i2c2, 400000); i2c3 = up_i2cinitialize(3); if (!i2c3) { message("[boot] FAILED to initialize I2C bus 3\r\n"); up_ledon(LED_AMBER); return -ENODEV; } /* set I2C3 speed */ I2C_SETFREQUENCY(i2c3, 400000); int mag_attempts = 0; int mag_fail = 0; while (mag_attempts < 5) { mag_fail = hmc5883l_attach(i2c2); mag_attempts++; if (mag_fail == 0) break; up_udelay(1000); } if (mag_fail) message("[boot] FAILED to attach HMC5883L magnetometer\r\n"); int baro_attempts = 0; int baro_fail = 0; while (baro_attempts < 5) { baro_fail = ms5611_attach(i2c2); baro_attempts++; if (baro_fail == 0) break; up_udelay(1000); } if (baro_fail) message("[boot] FAILED to attach MS5611 baro at addr #1 or #2 (0x76 or 0x77)\r\n"); /* try to attach, don't fail if device is not responding */ (void)eeprom_attach(i2c3, FMU_BASEBOARD_EEPROM_ADDRESS, FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES, FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES, FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1); int eeprom_attempts = 0; int eeprom_fail; while (eeprom_attempts < 5) { /* try to attach, fail if device does not respond */ eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS, FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES, FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES, FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1); eeprom_attempts++; if (eeprom_fail == OK) break; up_udelay(1000); } if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n"); /* Report back sensor status */ if (acc_fail || gyro_fail || mag_fail || baro_fail || eeprom_fail) { up_ledon(LED_AMBER); } #if defined(CONFIG_STM32_SPI3) /* Get the SPI port */ message("[boot] Initializing SPI port 3\r\n"); spi3 = up_spiinitialize(3); if (!spi3) { message("[boot] FAILED to initialize SPI port 3\r\n"); up_ledon(LED_AMBER); return -ENODEV; } message("[boot] Successfully initialized SPI port 3\r\n"); /* Now bind the SPI interface to the MMCSD driver */ result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3); if (result != OK) { message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n"); up_ledon(LED_AMBER); return -ENODEV; } message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n"); #endif /* SPI3 */ /* initialize I2C1 bus */ i2c1 = up_i2cinitialize(1); if (!i2c1) { message("[boot] FAILED to initialize I2C bus 1\r\n"); up_ledon(LED_AMBER); return -ENODEV; } /* set I2C1 speed */ I2C_SETFREQUENCY(i2c1, 400000); /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */ /* Get board information if available */ /* Initialize the user GPIOs */ px4fmu_gpio_init(); #ifdef CONFIG_ADC int adc_state = adc_devinit(); if (adc_state != OK) { /* Try again */ adc_state = adc_devinit(); if (adc_state != OK) { /* Give up */ message("[boot] FAILED adc_devinit: %d\r\n", adc_state); return -ENODEV; } } #endif /* configure the tone generator */ #ifdef CONFIG_TONE_ALARM tone_alarm_init(); #endif return OK; }
int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) { FAR struct i2c_dev_s *dev; FAR char *ptr; uint16_t rdvalue; uint8_t regaddr; bool addrinaddr; long wrvalue; long repititions; int nargs; int argndx; int ret; int i; /* Parse any command line arguments */ for (argndx = 1; argndx < argc; ) { /* Break out of the look when the last option has been parsed */ ptr = argv[argndx]; if (*ptr != '-') { break; } /* Otherwise, check for common options */ nargs = common_args(i2ctool, &argv[argndx]); if (nargs < 0) { return ERROR; } argndx += nargs; } /* The options may be followed by the optional wrvalue to be written. If omitted, then * the register address will be used as the wrvalue, providing an address-in-address * test. */ addrinaddr = true; wrvalue = 0; if (argndx < argc) { wrvalue = strtol(argv[argndx], NULL, 16); if (i2ctool->width == 8) { if (wrvalue < 0 || wrvalue > 255) { i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); return ERROR; } } else if (wrvalue < 0 || wrvalue > 65535) { i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); return ERROR; } addrinaddr = false; argndx++; } /* There may be one more thing on the command line: The repitition * count. */ repititions = 1; if (argndx < argc) { repititions = strtol(argv[argndx], NULL, 16); if (repititions < 1) { i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); return ERROR; } argndx++; } if (argndx != argc) { i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); return ERROR; } /* Get a handle to the I2C bus */ dev = up_i2cinitialize(i2ctool->bus); if (!dev) { i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); return ERROR; } /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */ I2C_SETFREQUENCY(dev, i2ctool->freq); I2C_SETADDRESS(dev, i2ctool->addr, 7); /* Loop for the requested number of repititions */ regaddr = i2ctool->regaddr; ret = OK; for (i = 0; i < repititions; i++) { /* If we are performing an address-in-address test, then use the register * address as the value to write. */ if (addrinaddr) { wrvalue = regaddr; } /* Write to the I2C bus */ ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)wrvalue); if (ret == OK) { /* Read the value back from the I2C bus */ ret = i2ctool_get(i2ctool, dev, regaddr, &rdvalue); } /* Display the result */ if (ret == OK) { i2ctool_printf(i2ctool, "VERIFY Bus: %d Addr: %02x Subaddr: %02x Wrote: ", i2ctool->bus, i2ctool->addr, i2ctool->regaddr); if (i2ctool->width == 8) { i2ctool_printf(i2ctool, "%02x Read: %02x", (int)wrvalue, (int)rdvalue); } else { i2ctool_printf(i2ctool, "%04x Read: %04x", (int)wrvalue, (int)rdvalue); } if (wrvalue != rdvalue) { i2ctool_printf(i2ctool, " <<< FAILURE\n"); } else { i2ctool_printf(i2ctool, "\n"); } } else { i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); break; } /* Auto-increment the address if so configured */ if (i2ctool->autoincr) { regaddr++; } } (void)up_i2cuninitialize(dev); return ret; }
int nsh_archinitialize(void) { int result; /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */ /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */ /* configure the high-resolution time/callout interface */ #ifdef CONFIG_HRT_TIMER hrt_init(); #endif /* configure CPU load estimation */ #ifdef CONFIG_SCHED_INSTRUMENTATION cpuload_initialize_once(); #endif /* set up the serial DMA polling */ #ifdef SERIAL_HAVE_DMA { static struct hrt_call serial_dma_call; struct timespec ts; /* * Poll at 1ms intervals for received bytes that have not triggered * a DMA event. */ ts.tv_sec = 0; ts.tv_nsec = 1000000; hrt_call_every(&serial_dma_call, ts_to_abstime(&ts), ts_to_abstime(&ts), (hrt_callout)stm32_serial_dma_poll, NULL); } #endif message("\r\n"); up_ledoff(LED_BLUE); up_ledoff(LED_AMBER); up_ledon(LED_BLUE); /* Configure user-space led driver */ px4fmu_led_init(); i2c2 = up_i2cinitialize(2); if (!i2c2) { message("[boot] FAILED to initialize I2C bus 3\r\n"); up_ledon(LED_AMBER); return -ENODEV; } /* set I2C3 speed */ I2C_SETFREQUENCY(i2c2, 400000); /* try to attach, don't fail if device is not responding */ (void)eeprom_attach(i2c2, FMU_BASEBOARD_EEPROM_ADDRESS, FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES, FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES, FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1); int eeprom_attempts = 0; int eeprom_fail; while (eeprom_attempts < 5) { /* try to attach, fail if device does not respond */ eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS, FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES, FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES, FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1); eeprom_attempts++; if (eeprom_fail == OK) break; up_udelay(1000); } if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n"); /* Report back sensor status */ if (eeprom_fail) { up_ledon(LED_AMBER); } #if defined(CONFIG_STM32_SPI3) /* Get the SPI port */ message("[boot] Initializing SPI port 3\r\n"); spi3 = up_spiinitialize(3); if (!spi3) { message("[boot] FAILED to initialize SPI port 3\r\n"); up_ledon(LED_AMBER); return -ENODEV; } message("[boot] Successfully initialized SPI port 3\r\n"); /* Now bind the SPI interface to the MMCSD driver */ result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3); if (result != OK) { message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n"); up_ledon(LED_AMBER); return -ENODEV; } message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n"); #endif /* SPI3 */ /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */ /* Get board information if available */ /* Initialize the user GPIOs */ px4fmu_gpio_init(); #ifdef CONFIG_ADC int adc_state = adc_devinit(); if (adc_state != OK) { /* Try again */ adc_state = adc_devinit(); if (adc_state != OK) { /* Give up */ message("[boot] FAILED adc_devinit: %d\r\n", adc_state); return -ENODEV; } } #endif /* configure the tone generator */ #ifdef CONFIG_TONE_ALARM tone_alarm_init(); #endif return OK; }
int sif_main(int argc, char *argv[]) { if (argc >= 2) { if (!strcmp(argv[1], "init")) { return sif_init(); } else if (!strcmp(argv[1], "gpio") && argc == 4) { vsn_sif.gpio[0] = atoi(argv[2]); vsn_sif.gpio[1] = atoi(argv[3]); sif_gpio1_update(); sif_gpio2_update(); printf("GPIO States: %2x %2x\n", vsn_sif.gpio[0], vsn_sif.gpio[1]); return 0; } else if (!strcmp(argv[1], "pwr") && argc == 3) { int val = atoi(argv[2]); //STM32_TIM_SETCOMPARE(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH, val); STM32_TIM_SETCOMPARE(vsn_sif.tim3, GPIO_OUT_PWM_TIM3_CH, val); return 0; } else if (!strcmp(argv[1], "time") && argc == 3) { struct timespec t_set; t_set.tv_sec = atoi(argv[2]); clock_settime(CLOCK_REALTIME, &t_set); } else if (!strcmp(argv[1], "free")) { size_t page = 0, stpage = 0xFFFF; ssize_t status; do { status = up_progmem_ispageerased(page++); /* Is this beginning of new free space section */ if (status == 0) { if (stpage == 0xFFFF) stpage = page-1; } else if (status != 0) { if (stpage != 0xFFFF) { printf("Free Range:\t%lu\t-\t%lu\n", (unsigned long)stpage, (unsigned long)(page-2)); stpage = 0xFFFF; } } } while (status >= 0); return 0; } else if (!strcmp(argv[1], "erase") && argc == 3) { size_t page = atoi(argv[2]); printf("Erase result: %d\n", up_progmem_erasepage(page)); return 0; } else if (!strcmp(argv[1], "flash") && argc == 3) { size_t page = atoi(argv[2]); size_t addr = page * up_progmem_pagesize(page); printf("Write result: %d (writing to address %lxh)\n", up_progmem_write(addr, "Test", 4), (unsigned long)addr); return 0; } else if (!strcmp(argv[1], "i2c") && argc == 3) { int val = atoi(argv[2]); I2C_SETFREQUENCY(vsn_sif.i2c1, 100000); struct lis331dl_dev_s * lis = lis331dl_init(vsn_sif.i2c1, val); if (lis) { const struct lis331dl_vector_s * a; int i; uint32_t time_stamp = clock_systimer(); /* Set to 400 Hz : 3 = 133 Hz/axis */ lis331dl_setconversion(lis, false, true); /* Sample some values */ for (i=0; i<1000;) { if ((a = lis331dl_getreadings(lis))) { i++; printf("%d %d %d\n", a->x, a->y, a->z); } else if (errno != 11) { printf("Readings errno %d\n", errno); break; } } printf("Time diff = %d\n", clock_systimer() - time_stamp); lis331dl_deinit(lis); } else printf("Exit point: errno=%d\n", errno); return 0; } else if (!strcmp(argv[1], "pga")) { int gain = atoi(argv[2]); gain = vsn_muxbus_setpgagain(gain); printf("Gain changed: %d\n", gain); return 0; } else if (!strcmp(argv[1], "cc")) { struct cc1101_dev_s * cc; uint8_t buf[64]; int sta; cc = cc1101_init(vsn_sif.spi2, CC1101_PIN_GDO0, GPIO_CC1101_GDO0, &cc1101_rfsettings_ISM1_868MHzGFSK100kbps); if (cc) { /* Work-around: enable falling edge, event and interrupt */ stm32_gpiosetevent(GPIO_CC1101_GDO0, false, true, true, cc1101_eventcb); /* Enable clock to ARM PLL, allowing to speed-up to 72 MHz */ cc1101_setgdo(cc, CC1101_PIN_GDO2, CC1101_GDO_CLK_XOSC3); cc1101_setchannel(cc, 0); /* AV Test Hex, receive on that channel */ cc1101_receive(cc); /* Enter RX mode */ while (1) { fflush(stdout); sta = cc1101_read(cc, buf, 64); if (sta > 0) { printf("Received %d bytes: rssi=%d [dBm], LQI=%d (CRC %s)\n", sta, cc1101_calcRSSIdBm(buf[sta-2]), buf[sta-1]&0x7F, (buf[sta-1]&0x80)?"OK":"BAD"); cc1101_write(cc, buf, 61); cc1101_send(cc); printf("Packet send back\n"); cc1101_receive(cc); } } } } } fprintf(stderr, "%s:\tinit\n\tgpio\tA B\n\tpwr\tval\n", argv[0]); fprintf(stderr, "rtc time = %u, time / systick = %u / %u\n", up_rtc_time(), time(NULL), clock_systimer()); return -1; }
int ov2640_initialize(FAR struct i2c_dev_s *i2c) { int ret; /* Configure I2C bus for the OV2640 */ I2C_SETADDRESS(i2c, CONFIG_OV2640_I2CADDR, 7); I2C_SETFREQUENCY(i2c, CONFIG_OV2640_FREQUENCY); /* Reset the OVR2640 */ ret = ov2640_reset(i2c); if (ret < 0) { gdbg("ERROR: ov2640_reset failed: %d\n", ret); goto errout; } /* Check the CHIP ID */ ret = ovr2640_chipid(i2c); if (ret < 0) { gdbg("ERROR: ovr2640_chipid failed: %d\n", ret); goto errout; } /* Initialize the OV2640 hardware */ #ifdef CONFIG_OV2640_JPEG /* Initialize for JPEG output */ ret = ov2640_putreglist(i2c, g_ov2640_jpeg_init, OV2640_JPEG_INIT_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } ret = ov2640_putreglist(i2c, g_ov2640_yuv422, OV2640_YUV422_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } ret = ov2640_putreglist(i2c, g_ov2640_jpeg, OV2640_JPEG_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } ret = ov2640_putreg(i2c, 0xff, 0x01); if (ret < 0) { gdbg("ERROR: ov2640_putreg failed: %d\n", ret); goto errout; } ret = ov2640_putreg(i2c, 0x15, 0x00); if (ret < 0) { gdbg("ERROR: ov2640_putreg failed: %d\n", ret); goto errout; } #if defined(CONFIG_OV2640_JPEG_QCIF_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_qcif_resolution, OV2640_JPEG_QCIF_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_QVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_qvga_resolution, OV2640_JPEG_QVGA_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_CIF_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_cif_resolution, OV2640_JPEG_CIF_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_VGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_vga_resolution, OV2640_JPEG_VGA_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_SVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_svga_resolution, OV2640_JPEG_SVGA_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_XVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_xvga_resolution, OV2640_JPEG_XVGA_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_SXVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_sxvga_resolution, OV2640_JPEG_SXVGA_RESOUTION_NENTRIES); #elif defined(CONFIG_OV2640_JPEG_UXGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_jpeg_uxga_resolution, OV2640_JPEG_UXGA_RESOUTION_NENTRIES); #else # error Unspecified JPEG resolution #endif if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } #else /* CONFIG_OV2640_JPEG */ /* Setup initial register values */ ret = ov2640_putreglist(i2c, g_ov2640_initialregs, OV2640_INITIALREGS_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } /* Setup image resolution */ ret = ov2640_putreglist(i2c, g_ov2640_resolution_common, OV2640_RESOLUTION_COMMON_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } #if defined(CONFIG_OV2640_QCIF_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_qcif_resolution, OV2640_QCIF_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_QVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_qvga_resolution, OV2640_QVGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_CIF_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_cif_resolution, OV2640_CIF_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_VGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_vga_resolution, OV2640_VGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_SVGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_svga_resolution, OV2640_SVGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_XGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_xga_resolution, OV2640_XGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_SXGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_sxga_resolution, OV2640_SXGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_UXGA_RESOLUTION) ret = ov2640_putreglist(i2c, g_ov2640_uxga_resolution, OV2640_UXGA_RESOLUTION_NENTRIES); #else # error Unknown image resolution #endif if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } /* Color format register settings */ ret = ov2640_putreglist(i2c, g_ov2640_colorfmt_common, OV2640_COLORFMT_COMMON_NENTRIES); if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } #if defined(CONFIG_OV2640_YUV422_COLORFMT) ret = ov2640_putreglist(i2c, g_ov2640_yuv422_colorfmt, OV2640_YUV422_COLORFMT_NENTRIES); #elif defined(CONFIG_OV2640_RGB565_COLORFMT) ret = ov2640_putreglist(i2c, g_ov2640_rgb565_colorfmt, OV2640_RGB565_COLORFMT_NENTRIES); #else # error Unknown color format #endif if (ret < 0) { gdbg("ERROR: ov2640_putreglist failed: %d\n", ret); goto errout; } #endif /* CONFIG_OV2640_JPEG */ return OK; errout: gdbg("ERROR: Failed to initialize the OV2640: %d\n", ret); (void)ov2640_reset(i2c); return ret; }
int I2C::init() { int ret = OK; unsigned bus_index; // attach to the i2c bus _dev = up_i2cinitialize(_bus); if (_dev == nullptr) { debug("failed to init I2C"); ret = -ENOENT; goto out; } // the above call fails for a non-existing bus index, // so the index math here is safe. bus_index = _bus - 1; // abort if the max frequency we allow (the frequency we ask) // is smaller than the bus frequency if (_bus_clocks[bus_index] > _frequency) { (void)up_i2cuninitialize(_dev); _dev = nullptr; log("FAIL: too slow for bus #%u: %u KHz, device max: %u KHz)", _bus, _bus_clocks[bus_index] / 1000, _frequency / 1000); ret = -EINVAL; goto out; } // set the bus frequency on the first access if it has // not been set yet if (_bus_clocks[bus_index] == 0) { _bus_clocks[bus_index] = _frequency; } // set frequency for this instance once to the bus speed // the bus speed is the maximum supported by all devices on the bus, // as we have to prioritize performance over compatibility. // If a new device requires a lower clock speed, this has to be // manually set via "fmu i2c <bus> <clock>" before starting any // drivers. // This is necessary as automatically lowering the bus speed // for maximum compatibility could induce timing issues on // critical sensors the adopter might be unaware of. I2C_SETFREQUENCY(_dev, _bus_clocks[bus_index]); // call the probe function to check whether the device is present ret = probe(); if (ret != OK) { debug("probe failed"); goto out; } // do base class init, which will create device node, etc ret = CDev::init(); if (ret != OK) { debug("cdev init failed"); goto out; } // tell the world where we are log("on I2C bus %d at 0x%02x (bus: %u KHz, max: %u KHz)", _bus, _address, _bus_clocks[bus_index] / 1000, _frequency / 1000); out: if ((ret != OK) && (_dev != nullptr)) { up_i2cuninitialize(_dev); _dev = nullptr; } return ret; }
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_dev_s *dev, unsigned int devno) #endif { FAR struct ssd1306_dev_s *priv = &g_oleddev; lcdvdbg("Initializing\n"); DEBUGASSERT(spi && devno == 0); #ifdef CONFIG_LCD_SSD1306_SPI priv->spi = dev; /* If this SPI bus is not shared, then we can config it now. * If it is shared, then other device could change our config, * then just configure before sending data. */ # ifdef CONFIG_SPI_OWNBUS /* Configure SPI */ SPI_SETMODE(priv->spi, CONFIG_SSD1306_SPIMODE); SPI_SETBITS(priv->spi, 8); SPI_SETFREQUENCY(priv->spi, CONFIG_SSD1306_FREQUENCY); # else /* Configure the SPI */ ssd1306_configspi(priv->spi); # endif #else /* Remember the I2C configuration */ priv->i2c = dev; priv->addr = CONFIG_SSD1306_I2CADDR; /* Set the I2C address and frequency. REVISIT: This logic would be * insufficient if we share the I2C bus with any other devices that also * modify the address and frequency. */ I2C_SETADDRESS(priv->i2c, CONFIG_SSD1306_I2CADDR, 7); I2C_SETFREQUENCY(priv->i2c, CONFIG_SSD1306_I2CFREQ); #endif /* Lock and select device */ ssd1306_select(priv, true); /* Select command transfer */ ssd1306_cmddata(priv, true); /* Configure OLED SPI or I/O, must be delayed 1-10ms */ up_mdelay(5); /* Configure the device */ ssd1306_sendbyte(priv, SSD1306_DISPOFF); /* Display off 0xae */ ssd1306_sendbyte(priv, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */ ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */ ssd1306_sendbyte(priv, SSD1306_STARTLINE(0)); /* Set display start line 0x40 */ /* ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0));*//* Set page address (Can ignore)*/ ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Contrast control 0x81 */ ssd1306_sendbyte(priv,SSD1306_CONTRAST(SSD1306_DEV_CONTRAST)); /* Default contrast 0xCF */ ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xa1 */ /* ssd1306_sendbyte(priv, SSD1306_EDISPOFF); */ /* Normal display off 0xa4 (Can ignore)*/ ssd1306_sendbyte(priv, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xa6 */ ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xa8 */ ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY)); /* Duty = 1/64 or 1/32 */ /* ssd1306_sendbyte(priv, SSD1306_SCANTOCOM0);*/ /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore)*/ ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE); /* Set display offset 0xd3 */ ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0)); ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET); /* Set clock divider 0xd5*/ ssd1306_sendbyte(priv, SSD1306_CLKDIV(8,0)); /* 0x80*/ ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET); /* Set pre-charge period 0xd9 */ ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f,1)); /* 0xf1 or 0x22 Enhanced mode */ ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xda */ ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */ ssd1306_sendbyte(priv, SSD1306_VCOM_SET); /* set vcomh 0xdb*/ ssd1306_sendbyte(priv, SSD1306_VCOM(0x40)); ssd1306_sendbyte(priv, SSD1306_CHRPUMP_SET); /* Set Charge Pump enable/disable 0x8d ssd1306 */ ssd1306_sendbyte(priv, SSD1306_CHRPUMP_ON); /* 0x14 close 0x10 */ /* ssd1306_sendbyte(priv, SSD1306_DCDC_MODE); */ /* DC/DC control mode: on (SSD1306 Not supported) */ /* ssd1306_sendbyte(priv, SSD1306_DCDC_ON); */ ssd1306_sendbyte(priv, SSD1306_DISPON); /* Display ON 0xaf */ /* De-select and unlock the device */ ssd1306_select(priv, false); /* Clear the display */ up_mdelay(100); ssd1306_fill(&priv->dev, SSD1306_Y1_BLACK); return &priv->dev; }