Beispiel #1
0
void cmd_sdc(BaseSequentialStream *chp, int argc, char *argv[]) {
  static const char *mode[] = {"SDV11", "SDV20", "MMC", NULL};
  systime_t start, end;
  uint32_t n, startblk;

  if (argc != 1) {
    chprintf(chp, "Usage: sdiotest read|write|erase|all\r\n");
    return;
  }

  /* Card presence check.*/
  if (!blkIsInserted(&SDCD1)) {
    chprintf(chp, "Card not inserted, aborting.\r\n");
    return;
  }

  /* Connection to the card.*/
  chprintf(chp, "Connecting... ");
  if (sdcConnect(&SDCD1)) {
    chprintf(chp, "failed\r\n");
    return;
  }

  chprintf(chp, "OK\r\n\r\nCard Info\r\n");
  chprintf(chp, "CSD      : %08X %8X %08X %08X \r\n",
           SDCD1.csd[3], SDCD1.csd[2], SDCD1.csd[1], SDCD1.csd[0]);
  chprintf(chp, "CID      : %08X %8X %08X %08X \r\n",
           SDCD1.cid[3], SDCD1.cid[2], SDCD1.cid[1], SDCD1.cid[0]);
  chprintf(chp, "Mode     : %s\r\n", mode[SDCD1.cardmode & 3U]);
  chprintf(chp, "Capacity : %DMB\r\n", SDCD1.capacity / 2048);

  /* The test is performed in the middle of the flash area.*/
  startblk = (SDCD1.capacity / MMCSD_BLOCK_SIZE) / 2;

  if ((strcmp(argv[0], "read") == 0) ||
      (strcmp(argv[0], "all") == 0)) {

    /* Single block read performance, aligned.*/
    chprintf(chp, "Single block aligned read performance:           ");
    start = chVTGetSystemTime();
    end = start + MS2ST(1000);
    n = 0;
    do {
      if (blkRead(&SDCD1, startblk, buf, 1)) {
        chprintf(chp, "failed\r\n");
        goto exittest;
      }
      n++;
    } while (chVTIsSystemTimeWithin(start, end));
    chprintf(chp, "%D blocks/S, %D bytes/S\r\n", n, n * MMCSD_BLOCK_SIZE);

    /* Multiple sequential blocks read performance, aligned.*/
    chprintf(chp, "16 sequential blocks aligned read performance:   ");
    start = chVTGetSystemTime();
    end = start + MS2ST(1000);
    n = 0;
    do {
      if (blkRead(&SDCD1, startblk, buf, SDC_BURST_SIZE)) {
        chprintf(chp, "failed\r\n");
        goto exittest;
      }
      n += SDC_BURST_SIZE;
    } while (chVTIsSystemTimeWithin(start, end));
    chprintf(chp, "%D blocks/S, %D bytes/S\r\n", n, n * MMCSD_BLOCK_SIZE);

#if STM32_SDC_SDIO_UNALIGNED_SUPPORT
    /* Single block read performance, unaligned.*/
    chprintf(chp, "Single block unaligned read performance:         ");
    start = chVTGetSystemTime();
    end = start + MS2ST(1000);
    n = 0;
    do {
      if (blkRead(&SDCD1, startblk, buf + 1, 1)) {
        chprintf(chp, "failed\r\n");
        goto exittest;
      }
      n++;
    } while (chVTIsSystemTimeWithin(start, end));
    chprintf(chp, "%D blocks/S, %D bytes/S\r\n", n, n * MMCSD_BLOCK_SIZE);

    /* Multiple sequential blocks read performance, unaligned.*/
    chprintf(chp, "16 sequential blocks unaligned read performance: ");
    start = chVTGetSystemTime();
    end = start + MS2ST(1000);
    n = 0;
    do {
      if (blkRead(&SDCD1, startblk, buf + 1, SDC_BURST_SIZE)) {
        chprintf(chp, "failed\r\n");
        goto exittest;
      }
      n += SDC_BURST_SIZE;
    } while (chVTIsSystemTimeWithin(start, end));
    chprintf(chp, "%D blocks/S, %D bytes/S\r\n", n, n * MMCSD_BLOCK_SIZE);
#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */
  }

  if ((strcmp(argv[0], "write") == 0) ||
      (strcmp(argv[0], "all") == 0)) {
    unsigned i;

    memset(buf, 0xAA, MMCSD_BLOCK_SIZE * 2);
    chprintf(chp, "Writing...");
    if(sdcWrite(&SDCD1, startblk, buf, 2)) {
      chprintf(chp, "failed\r\n");
      goto exittest;
    }
    chprintf(chp, "OK\r\n");

    memset(buf, 0x55, MMCSD_BLOCK_SIZE * 2);
    chprintf(chp, "Reading...");
    if (blkRead(&SDCD1, startblk, buf, 1)) {
      chprintf(chp, "failed\r\n");
      goto exittest;
    }
    chprintf(chp, "OK\r\n");

    for (i = 0; i < MMCSD_BLOCK_SIZE; i++)
      buf[i] = i + 8;
    chprintf(chp, "Writing...");
    if(sdcWrite(&SDCD1, startblk, buf, 2)) {
      chprintf(chp, "failed\r\n");
      goto exittest;
    }
    chprintf(chp, "OK\r\n");

    memset(buf, 0, MMCSD_BLOCK_SIZE * 2);
    chprintf(chp, "Reading...");
    if (blkRead(&SDCD1, startblk, buf, 1)) {
      chprintf(chp, "failed\r\n");
      goto exittest;
    }
    chprintf(chp, "OK\r\n");
  }

  if ((strcmp(argv[0], "erase") == 0) ||
      (strcmp(argv[0], "all") == 0)) {
    /**
     * Test sdcErase()
     * Strategy:
     *   1. Fill two blocks with non-constant data
     *   2. Write two blocks starting at startblk
     *   3. Erase the second of the two blocks
     *      3.1. First block should be equal to the data written
     *      3.2. Second block should NOT be equal too the data written (i.e. erased).
     *   4. Erase both first and second block
     *      4.1 Both blocks should not be equal to the data initially written
     * Precondition: SDC_BURST_SIZE >= 2
     */
    memset(buf, 0, MMCSD_BLOCK_SIZE * 2);
    memset(buf2, 0, MMCSD_BLOCK_SIZE * 2);
    /* 1. */
    unsigned int i = 0;
    for (; i < MMCSD_BLOCK_SIZE * 2; ++i) {
      buf[i] = (i + 7) % 'T'; //Ensure block 1/2 are not equal
    }
    /* 2. */
    if(sdcWrite(&SDCD1, startblk, buf, 2)) {
      chprintf(chp, "sdcErase() test write failed\r\n");
      goto exittest;
    }
    /* 3. (erase) */
    if(sdcErase(&SDCD1, startblk + 1, startblk + 2)) {
      chprintf(chp, "sdcErase() failed\r\n");
      goto exittest;
    }
    sdcflags_t errflags = sdcGetAndClearErrors(&SDCD1);
    if(errflags) {
      chprintf(chp, "sdcErase() yielded error flags: %d\r\n", errflags);
      goto exittest;
    }
    if(sdcRead(&SDCD1, startblk, buf2, 2)) {
      chprintf(chp, "single-block sdcErase() failed\r\n");
      goto exittest;
    }
    /* 3.1. */
    if(memcmp(buf, buf2, MMCSD_BLOCK_SIZE) != 0) {
      chprintf(chp, "sdcErase() non-erased block compare failed\r\n");
      goto exittest;
    }
    /* 3.2. */
    if(memcmp(buf + MMCSD_BLOCK_SIZE,
              buf2 + MMCSD_BLOCK_SIZE, MMCSD_BLOCK_SIZE) == 0) {
      chprintf(chp, "sdcErase() erased block compare failed\r\n");
      goto exittest;
    }
    /* 4. */
    if(sdcErase(&SDCD1, startblk, startblk + 2)) {
      chprintf(chp, "multi-block sdcErase() failed\r\n");
      goto exittest;
    }
    if(sdcRead(&SDCD1, startblk, buf2, 2)) {
      chprintf(chp, "single-block sdcErase() failed\r\n");
      goto exittest;
    }
    /* 4.1 */
    if(memcmp(buf, buf2, MMCSD_BLOCK_SIZE) == 0) {
      chprintf(chp, "multi-block sdcErase() erased block compare failed\r\n");
      goto exittest;
    }
    if(memcmp(buf + MMCSD_BLOCK_SIZE,
              buf2 + MMCSD_BLOCK_SIZE, MMCSD_BLOCK_SIZE) == 0) {
      chprintf(chp, "multi-block sdcErase() erased block compare failed\r\n");
      goto exittest;
    }
    /* END of sdcErase() test */
  }
  
  /* Card disconnect and command end.*/
exittest:
  sdcDisconnect(&SDCD1);
}
/********************************************************************
Desc: This routine follows all of the blocks in a chain, verifying
		that they are properly linked.  It also verifies each block's
		header.
*********************************************************************/
RCODE F_DbCheck::verifyBlkChain(
	BLOCK_INFO *	pBlkInfo,
	FLMUINT			uiLocale,
	FLMUINT			uiFirstBlkAddr,
	FLMUINT			uiBlkType,
	FLMBOOL *		pbStartOverRV
	)
{
	RCODE					rc = NE_XFLM_OK;
	FLMINT32				i32VerifyCode = 0;
	F_CachedBlock *	pSCache = NULL;
	F_BLK_HDR *			pBlkHdr = NULL;
	FLMUINT				uiPrevBlkAddress;
	FLMUINT				uiBlkCount = 0;
	STATE_INFO			StateInfo;
	FLMBOOL				bStateInitialized = FALSE;
	FLMUINT64			ui64SaveBytesExamined;
	FLMUINT				uiBlockSize = m_pDb->m_pDatabase->getBlockSize();
	FLMUINT				uiMaxBlocks = (FLMUINT)(FSGetSizeInBytes(
										m_pDb->m_pDatabase->getMaxFileSize(),
											m_pDb->m_uiLogicalEOF) /
											(FLMUINT64)uiBlockSize);

	uiPrevBlkAddress = 0;

	/* There must be at least ONE block if it is the LFH chain. */

	if ((uiBlkType == BT_LFH_BLK) && (uiFirstBlkAddr == 0))
	{
		i32VerifyCode = FLM_BAD_LFH_LIST_PTR;
		(void)chkReportError( i32VerifyCode,
									 (FLMUINT32)uiLocale,
									 0,
									 0,
									 0xFF,
									 0,
									 0,
									 0,
									 0);
		goto Exit;
	}

	/* Read through all of the blocks, verifying them as we go. */

Restart_Chain:
	uiBlkCount = 0;
	flmInitReadState( &StateInfo,
							&bStateInitialized,
							(FLMUINT)m_pDb->m_pDatabase->
											m_lastCommittedDbHdr.ui32DbVersion,
							m_pDb,
							NULL,
							(FLMUINT)((uiBlkType == BT_FREE)
											? (FLMUINT)0xFF
											: (FLMUINT)0),
							uiBlkType,
							NULL);
	
	ui64SaveBytesExamined = m_Progress.ui64BytesExamined;
	StateInfo.ui32BlkAddress = (FLMUINT32)uiFirstBlkAddr;

	while ((StateInfo.ui32BlkAddress != 0) && (uiBlkCount < uiMaxBlocks))
	{
		StateInfo.pBlkHdr = NULL;
		if( RC_BAD( rc = blkRead( StateInfo.ui32BlkAddress, &pBlkHdr,
			&pSCache, &i32VerifyCode)))
		{
			if (rc == NE_XFLM_OLD_VIEW)
			{
				FLMUINT	uiSaveDictSeq = m_pDb->m_pDict->getDictSeq();

				if (RC_BAD( rc = getDictInfo()))
					goto Exit;

				// If the dictionary ID changed, start over.

				if (m_pDb->m_pDict->getDictSeq() != uiSaveDictSeq)
				{
					*pbStartOverRV = TRUE;
					goto Exit;
				}

				m_Progress.ui64BytesExamined = ui64SaveBytesExamined;
				goto Restart_Chain;
			}
			pBlkInfo->i32ErrCode = i32VerifyCode;
			pBlkInfo->uiNumErrors++;
			rc = chkReportError( i32VerifyCode,
										(FLMUINT32)uiLocale,
										0,
										0,
										0xFF,
										StateInfo.ui32BlkAddress,
										0,
										0,
										0);
		}
		StateInfo.pBlkHdr = pBlkHdr;
		uiBlkCount++;
		m_Progress.ui64BytesExamined += (FLMUINT64)uiBlockSize;
		if (RC_BAD( rc = chkCallProgFunc()))
		{
			goto Exit;
		}

		f_yieldCPU();

		if ((i32VerifyCode = flmVerifyBlockHeader( &StateInfo,
															  pBlkInfo,
															  uiBlockSize,
															  0xFFFFFFFF,
															  uiPrevBlkAddress,
															  TRUE)) != 0)
		{
			pBlkInfo->i32ErrCode = i32VerifyCode;
			pBlkInfo->uiNumErrors++;
			chkReportError( i32VerifyCode,
								 (FLMUINT32)uiLocale,
								 0,
								 0,
								 0xFF,
								 StateInfo.ui32BlkAddress,
								 0,
								 0,
								 0);
			goto Exit;
		}
		uiPrevBlkAddress = StateInfo.ui32BlkAddress;
		StateInfo.ui32BlkAddress = pBlkHdr->ui32NextBlkInChain;
	}
	if (StateInfo.ui32BlkAddress != 0 && RC_OK( m_LastStatusRc))
	{
		switch (uiBlkType)
		{
			case BT_LFH_BLK:
				i32VerifyCode = FLM_BAD_LFH_LIST_END;
				break;
			case BT_FREE:
				i32VerifyCode = FLM_BAD_AVAIL_LIST_END;
				break;
		}
		pBlkInfo->i32ErrCode = i32VerifyCode;
		pBlkInfo->uiNumErrors++;
		chkReportError( i32VerifyCode,
							 (FLMUINT32)uiLocale,
							 0,
							 0,
							 0xFF,
							 (FLMUINT32)uiPrevBlkAddress,
							 0,
							 0,
							 0);
		goto Exit;
	}

Exit:

	if( pSCache)
	{
		ScaReleaseCache( pSCache, FALSE);
	}
	else if( pBlkHdr)
	{
		f_free( &pBlkHdr);
	}

	if (RC_OK(rc) && (i32VerifyCode != 0))
	{
		rc = RC_SET( NE_XFLM_DATA_ERROR);
	}

	return( rc);
}