/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }