Example #1
0
int osChip_init(uint32_t base)
{
	int err = 0, res;
	mem_size = 32*1024*1024;
	mem0 = (unsigned char*)memalign(mem_size, mem_size);
	tfile = fopen("ssd_tb.log", "w+b");

	int i, ch = 7;

	/* wait for ready */
	res = wait_idle(base, ch);
	fmTrace("ready %d.", res);

	/* flash reset */
	osChipRegWrite(base + (ch<<4), 0xff);
	res = wait_idle(base, ch);
	fmTrace("reset flash %d.", res);

	/* change to sync mode */
	osChipRegWrite(base + (ch<<4), 0xef);
	res = wait_idle(base, ch);
	fmTrace("set to sync mode %d.", res);

	/* read */
	osChipRegWrite(base + (ch<<4), 0x01);
	wait_idle(base, ch);
	fmTrace("flash read %d", res);

	return 0;
}
irom static i2c_error_t receive_bit(bool_t *bit)
{
	int current, total;
	i2c_error_t error;

	// at this point scl should be high and sda is unknown,
	// but should be high before reading
	
	if(state == i2c_state_idle)
		return(i2c_error_invalid_state_idle);

	// wait for scl to be released by slave (clock stretching)
	
	if((error = wait_idle()) != i2c_error_ok)
		return(error);
	
	// make sure sda is high (open) so slave can pull it
	// do it while clock is pulled
	
	clear_scl();
	set_sda();

	// wait for slave to pull/release sda

	delay();

	// release clock again

	set_scl();

	// take care of clock stretching

	if((error = wait_idle()) != i2c_error_ok)
		return(error);

	delay();

	// do oversampling of sda, to implement a software
	// low-pass filter / spike filter

	for(total = 0, current = 0; current < i2c_config_sda_sampling_window; current++)
	{
		int set;
		set = sda_is_set();

		total += set ? 4 : 0;

		short_delay();
	}

	if(total < (i2c_config_sda_sampling_window * 1))		// 0-1/4	=> 0
		*bit = 0;
	else if(total < (i2c_config_sda_sampling_window * 3))	// 1/4-3/4	=> error
		return(i2c_error_receive_error);
	else													// 3/4-1	=> 1
		*bit = 1;

	return(i2c_error_ok);
}
Example #3
0
int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
{
	int timeout = I2C_MAX_TIMEOUT;
	char i = 0;
	//printf("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d, data: %d\n", __func__, chip, addr, alen, len, *buf);
	__REG16(i2c_port_addr[i2c_port_num] + I2SR) = 0;
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) = I2CR_IEN;
	/* Wait controller to be stable */
	udelay(50);
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) |= I2CR_MSTA;
	/* Start I2C transaction */
	wait_busy();
	
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) |= I2CR_IIEN | I2CR_MTX | I2CR_TX_NO_AK;
	__REG16(i2c_port_addr[i2c_port_num] + I2DR) = chip << 1;
	wait_complete();
	for(i = 0; i < len; i++){
		__REG16(i2c_port_addr[i2c_port_num] + I2DR) = *(buf+i);
		wait_complete();
	}	
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) &= ~(I2CR_MSTA | I2CR_MTX);
	wait_idle();
	__REG16(i2c_port_addr[i2c_port_num] + I2CR)  = 0;
	return 0;
}
irom static i2c_error_t send_bit(bool_t bit)
{
	i2c_error_t error;

	// at this point scl should be high and sda will be unknown
	// wait for scl to be released by slave (clock stretching)
	
	if((error = wait_idle()) != i2c_error_ok)
		return(error);
	
	clear_scl();
	delay();

	if(scl_is_set())
		return(i2c_error_bus_lock);

	if(bit)
	{
		set_sda();
		delay();

		if(!sda_is_set())
			return(i2c_error_sda_stuck);
	}
	else
	{
		clear_sda();
		delay();

		if(sda_is_set())
			return(i2c_error_sda_stuck);
	}

	set_scl();
	delay();

	// take care of clock stretching

	if((error = wait_idle()) != i2c_error_ok)
		return(error);

	return(i2c_error_ok);
}
irom static i2c_error_t send_start(void)
{
	i2c_error_t error;
	int current;

	if(state != i2c_state_start_send)
		return(i2c_error_invalid_state_not_send_start);

	// wait for scl and sda to be released by all masters and slaves
	
	state = i2c_state_bus_wait_1;

	if((error = wait_idle()) != i2c_error_ok)
		return(error);

	// set sda to high

	clear_scl();
	delay();

	if(scl_is_set())
		return(i2c_error_bus_lock);

	set_sda();
	delay();

	if(!sda_is_set())
		return(i2c_error_sda_stuck);

	set_scl();
	delay();

	state = i2c_state_bus_wait_2;

	// demand bus is idle for a minimum window

	for(current = i2c_config_scl_sampling_window; current > 0; current--)
	{
		if(!scl_is_set() || !sda_is_set())
			return(i2c_error_bus_lock);
		short_delay();
	}

	// generate start condition by leaving scl high and pulling sda low

	clear_sda();
	delay();

	if(sda_is_set())
		return(i2c_error_sda_stuck);

	return(i2c_error_ok);
}
irom static i2c_error_t send_stop(void)
{
	i2c_error_t error;

	if(state != i2c_state_stop_send)
		return(i2c_error_invalid_state_not_send_stop);

	// at this point scl should be high and sda is unknown
	// wait for scl to be released by all masters and slaves
	
	if((error = wait_idle()) != i2c_error_ok)
		return(error);

	delay();

	// set sda to low

	clear_scl();
	delay();

	if(scl_is_set())
		return(i2c_error_bus_lock);

	clear_sda();
	delay();

	if(sda_is_set())
		return(i2c_error_sda_stuck);

	set_scl();
	delay();

	if(sda_is_set())
		return(i2c_error_sda_stuck);

	if(!scl_is_set())
		return(i2c_error_bus_lock);

	// now generate the stop condition by leaving scl high and setting sda high

	set_sda();
	delay();

	if(!scl_is_set())
		return(i2c_error_bus_lock);

	if(!sda_is_set())
		return(i2c_error_sda_stuck);

	return(i2c_error_ok);
}
Example #7
0
void Hologram::Worker::draw_objects(VkFramebuffer fb) {
    // wait for step_objects first
    wait_idle();

    {
        std::lock_guard<std::mutex> lock(mutex_);
        bool started = (state_ != INIT);

        fb_ = fb;
        state_ = DRAW;

        // render directly
        if (!started) {
            hologram_.draw_objects(*this);
            state_ = INIT;
        }
    }
    state_cv_.notify_one();
}
Example #8
0
int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
{
	int timeout = I2C_MAX_TIMEOUT;
	char i = 0;
	uchar temp = 0;
	uchar temp2 = 0;
	DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", __func__, chip, addr, alen, len);

	__REG16(i2c_port_addr[i2c_port_num] + I2SR) = 0;
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) = I2CR_IEN;
	/* Wait controller to be stable */
	udelay(50);
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) |= I2CR_MSTA;
	/* Start I2C transaction */
	wait_busy();
	
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) |= I2CR_IIEN | I2CR_MTX | I2CR_TX_NO_AK;
	__REG16(i2c_port_addr[i2c_port_num] + I2DR) = chip << 1;
	wait_complete();
	__REG16(i2c_port_addr[i2c_port_num] + I2DR) = addr;		// address 0 -> version
	wait_complete();	// write finish: address and addr
	//DPRINTF("i2c_read: write addr done\n");
	udelay(500);
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX | I2CR_RSTA;
	/* Restart I2C transaction */
	wait_busy();
	__REG16(i2c_port_addr[i2c_port_num] + I2DR) = (chip << 1) | 0x01;
	wait_complete();
	//DPRINTF("i2c_read: read action send\n");	
	udelay(500);
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_TX_NO_AK;
	temp = __REG16(i2c_port_addr[i2c_port_num] + I2DR);
	wait_complete();
	__REG16(i2c_port_addr[i2c_port_num] + I2CR) &= ~(I2CR_MSTA | I2CR_MTX);
	wait_idle();
	*buf =  __REG16(i2c_port_addr[i2c_port_num] + I2DR);
	DPRINTF("i2c_read temp: 0x%x, buf: 0x%x\n", temp, *buf);
	__REG16(i2c_port_addr[i2c_port_num] + I2CR)  = 0;
	return 0;
}
Example #9
0
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop)
{
	uint8_t tmp __attribute__((unused));
	uint8_t status, count=0;
	uint32_t wait_begin;

	rxBufferIndex = 0;
	rxBufferLength = 0;
	//serial_print("requestFrom\n");
	// clear the status flags
	port().S = I2C_S_IICIF | I2C_S_ARBL;
	// now take control of the bus...
	if (port().C1 & I2C_C1_MST) {
		// we are already the bus master, so send a repeated start
		port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX;
	} else {
		// we are not currently the bus master, so wait for bus ready
		if (!wait_idle()) {
			//Serial.printf("requestFrom err1\n");
			return 0; // timeout waiting for bus
		}
		// become the bus master in transmit mode (send start)
		slave_mode = 0;
		port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
	}

	// wait until start condition establishes control of the bus
	wait_begin = millis();
	while (1) {
		status = i2c_status();
		if ((status & I2C_S_BUSY)) break;
		if (millis() - wait_begin > 4) {
			port().C1 = 0;
			port().C1 = I2C_C1_IICEN;
			//Serial.printf("requestFrom err2\n");
			return 0; // error generating start condition
		}
	}
	// send the address
	port().D = (address << 1) | 1;
	wait_begin = millis();
	while (!(port().S & I2C_S_IICIF)) {
		if (millis() - wait_begin > 5) {
			port().C1 = 0;
			port().C1 = I2C_C1_IICEN;
			//Serial.printf("requestFrom err3\n");
			return 0; // clock stretch too long (during address)
		}
	}
	port().S = I2C_S_IICIF;
	status = i2c_status();
	if ((status & I2C_S_RXAK) || (status & I2C_S_ARBL)) {
		// the slave device did not acknowledge
		// or we lost bus arbitration to another master
		port().C1 = I2C_C1_IICEN;
		//Serial.printf("requestFrom err4\n");
		return 0;
	}
	if (length == 0) {
		// TODO: does anybody really do zero length reads?
		// if so, does this code really work?
		port().C1 = I2C_C1_IICEN | (sendStop ? 0 : I2C_C1_MST);
		//Serial.printf("requestFrom err5\n");
		return 0;
	} else if (length == 1) {
		port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK;
	} else {
		port().C1 = I2C_C1_IICEN | I2C_C1_MST;
	}
	tmp = port().D; // initiate the first receive
	//delayMicroseconds(250);
	while (length > 1) {
		wait_begin = millis();
		while (!(port().S & I2C_S_IICIF)) {
			if (millis() - wait_begin > 5) {
				port().C1 = 0;
				port().C1 = I2C_C1_IICEN;
				rxBufferLength = count;
				//Serial.printf("requestFrom err6\n");
				return count; // clock stretch too long (during data)
			}
		}
		port().S = I2C_S_IICIF;
		status = port().S;
		if ((status & I2C_S_ARBL)) {
			// we lost bus arbitration to another master
			// or suddenly lost control of the bus!
			// TODO: what is the proper thing to do here??
			//Serial.printf("requestFrom err7a\n");
			return count;
		}
		if (!(status & I2C_S_BUSY)) {
			// we lost bus arbitration to another master
			// or suddenly lost control of the bus!
			// TODO: what is the proper thing to do here??
			//Serial.printf("requestFrom err7b\n");
			return count;
		}
		length--;
		if (length == 1) port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK;
		if (count < BUFFER_LENGTH) {
			rxBuffer[count++] = port().D;
		} else {
			tmp = port().D;
		}
	}
	wait_begin = millis();
	while (!(port().S & I2C_S_IICIF)) {
		if (millis() - wait_begin > 5) {
			port().C1 = 0;
			port().C1 = I2C_C1_IICEN;
			rxBufferLength = count;
			//Serial.printf("requestFrom err8\n");
			return count; // clock stretch too long (during data)
		}
	}
	port().S = I2C_S_IICIF;
	status = port().S;
	if ((status & I2C_S_ARBL)) {
		// we lost bus arbitration to another master
		// or suddenly lost control of the bus!
		// TODO: what is the proper thing to do here??
		//digitalWriteFast(13, HIGH);
		port().S = I2C_S_ARBL;
		delayMicroseconds(5);
		port().C1 &= ~I2C_C1_TXAK;
		//Serial.printf("requestFrom err9a\n");
		return count;
	}
	if (!(status & I2C_S_BUSY)) {
		// we lost bus arbitration to another master
		// or suddenly lost control of the bus!
		// TODO: what is the proper thing to do here??
		//Serial.printf("requestFrom err9b\n");
		return count;
	}
	port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
	if (count < BUFFER_LENGTH) {
		rxBuffer[count++] = port().D;
	} else {
		tmp = port().D;
	}
#if F_CPU > 120000000
	__asm__("nop");
	__asm__("nop");
	__asm__("nop");
#endif
	if (sendStop) port().C1 = I2C_C1_IICEN;
	rxBufferLength = count;
	return count;
}
Example #10
0
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
	uint8_t i, status, ret=0;
	uint32_t wait_begin;

	// clear the status flags
	port().S = I2C_S_IICIF | I2C_S_ARBL;
	// now take control of the bus...
	if (port().C1 & I2C_C1_MST) {
		// we are already the bus master, so send a repeated start
		//Serial.print("rstart:");
		port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX;
	} else {
		// we are not currently the bus master, so wait for bus ready
		if (!wait_idle()) {
			//Serial.printf("endTransmission err1\n");
			return 4; // timeout waiting for bus
		}
		// become the bus master in transmit mode (send start)
		slave_mode = 0;
		port().C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
	}
	// wait until start condition establishes control of the bus
	wait_begin = millis();
	while (1) {
		status = i2c_status();
		if ((status & I2C_S_BUSY)) break;
		//Serial.write('*') ;
		if (millis() - wait_begin > 4) {
			port().C1 = 0;
			port().C1 = I2C_C1_IICEN;
			//Serial.println("abort2");
			//Serial.printf("endTransmission err2\n");
			return 4; // error generating start condition
		}
	}
	// transmit the address and data
	for (i=0; i < txBufferLength; i++) {
		port().D = txBuffer[i];
		//Serial.write('^');
		wait_begin = millis();
		while (1) {
			status = i2c_status();
			if ((status & I2C_S_IICIF)) break;
			if (!(status & I2C_S_BUSY)) break;
			if (millis() - wait_begin > 5) {
				port().C1 = 0;
				port().C1 = I2C_C1_IICEN;
				//Serial.println("abort3");
				//Serial.printf("endTransmission err3\n");
				return 4; // clock stretch too long
			}
		}
		port().S = I2C_S_IICIF;
		//Serial.write('$');
		status = i2c_status();
		if ((status & I2C_S_ARBL)) {
			// we lost bus arbitration to another master
			// TODO: what is the proper thing to do here??
			//Serial.printf(" c1=%02X ", port().C1);
			port().C1 = I2C_C1_IICEN;
			//Serial.printf("endTransmission err4\n");
			ret = 4; // 4:other error
			break;
		}
		if (!(status & I2C_S_BUSY)) {
			// suddenly lost control of the bus!
			port().C1 = I2C_C1_IICEN;
			//Serial.printf("endTransmission err5\n");
			ret = 4; // 4:other error
			break;
		}
		if (status & I2C_S_RXAK) {
			// the slave device did not acknowledge
			if (i == 0) {
				//Serial.printf("endTransmission err6\n");
				ret = 2; // 2:received NACK on transmit of address
			} else {
				//Serial.printf("endTransmission err7\n");
				ret = 3; // 3:received NACK on transmit of data 
			}
			sendStop = 1;
			break;
		}
	}
	if (sendStop) {
		// send the stop condition
		port().C1 = I2C_C1_IICEN;
		// TODO: do we wait for this somehow?
	}
	transmitting = 0;
	//Serial.print(" ret=");
	//Serial.println(ret);
	return ret;
}
Example #11
0
File: i2c.c Project: thehobn/ec
int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
	     uint8_t *in, int in_size, int flags)
{
	int i;
	int started = (flags & I2C_XFER_START) ? 0 : 1;
	uint8_t reg_sts;

	if (out_size == 0 && in_size == 0)
		return EC_SUCCESS;

	wait_idle(port);

	reg_sts = MEC1322_I2C_STATUS(port);
	if (!started &&
	    (((reg_sts & (STS_BER | STS_LAB)) || !(reg_sts & STS_NBB)) ||
			    (i2c_get_line_levels(port) != I2C_LINE_IDLE))) {
		CPRINTS("I2C%d bad status 0x%02x, SCL=%d, SDA=%d", port,
			reg_sts,
			i2c_get_line_levels(port) & I2C_LINE_SCL_HIGH,
			i2c_get_line_levels(port) & I2C_LINE_SDA_HIGH);

		/* Attempt to unwedge the port. */
		i2c_unwedge(port);

		/* Bus error, bus busy, or arbitration lost. Reset port. */
		reset_port(port);

		/*
		 * We don't know what edges the slave saw, so sleep long enough
		 * that the slave will see the new start condition below.
		 */
		usleep(1000);
	}

	if (out) {
		MEC1322_I2C_DATA(port) = (uint8_t)slave_addr;

		/*
		 * Clock out the slave address. Send START bit if start flag is
		 * set.
		 */
		MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_ENI |
					 CTRL_ACK | (started ? 0 : CTRL_STA);
		if (!started)
			started = 1;

		for (i = 0; i < out_size; ++i) {
			if (wait_byte_done(port))
				goto err_i2c_xfer;
			MEC1322_I2C_DATA(port) = out[i];
		}
		if (wait_byte_done(port))
			goto err_i2c_xfer;

		/*
		 * Send STOP bit if the stop flag is on, and caller
		 * doesn't expect to receive data.
		 */
		if ((flags & I2C_XFER_STOP) && in_size == 0) {
			MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO |
						 CTRL_STO | CTRL_ACK;
		}
	}

	if (in_size) {
		if (out_size) {
			/* resend start bit when change direction */
			MEC1322_I2C_CTRL(port) = CTRL_ESO | CTRL_STA |
						 CTRL_ACK | CTRL_ENI;
		}

		MEC1322_I2C_DATA(port) = (uint8_t)slave_addr | 0x01;

		if (!started) {
			started = 1;
			/* Clock out slave address with START bit */
			MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO |
						 CTRL_STA | CTRL_ACK | CTRL_ENI;
		}

		/* On MEC1322, first byte read is dummy read (slave addr) */
		in_size++;

		for (i = 0; i < in_size - 2; ++i) {
			if (wait_byte_done(port))
				goto err_i2c_xfer;
			fill_in_buf(in, i, MEC1322_I2C_DATA(port));
		}
		if (wait_byte_done(port))
			goto err_i2c_xfer;

		/*
		 * De-assert ACK bit before reading the next to last byte,
		 * so that the last byte is NACK'ed.
		 */
		MEC1322_I2C_CTRL(port) = CTRL_ESO | CTRL_ENI;
		fill_in_buf(in, in_size - 2, MEC1322_I2C_DATA(port));
		if (wait_byte_done(port))
			goto err_i2c_xfer;

		/* Send STOP if stop flag is set */
		MEC1322_I2C_CTRL(port) =
			CTRL_PIN | CTRL_ESO | CTRL_ACK |
			((flags & I2C_XFER_STOP) ? CTRL_STO : 0);

		/* Now read the last byte */
		fill_in_buf(in, in_size - 1, MEC1322_I2C_DATA(port));
	}

	/* Check for error conditions */
	if (MEC1322_I2C_STATUS(port) & (STS_LAB | STS_BER))
		return EC_ERROR_UNKNOWN;

	return EC_SUCCESS;
err_i2c_xfer:
	/* Send STOP and return error */
	MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK;
	return EC_ERROR_UNKNOWN;
}