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); }
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); }
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(); }
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; }
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; }
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; }
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; }