Exemplo n.º 1
0
static int spi_flash_send_write_sequence(spi_flash_dev *sfd) {
  u32_t addr = sfd->addr;
  u32_t len_rem_page = sfd->flash_conf.size_page_write_max - (addr & (sfd->flash_conf.size_page_write_max - 1));
  u32_t len_to_write = MIN(len_rem_page, sfd->count);
  if (len_to_write == 0) {
    len_to_write = MIN(sfd->count, sfd->flash_conf.size_page_write_max);
  }

  spi_flash_set_first_seq_to_wren(sfd);

  sfd->tmp_buf[0] = sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_WRITE];
  spi_flash_fill_in_address(sfd, &sfd->tmp_buf[1], addr);
  sfd->sequence_buf[1].tx = &sfd->tmp_buf[0];
  sfd->sequence_buf[1].tx_len = 1 + sfd->flash_conf.addressing_bytes + 1;
  sfd->sequence_buf[1].rx = 0;
  sfd->sequence_buf[1].rx_len = 0;
  sfd->sequence_buf[1].cs_release = 0;

  sfd->sequence_buf[2].tx = (u8_t*)sfd->ptr;
  sfd->sequence_buf[2].tx_len = len_to_write;
  sfd->sequence_buf[2].rx = 0;
  sfd->sequence_buf[2].rx_len = 0;
  sfd->sequence_buf[2].cs_release = 0;

  int res = spi_flash_exec(sfd, &sfd->sequence_buf[0], 3);

  if (res == SPI_OK) {
    sfd->addr += len_to_write;
    sfd->ptr += len_to_write;
    sfd->count -= len_to_write;
  }

  return res;
}
Exemplo n.º 2
0
int spi_flash_read_reg(struct spi_flash *flash, u8 inst, u8 *buf, size_t len)
{
	struct spi_flash_command cmd;

	spi_flash_command_init(&cmd, inst, 0, SFLASH_TYPE_READ_REG);
	cmd.proto = flash->reg_proto;
	cmd.data_len = len;
	cmd.rx_data = buf;
	return spi_flash_exec(flash, &cmd);
}
Exemplo n.º 3
0
int SPI_FLASH_read_busy(spi_flash_dev *sfd, spi_flash_callback cb, u8_t *res) {
  spi_dev_sequence seq;
  sfd->state = SPI_FLASH_STATE_READ_BUSY;
  sfd->sr_dst = res;
  seq.tx = (u8_t*)&sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_READ_SR];
  seq.tx_len = 1;
  seq.rx = &sfd->sr_tmp;
  seq.rx_len = 1;
  seq.cs_release = 0;
  sfd->spi_flash_callback = cb;

  return spi_flash_exec(sfd, &seq, 1);
}
Exemplo n.º 4
0
static int spi_flash_closeprotectun(spi_flash_dev *sfd, char unprotect) {
  spi_flash_set_first_seq_to_wren(sfd);

  sfd->tmp_buf[0] = sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_WRITE_SR];
  sfd->tmp_buf[1] = sfd->flash_conf.cmd_defs[unprotect ? SPI_FLASH_CMD_SR_UNPROTECT : SPI_FLASH_CMD_SR_PROTECT];
  sfd->sequence_buf[1].tx = &sfd->tmp_buf[0];
  sfd->sequence_buf[1].tx_len = 2;
  sfd->sequence_buf[1].rx = 0;
  sfd->sequence_buf[1].rx_len = 0;
  sfd->sequence_buf[1].cs_release = 0;

  return spi_flash_exec(sfd, &sfd->sequence_buf[0], 2);
}
Exemplo n.º 5
0
int SPI_FLASH_open(spi_flash_dev *sfd, spi_flash_callback cb) {
  if (sfd->open) {
    return SPI_FLASH_ERR_OPENED;
  }
  if (sfd->busy) {
    return SPI_FLASH_ERR_BUSY;
  }
  sfd->busy = TRUE;

  sfd->state = SPI_FLASH_STATE_OPENING_READ_ID;
  sfd->sequence_buf[0].tx = (u8_t*)&sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_READ_ID];
  sfd->sequence_buf[0].tx_len = 1;
  sfd->sequence_buf[0].rx = sfd->tmp_buf;
  sfd->sequence_buf[0].rx_len = 3;

  sfd->sequence_buf[0].cs_release = 0;
  sfd->spi_flash_callback = cb;

  return spi_flash_exec(sfd, &sfd->sequence_buf[0], 1);
}
Exemplo n.º 6
0
int SPI_FLASH_mass_erase(spi_flash_dev *sfd, spi_flash_callback cb) {
  if (!sfd->open) {
    return SPI_FLASH_ERR_CLOSED;
  }
  if (sfd->busy) {
    return SPI_FLASH_ERR_BUSY;
  }
  sfd->busy = TRUE;
  sfd->state = SPI_FLASH_STATE_MASS_ERASE;
  sfd->spi_flash_callback = cb;

  spi_flash_set_first_seq_to_wren(sfd);

  sfd->sequence_buf[1].tx = (u8_t*)&sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_MASS_ERASE];
  sfd->sequence_buf[1].tx_len = 1;
  sfd->sequence_buf[1].rx = 0;
  sfd->sequence_buf[1].rx_len = 0;
  sfd->sequence_buf[1].cs_release = 0;

  return spi_flash_exec(sfd, &sfd->sequence_buf[0], 2);
}
Exemplo n.º 7
0
static int spi_flash_send_erase_sequence(spi_flash_dev *sfd) {
  u32_t addr = sfd->addr;
  u32_t len = sfd->flash_conf.size_sector_erase_min;

  spi_flash_set_first_seq_to_wren(sfd);

  sfd->tmp_buf[0] = sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_SECTOR_ERASE];
  spi_flash_fill_in_address(sfd, &sfd->tmp_buf[1], addr);
  sfd->sequence_buf[1].tx = &sfd->tmp_buf[0];
  sfd->sequence_buf[1].tx_len = 1 + sfd->flash_conf.addressing_bytes + 1;
  sfd->sequence_buf[1].rx = 0;
  sfd->sequence_buf[1].rx_len = 0;
  sfd->sequence_buf[1].cs_release = 0;

  int res = spi_flash_exec(sfd, &sfd->sequence_buf[0], 2);

  if (res == SPI_OK) {
    sfd->addr += len;
    sfd->count -= len;
  }

  return res;
}
Exemplo n.º 8
0
int SPI_FLASH_read(spi_flash_dev *sfd, spi_flash_callback cb, u32_t addr, u16_t size, u8_t *dest) {
  if (!sfd->open) {
    return SPI_FLASH_ERR_CLOSED;
  }
  if (addr > sfd->flash_conf.size_total || (addr+size) > sfd->flash_conf.size_total) {
    return SPI_FLASH_ERR_ADDRESS;
  }
  if (sfd->busy) {
    return SPI_FLASH_ERR_BUSY;
  }
  sfd->busy = TRUE;
  sfd->state = SPI_FLASH_STATE_READ;

  sfd->tmp_buf[0] = sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_READ];
  spi_flash_fill_in_address(sfd, &sfd->tmp_buf[1], (u32_t)addr);
  sfd->sequence_buf[0].tx = &sfd->tmp_buf[0];
  sfd->sequence_buf[0].tx_len = 1 + (1+sfd->flash_conf.addressing_bytes);
  sfd->sequence_buf[0].rx = dest;
  sfd->sequence_buf[0].rx_len = size;
  sfd->sequence_buf[0].cs_release = 0;
  sfd->spi_flash_callback = cb;

  return spi_flash_exec(sfd, &sfd->sequence_buf[0], 1);
}
Exemplo n.º 9
0
/*
 * spi flash task function, used for reporting finished operations to user and
 * to keep state of intermediate operations
 */
static void spi_flash_task_f(u32_t res_u, void *sfd_v) {

  int res = (int)res_u;
  spi_flash_dev *sfd = (spi_flash_dev *)sfd_v;
  ASSERT(sfd);

  if (sfd->busy_poll) {
    spi_dev_sequence seq;
    // busy poll, fire off an SR read

    sfd->poll_count++;
    DBG(D_SPI, D_DEBUG, "SPIF poll: SR busy %i/%i?\n", sfd->poll_count, sfd->flash_conf.busy_poll_divisor);
    seq.tx = (u8_t*)&sfd->flash_conf.cmd_defs[SPI_FLASH_CMD_READ_SR];
    seq.tx_len = 1;
    seq.rx = sfd->tmp_buf;
    seq.rx_len = 1;
    seq.cs_release = 0;
    res = spi_flash_exec(sfd, &seq, 1);
    if (res == SPI_ERR_DEV_BUSY && sfd->poll_count < 16) {
      DBG(D_SPI, D_INFO, "SPIF poll: device busy\n");
    } else if (res != SPI_OK) {
      DBG(D_SPI, D_WARN, "SPIF poll: ERROR %i\n", res);
      TASK_stop_timer(&sfd->timer);
      sfd->busy_poll = FALSE;

      sfd->state = SPI_FLASH_STATE_ERROR;
      spi_flash_finalize(sfd, res);
    }
    return;
  }

  // if res != SPI_OK, state is always SPI_FLASH_STATE_ERROR here

  switch (sfd->state) {
  case SPI_FLASH_STATE_WRITE_WAIT: {
    if (sfd->count > 0) {
      // more to write
      sfd->state = SPI_FLASH_STATE_WRITE_SEQ;
      res = spi_flash_send_write_sequence(sfd);
      if (res != SPI_OK) {
        // error in middle of write
        sfd->state = SPI_FLASH_STATE_ERROR;
        spi_flash_finalize(sfd, res);
      }
    } else {
      // finished
      sfd->state = SPI_FLASH_STATE_OPENED;
      spi_flash_finalize(sfd, res);
    }
    break;
  }
  case SPI_FLASH_STATE_ERASE_WAIT: {
    if (sfd->count > 0) {
      // more to erase
      sfd->state = SPI_FLASH_STATE_ERASE_SEQ;
      res = spi_flash_send_erase_sequence(sfd);
      if (res != SPI_OK) {
        // error in middle of erase
        sfd->state = SPI_FLASH_STATE_ERROR;
        spi_flash_finalize(sfd, res);
      }
    } else {
      // finished
      sfd->state = SPI_FLASH_STATE_OPENED;
      spi_flash_finalize(sfd, res);
    }
    break;
  }
  case SPI_FLASH_STATE_CLOSED:
    if (sfd->open) {
      SPI_DEV_close(&sfd->dev);
      spi_flash_finalize(sfd, res);
      TASK_stop_timer(&sfd->timer);
      TASK_free(sfd->task);
      sfd->open = FALSE;
    }
  break;
  case SPI_FLASH_STATE_WRSR_WAIT:
  case SPI_FLASH_STATE_OPENED:
  case SPI_FLASH_STATE_ERROR:
    spi_flash_finalize(sfd, res);
  break;
  default:
    sfd->state = SPI_FLASH_STATE_ERROR;
    if (sfd->open) {
      SPI_DEV_close(&sfd->dev);
      spi_flash_finalize(sfd, res);
      TASK_stop_timer(&sfd->timer);
      TASK_free(sfd->task);
      sfd->open = FALSE;
    }
    break;
  }
}