コード例 #1
0
static int i2c_eeprom_set_pointer(I2CEEPROM *i2c_eeprom,
                                  uint8_t *eeprom_memory_address) {
	int bytes_written = 0;

	if (i2c_eeprom == NULL || i2c_eeprom->file < 0) {
		log_error("I2C EEPROM structure uninitialized");

		return -1;
	}

	bytes_written = robust_write(i2c_eeprom->file, eeprom_memory_address, 2);

	if (bytes_written != 2) {
		// We only use debug here to not spam the log with errors.
		// This is the expected case if an extension is not present.
		log_debug("Error setting EEPROM address pointer: %s (%d)",
		          get_errno_name(errno), errno);

		i2c_eeprom_destroy(i2c_eeprom);

		return -1;
	}

	return bytes_written;
}
コード例 #2
0
// TODO: If we want "real parallel accessibility" of the EEPROM we need to
//       lock a mutex in the init function and unlock it in the release function
int i2c_eeprom_create(I2CEEPROM *i2c_eeprom, int extension) {
	GPIOREDPin pullup = {GPIO_RED_PORT_B, GPIO_RED_PIN_6};

	log_debug("Initializing I2C EEPROM for extension %d", extension);

	if (i2c_eeprom == NULL || extension < 0 || extension > 1) {
		log_error("Initialization of I2C EEPROM for extension %d failed (malformed parameters)",
		          extension);

		return -1;
	}

	// Enable pullups
	gpio_red_mux_configure(pullup, GPIO_RED_MUX_OUTPUT);
	gpio_red_output_clear(pullup);

	// Initialize I2C EEPROM structure
	i2c_eeprom->extension = extension;

	switch (extension) {
	case 0:
		i2c_eeprom->address_pin.port_index = GPIO_RED_PORT_G;
		i2c_eeprom->address_pin.pin_index = GPIO_RED_PIN_9;

		break;

	case 1:
		i2c_eeprom->address_pin.port_index = GPIO_RED_PORT_G;
		i2c_eeprom->address_pin.pin_index = GPIO_RED_PIN_13;

		break;
	}

	// enable I2C bus with GPIO_RED
	gpio_red_mux_configure(i2c_eeprom->address_pin, GPIO_RED_MUX_OUTPUT);
	i2c_eeprom_deselect(i2c_eeprom);

	i2c_eeprom->file = open(I2C_EEPROM_BUS, O_RDWR);

	if (i2c_eeprom->file < 0) {
		log_error("Initialization of I2C EEPROM for extension %d failed (Unable to open I2C bus: %s (%d))",
		          extension, get_errno_name(errno), errno);

		return -1;
	}

	if (ioctl(i2c_eeprom->file, I2C_SLAVE, I2C_EEPROM_DEVICE_ADDRESS) < 0) {
		log_error("Initialization of I2C EEPROM for extension %d failed (Unable to access I2C device on the bus: %s (%d))",
		          extension, get_errno_name(errno), errno);

		i2c_eeprom_destroy(i2c_eeprom);

		return -1;
	}

	return 0;
}
コード例 #3
0
int i2c_eeprom_read(I2CEEPROM *i2c_eeprom, uint16_t eeprom_memory_address,
                    uint8_t *buffer_to_store, int bytes_to_read) {
	int bytes_read = 0;
	uint8_t mem_address[2] = {eeprom_memory_address >> 8,
		                  eeprom_memory_address & 0xFF};

	if (i2c_eeprom == NULL || i2c_eeprom->file < 0) {
		log_error("I2C EEPROM structure uninitialized\n");
		return -1;
	}

	i2c_eeprom_select(i2c_eeprom);

	if (i2c_eeprom_set_pointer(i2c_eeprom, mem_address) < 0) {
		return -1;
	}

	bytes_read = robust_read(i2c_eeprom->file, buffer_to_store, bytes_to_read);

	if (bytes_read != bytes_to_read) {
		log_error("EEPROM read failed: %s (%d)", get_errno_name(errno), errno);

		i2c_eeprom_destroy(i2c_eeprom);
		return -1;
	}

	i2c_eeprom_deselect(i2c_eeprom);

	return bytes_read;
}

int i2c_eeprom_write(I2CEEPROM *i2c_eeprom, uint16_t eeprom_memory_address,
                     uint8_t *buffer_to_write, int bytes_to_write) {
	int i;
	int rc;
	char bytes_written = 0;
	uint8_t write_byte[3] = {0};

	if (i2c_eeprom == NULL || i2c_eeprom->file < 0) {
		log_error("I2C EEPROM structure uninitialized\n");
		return -1;
	}

	for (i = 0; i < bytes_to_write; i++) {
		write_byte[0] = eeprom_memory_address >> 8;
		write_byte[1] = eeprom_memory_address & 0xFF;
		write_byte[2] = buffer_to_write[i];

		i2c_eeprom_select(i2c_eeprom);
		rc = robust_write(i2c_eeprom->file, write_byte, 3);
		i2c_eeprom_deselect(i2c_eeprom);

		// Wait at least 5ms between writes (see m24128-bw.pdf)
		usleep(5*1000);

		if (rc != 3) {
			log_error("EEPROM write failed (pos(%d), length(%d), expected length(%d): %s (%d)",
			          i, rc, 3, get_errno_name(errno), errno);

			i2c_eeprom_destroy(i2c_eeprom);

			return -1;
		}

		eeprom_memory_address++;
		bytes_written++;
	}

	return bytes_written;
}
コード例 #4
0
ファイル: red_extension.c プロジェクト: vszurma/brickd
int red_extension_init(void) {
	uint8_t buf[4];
	int i, j, ret;
	ExtensionBaseConfig base_config[2];

	// First we remove the Ethernet Extension kernel module (if there is one)
	// to make sure that there isn't a collision between SPI select and I2C select.
	red_ethernet_extension_rmmod();

	// Then we deselect all EEPROMS
	for (i = 0; i < EXTENSION_NUM_MAX; i++) {
		for (j = 0; j < extension_startup.num_configs; j++) {
			red_extension_configure_pin(&extension_startup.config[j], i);
		}
	}

	// Now we can try to find the configurations
	for (i = 0; i < EXTENSION_NUM_MAX; i++) {
		I2CEEPROM i2c_eeprom;
		log_debug("Checking for presence of Extension at position %d", i);
		int eeprom_length = 0;
		uint8_t eeprom_buffer[EEPROM_SIZE];

		base_config[i].extension = i;
		base_config[i].type = EXTENSION_TYPE_NONE;

		if (i2c_eeprom_create(&i2c_eeprom, i) < 0) {
			return -1;
		}

		if ((eeprom_length = red_extension_read_eeprom_from_fs(eeprom_buffer, i)) > 2) {
			int start_addr = eeprom_buffer[0] | (eeprom_buffer[1] << 8);

			if (eeprom_length + start_addr >= EEPROM_SIZE) {
				log_warn("Found malformed EEPROM config (start=%d, length=%d) for extension %d",
				         start_addr, eeprom_length, i);
			} else {
				log_info("Found new EEPROM config (start=%d, length=%d) for extension %d",
				         start_addr, eeprom_length, i);

				if (i2c_eeprom_write(&i2c_eeprom, start_addr, eeprom_buffer+2, eeprom_length-2) < 0) {
					log_warn("Writing EEPROM config for extension %d failed", i);
				} else {
					log_debug("Wrote EEPROM config (start=%d, length=%d) for extension %d",
					          start_addr, eeprom_length, i);
				}
			}
		}

		if (i2c_eeprom_read(&i2c_eeprom,
		                    EXTENSION_EEPROM_TYPE_LOCATION,
		                    buf,
		                    EXTENSION_EEPROM_TYPE_SIZE) < EXTENSION_EEPROM_TYPE_SIZE) {
			log_info("Could not find Extension at position %d", i);

			continue;
		}

		base_config[i].type = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);

		// If there is an extension that is either not configured (Extension type NONE)
		// Or that we currently don't support (WIFI), we will log it, but try to
		// continue finding extensions. We can support an extension at position 1 if
		// there is an unsupported extension at position 0.
		if (base_config[i].type == EXTENSION_TYPE_NONE) {
			log_warn("Could not find Extension at position %d (Type None)", i);
			continue;
		}

		if ((base_config[i].type != EXTENSION_TYPE_ETHERNET) && (base_config[i].type != EXTENSION_TYPE_RS485)) {
			log_warn("Extension at position %d not supported (type %d)", i, base_config[i].type);
			continue;
		}

		switch (base_config[i].type) {
		case EXTENSION_TYPE_RS485:
			ret = red_extension_read_rs485_config(&i2c_eeprom, (ExtensionRS485Config *) &base_config[i]);
			i2c_eeprom_destroy(&i2c_eeprom);

			if (ret < 0) {
				log_warn("Could not read RS485 config, ignoring extension at position %d", i);

				continue;
			}

			if (red_extension_save_rs485_config_to_fs((ExtensionRS485Config *) &base_config[i]) < 0) {
				log_warn("Could not save RS485 config. RS485 Extension at position %d will not show up in Brick Viewer", i);
			}

			break;

		case EXTENSION_TYPE_ETHERNET:
			ret = red_extension_read_ethernet_config(&i2c_eeprom, (ExtensionEthernetConfig *) &base_config[i]);
			i2c_eeprom_destroy(&i2c_eeprom);

			if (ret < 0) {
				log_warn("Could not read Ethernet config, ignoring extension at position %d", i);

				continue;
			}

			if (red_extension_save_ethernet_config_to_fs((ExtensionEthernetConfig *) &base_config[i]) < 0) {
				log_warn("Could not save Ethernet config. Ethernet Extension at position %d will not show up in Brick Viewer", i);
			}

			break;
		}
	}

	// Configure the pins and initialize extensions
	for (i = 0; i < EXTENSION_NUM_MAX; i++) {
		switch (base_config[i].type) {
		case EXTENSION_TYPE_RS485:
			log_info("Found RS485 Extension at position %d", i);

			for (j = 0; j < extension_rs485_pin_config.num_configs; j++) {
				red_extension_configure_pin(&extension_rs485_pin_config.config[j], i);
			}

			if (red_rs485_extension_init((ExtensionRS485Config *) &base_config[i]) < 0) {
				continue;
			}

			_red_extension_type[i] = EXTENSION_TYPE_RS485;
			break;

		case EXTENSION_TYPE_ETHERNET:
			log_info("Found Ethernet Extension at position %d", i);

			for (j = 0; j < extension_ethernet_pin_config.num_configs; j++) {
				red_extension_configure_pin(&extension_ethernet_pin_config.config[j], i);
			}

			if (red_ethernet_extension_init((ExtensionEthernetConfig *) &base_config[i]) < 0) {
				continue;
			}

			_red_extension_type[i] = EXTENSION_TYPE_ETHERNET;
			break;
		}
	}

	return 0;
}