예제 #1
0
/**
 * @brief   Starts a sequential read.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] startblk  first block to read
 *
 * @return              The operation status.
 * @retval CH_SUCCESS   the operation succeeded.
 * @retval CH_FAILED    the operation failed.
 *
 * @api
 */
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {

  chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");
  chDbgAssert(mmcp->state == BLK_READY,
              "mmcStartSequentialRead(), #1", "invalid state");

  /* Read operation in progress.*/
  mmcp->state = BLK_READING;

  /* (Re)starting the SPI in case it has been reprogrammed externally, it can
     happen if the SPI bus is shared among multiple peripherals.*/
  spiStart(mmcp->config->spip, mmcp->config->hscfg);
  spiSelect(mmcp->config->spip);

  if (mmcp->block_addresses)
    send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk);
  else
    send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE);

  if (recvr1(mmcp) != 0x00) {
    spiStop(mmcp->config->spip);
    return CH_FAILED;
  }
  return CH_SUCCESS;
}
예제 #2
0
파일: mmc_spi.c 프로젝트: glockwork/dfu
/**
 * @brief   Starts a sequential write.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] startblk  first block to write
 * @return              The operation status.
 * @retval FALSE        the operation succeeded.
 * @retval TRUE         the operation failed.
 *
 * @api
 */
bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {

  chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite");

  chSysLock();
  if (mmcp->state != MMC_READY) {
    chSysUnlock();
    return TRUE;
  }
  mmcp->state = MMC_WRITING;
  chSysUnlock();

  spiStart(mmcp->spip, mmcp->hscfg);
  spiSelect(mmcp->spip);
  if(mmcp->block_addresses)
    send_hdr(mmcp, MMC_CMDWRITEMULTIPLE, startblk);
  else
    send_hdr(mmcp, MMC_CMDWRITEMULTIPLE, startblk * MMC_SECTOR_SIZE);


  if (recvr1(mmcp) != 0x00) {
    spiUnselect(mmcp->spip);
    chSysLock();
    if (mmcp->state == MMC_WRITING)
      mmcp->state = MMC_READY;
    chSysUnlock();
    return TRUE;
  }
  return FALSE;
}
예제 #3
0
파일: hal_mmc_spi.c 프로젝트: mabl/ChibiOS
/**
 * @brief   Starts a sequential write.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] startblk  first block to write
 *
 * @return              The operation status.
 * @retval HAL_SUCCESS   the operation succeeded.
 * @retval HAL_FAILED    the operation failed.
 *
 * @api
 */
bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {

  osalDbgCheck(mmcp != NULL);
  osalDbgAssert(mmcp->state == BLK_READY, "invalid state");

  /* Write operation in progress.*/
  mmcp->state = BLK_WRITING;

  spiStart(mmcp->config->spip, mmcp->config->hscfg);
  spiSelect(mmcp->config->spip);
  if (mmcp->block_addresses) {
    send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk);
  }
  else {
    send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
             startblk * MMCSD_BLOCK_SIZE);
  }

  if (recvr1(mmcp) != 0x00U) {
    spiStop(mmcp->config->spip);
    mmcp->state = BLK_READY;
    return HAL_FAILED;
  }
  return HAL_SUCCESS;
}
예제 #4
0
파일: mmc_spi.c 프로젝트: gale320/ChibiOS
/**
 * @brief   Starts a sequential read.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] startblk  first block to read
 *
 * @return              The operation status.
 * @retval FALSE        the operation succeeded.
 * @retval TRUE         the operation failed.
 *
 * @api
 */
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {

  chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");

  chSysLock();
  if (mmcp->state != MMC_READY) {
    chSysUnlock();
    return TRUE;
  }
  mmcp->state = MMC_READING;
  chSysUnlock();

  spiStart(mmcp->config->spip, mmcp->config->hscfg);
  spiSelect(mmcp->config->spip);

  if(mmcp->block_addresses)
    send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk);
  else
    send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE);

  if (recvr1(mmcp) != 0x00) {
    spiUnselect(mmcp->config->spip);
    chSysLock();
    if (mmcp->state == MMC_READING)
      mmcp->state = MMC_READY;
    chSysUnlock();
    return TRUE;
  }
  return FALSE;
}
예제 #5
0
/**
 * @brief   Reads the CSD.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[out] csd       pointer to the CSD buffer
 *
 * @return              The operation status.
 * @retval CH_SUCCESS   the operation succeeded.
 * @retval CH_FAILED    the operation failed.
 *
 * @notapi
 */
static bool_t read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) {
  unsigned i;
  uint8_t *bp, buf[16];

  spiSelect(mmcp->config->spip);
  send_hdr(mmcp, cmd, 0);
  if (recvr1(mmcp) != 0x00) {
    spiUnselect(mmcp->config->spip);
    return CH_FAILED;
  }

  /* Wait for data availability.*/
  for (i = 0; i < MMC_WAIT_DATA; i++) {
    spiReceive(mmcp->config->spip, 1, buf);
    if (buf[0] == 0xFE) {
      uint32_t *wp;

      spiReceive(mmcp->config->spip, 16, buf);
      bp = buf;
      for (wp = &cxd[3]; wp >= cxd; wp--) {
        *wp = ((uint32_t)bp[0] << 24) | ((uint32_t)bp[1] << 16) |
              ((uint32_t)bp[2] << 8)  | (uint32_t)bp[3];
        bp += 4;
      }

      /* CRC ignored then end of transaction. */
      spiIgnore(mmcp->config->spip, 2);
      spiUnselect(mmcp->config->spip);

      return CH_SUCCESS;
    }
  }
  return CH_FAILED;
}
예제 #6
0
/**
 * @brief   Starts a sequential read.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] startblk  first block to read
 * @return              The operation status.
 * @retval FALSE        the operation was successful.
 * @retval TRUE         the operation failed.
 */
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {

  chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");

  chSysLock();
  if (mmcp->mmc_state != MMC_READY) {
    chSysUnlock();
    return TRUE;
  }
  mmcp->mmc_state = MMC_READING;
  chSysUnlock();

  spiStart(mmcp->mmc_spip, mmcp->mmc_hscfg);
  spiSelect(mmcp->mmc_spip);
  send_hdr(mmcp, MMC_CMDREADMULTIPLE, startblk * MMC_SECTOR_SIZE);
  if (recvr1(mmcp) != 0x00) {
    spiUnselect(mmcp->mmc_spip);
    chSysLock();
    if (mmcp->mmc_state == MMC_READING)
      mmcp->mmc_state = MMC_READY;
    chSysUnlock();
    return TRUE;
  }
  return FALSE;
}
예제 #7
0
/**
 * @brief   Sends a command an returns a single byte response.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] cmd       the command id
 * @param[in] arg       the command argument
 * @return              The response as an @p uint8_t value.
 * @retval 0xFF         timed out.
 *
 * @notapi
 */
static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) {
  uint8_t r1;

  spiSelect(mmcp->config->spip);
  send_hdr(mmcp, cmd, arg);
  r1 = recvr1(mmcp);
  spiUnselect(mmcp->config->spip);
  return r1;
}
예제 #8
0
파일: mmc_spi.c 프로젝트: glockwork/dfu
/**
 * @brief   Sends a command which returns a five bytes response (R3).
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 * @param[in] cmd       the command id
 * @param[in] arg       the command argument
 * @param[out] response pointer to four bytes wide uint8_t buffer
 * @return              The first byte of the response (R1) as an @p
 *                      uint8_t value.
 * @retval 0xFF         timed out.
 *
 * @notapi
 */
static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg,
                               uint8_t *response) {
  uint8_t r1;
  
  spiSelect(mmcp->spip);
  send_hdr(mmcp, cmd, arg);
  r1 = recvr3(mmcp, response);
  spiUnselect(mmcp->spip);
  return r1;
}