/******************************************************************************* MicroSD initialization return: 0x00=success *******************************************************************************/ u8 MSD_Init(void) { u32 i=0; SPI_Config(); MSD_CS_HIGH(); for(i=0; i <10; i++) MSD_WriteByte(DUMMY); //Send dummy byte: 8 Clock pulses of delay return MSD_GoIdleState(); }
/******************************************************************************************************************* ** 函数名称: void SD_HardWareInit() Name: void SD_HardWareInit() ** 功能描述: 初始化访问SD卡的硬件条件 Function: initialize the hardware condiction that access sd card ** 输 入: 无 Input: NULL ** 输 出: 无 Output: NULL ********************************************************************************************************************/ void SD_HardWareInit(void) { SPI_Config(); /* 配置,初始化,SPI接口和SD片选 */ MSD_CS_HIGH(); // SPI_Clk400k(); /* 配置BSPI波特率为400k */ }
void if_spiInit(hwInterface *iface) { euint8 i; //硬件SPI初始化 SPI_Config(); MSD_CS_HIGH(); /* Send 20 spi commands with card not selected */ for (i = 0;i < 21;i++) my_if_spiSend(iface, 0xff); }
euint8 if_spiSend(hwInterface *iface, euint8 outgoing) { euint8 incoming; MSD_CS_LOW(); SPI1->DR = outgoing; /* SPI_I2S_SendData(SPI1, outgoing); */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); incoming = SPI1->DR; /* SPI_I2S_ReceiveData(SPI1); */ MSD_CS_HIGH(); return(incoming); }
/******************************************************************************* * Function Name : MSD_GoIdleState * Description : Put MSD in Idle state. * Input : None * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GoIdleState(void) { /* MSD chip select low */ MSD_CS_LOW(); Delay_us(); /* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */ MSD_SendCmd(MSD_GO_IDLE_STATE, 0, 0x95); /* Wait for In Idle State Response (R1 Format) equal to 0x01 */ if (MSD_GetResponse(MSD_IN_IDLE_STATE)) { /* No Idle State Response: return response failue */ return MSD_RESPONSE_FAILURE; } /*----------Activates the card initialization process-----------*/ do { /* MSD chip select high */ MSD_CS_HIGH(); /* Send Dummy byte 0xFF */ MSD_WriteByte(DUMMY); /* MSD chip select low */ MSD_CS_LOW(); /* Send CMD1 (Activates the card process) until response equal to 0x0 */ MSD_SendCmd(MSD_SEND_OP_COND, 0, 0xFF); /* Wait for no error Response (R1 Format) equal to 0x00 */ } while (MSD_GetResponse(MSD_RESPONSE_NO_ERROR)); /* MSD chip select high */ MSD_CS_HIGH(); /* Send dummy byte 0xFF */ MSD_WriteByte(DUMMY); return MSD_RESPONSE_NO_ERROR; }
void if_spiInit(hwInterface *iface) { euint8 i; SPI_Config(); MSD_CS_HIGH(); /* Send 20 spi commands with card not selected */ for(i=0;i<21;i++) my_if_spiSend(iface,0xff); /* Speed up */ if_spiSetSpeed(SPI_BaudRatePrescaler_2); }
/******************************************************************************* MicroSD Read a Block return: 0x00=success *******************************************************************************/ u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; mutex++; while (mutex > 1); MSD_CS_LOW(); Delay_us(); MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);//send CMD17 if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { for (i = 0; i < NumByteToRead; i++) { *pBuffer = MSD_ReadByte(); pBuffer++; } MSD_ReadByte(); MSD_ReadByte(); //DUMMY CRC bytes rvalue = MSD_RESPONSE_NO_ERROR; } } MSD_CS_HIGH(); MSD_WriteByte(DUMMY); //Send dummy byte: 8 Clock pulses of delay mutex--; return rvalue; }
/******************************************************************************* MicroSD Write a Block return: 0x00=success *******************************************************************************/ u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) { u32 i=0; u8 rvalue = MSD_RESPONSE_FAILURE; mutex++; while (mutex > 1); MSD_CS_LOW(); Delay_us(); MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr, 0xFF);//Send CMD24 if(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)){ MSD_WriteByte(DUMMY); //Send dummy byte: 8 Clock pulses of delay MSD_WriteByte(0xFE); for(i=0; i<NumByteToWrite; i++) { MSD_WriteByte(*pBuffer); pBuffer++; } MSD_ReadByte(); MSD_ReadByte(); //DUMMY CRC bytes if(MSD_GetDataResponse()==MSD_DATA_OK) rvalue=MSD_RESPONSE_NO_ERROR; } MSD_CS_HIGH(); MSD_WriteByte(DUMMY); //Send dummy byte: 8 Clock pulses of delay mutex--; return rvalue; }
/******************************************************************************* * Function Name : MSD_GetStatus * Description : Returns the MSD status. * Input : None * Output : None * Return : The MSD status. *******************************************************************************/ u16 MSD_GetStatus(void) { u16 Status = 0; /* MSD chip select low */ MSD_CS_LOW(); Delay_us(); /* Send CMD13 (MSD_SEND_STATUS) to get MSD status */ MSD_SendCmd(MSD_SEND_STATUS, 0, 0xFF); Status = MSD_ReadByte(); Status |= (u16)(MSD_ReadByte() << 8); /* MSD chip select high */ MSD_CS_HIGH(); /* Send dummy byte 0xFF */ MSD_WriteByte(DUMMY); return Status; }
/******************************************************************************* * Function Name : MSD_ReadBlock * Description : Reads a block of data from the MSD. * Input : - pBuffer : pointer to the buffer that receives the data read * from the MSD. * - ReadAddr : MSD's internal address to read from. * - NumByteToRead : number of bytes to read from the MSD. * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_ReadBlock_DMA(u8 *pBuffer, u32 ReadAddr, u16 NumByteToRead) { u8 rvalue = MSD_RESPONSE_FAILURE; DMA_InitTypeDef DMA_InitStructure; char DuumyClock[512]; // INT8U err; memset(DuumyClock, 0xff, 512); // debug("MSD_ReadBlock_DMA!\r\n"); if(CardInfo.CardType != CARDTYPE_SDV2HC) { ReadAddr = ReadAddr << 9; } /* MSD chip select low */ MSD_CS_LOW(); DMA_DeInit(DMA1_Channel4); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 512; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DuumyClock; //512字节的dummy DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_Low; DMA_Init(DMA1_Channel5, &DMA_InitStructure); /* Enable DMA1 Channel4 Transfer Complete interrupt */ DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); /* Enable DMA1 Channel5 Transfer Complete interrupt */ DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); /* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */ MSD_SendCmd(CMD17, ReadAddr, 0xFF); /* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Now look for the data token to signify the start of the data */ if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { DMA_Cmd(DMA1_Channel5, ENABLE); DMA_Cmd(DMA1_Channel4, ENABLE); #ifdef DMA1_IRQ OSFlagPend(Sem_SD_DMA, (OS_FLAGS)3, OS_FLAG_WAIT_SET_ALL, 0, &err); //请求信号量集的第0和第1位且都置1。 //debug("MSD_ReadBlock_DMA OSFlagPend err=%d \r\n",err); DMA_ClearFlag(DMA1_FLAG_TC4); #else while(!DMA_GetFlagStatus(DMA1_FLAG_TC5)); while(!DMA_GetFlagStatus(DMA1_FLAG_TC4)); DMA_ClearFlag(DMA1_FLAG_TC4); #endif /* Get CRC bytes (not really needed by us, but required by MSD) */ MSD_ReadByte(); MSD_ReadByte(); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } else { //debug("\r\n erro:MSD_START_DATA_SINGLE_BLOCK_READ\r\n"); } } else { //debug("\r\n error:MSD_RESPONSE_NO_ERROR\r\n"); } DMA_Cmd(DMA1_Channel4, DISABLE); DMA_Cmd(DMA1_Channel5, DISABLE); /* MSD chip select high */ MSD_CS_HIGH(); /* Send dummy byte: 8 Clock pulses of delay */ MSD_WriteByte(DUMMY_BYTE); /* Send stop data transmit command - CMD12 */ _send_command(CMD12, 0, 0); /* Returns the reponse */ return rvalue; }
/******************************************************************************************************************* ** 函数名称: void SPI_CS_Deassert() Name: void SPI_CS_Deassert() ** 功能描述: 不片选SPI从机 Function: not select the SPI slave ** 输 入: 无 Input: NULL ** 输 出: 无 Output: NULL ********************************************************************************************************************/ void SPI_CS_Deassert(void) { MSD_CS_HIGH(); /* 不片选SPI从机 not select the SPI slave */ }
/******************************************************************************* * Function Name : MSD_GetCSDRegister * Description : Read the CSD card register. * Reading the contents of the CSD register in SPI mode * is a simple read-block transaction. * Input : - MSD_csd: pointer on an SCD register structure * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; u8 CSD_Tab[16]; /* MSD chip select low */ MSD_CS_LOW(); Delay_us(); /* Send CMD9 (CSD register) or CMD10(CSD register) */ MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF); /* Wait for response in the R1 format (0x00 is no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { for (i = 0; i < 16; i++) { /* Store CSD register value on CSD_Tab */ CSD_Tab[i] = MSD_ReadByte(); } } /* Get CRC bytes (not really needed by us, but required by MSD) */ MSD_WriteByte(DUMMY); MSD_WriteByte(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } /* MSD chip select high */ MSD_CS_HIGH(); /* Send dummy byte: 8 Clock pulses of delay */ MSD_WriteByte(DUMMY); /* Byte 0 */ MSD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; MSD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2; MSD_csd->Reserved1 = CSD_Tab[0] & 0x03; /* Byte 1 */ MSD_csd->TAAC = CSD_Tab[1] ; /* Byte 2 */ MSD_csd->NSAC = CSD_Tab[2]; /* Byte 3 */ MSD_csd->MaxBusClkFrec = CSD_Tab[3]; /* Byte 4 */ MSD_csd->CardComdClasses = CSD_Tab[4] << 4; /* Byte 5 */ MSD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4; MSD_csd->RdBlockLen = CSD_Tab[5] & 0x0F; /* Byte 6 */ MSD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; MSD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; MSD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; MSD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4; MSD_csd->Reserved2 = 0; /* Reserved */ MSD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10; /* Byte 7 */ MSD_csd->DeviceSize |= (CSD_Tab[7]) << 2; /* Byte 8 */ MSD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6; MSD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; MSD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); /* Byte 9 */ MSD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; MSD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; MSD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1; /* Byte 10 */ MSD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7; MSD_csd->EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2; MSD_csd->EraseGrMul = (CSD_Tab[10] & 0x03) << 3; /* Byte 11 */ MSD_csd->EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5; MSD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x1F); /* Byte 12 */ MSD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; MSD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5; MSD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; MSD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2; /* Byte 13 */ MSD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6; MSD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5; MSD_csd->Reserved3 = 0; MSD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01); /* Byte 14 */ MSD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; MSD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6; MSD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; MSD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; MSD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2; MSD_csd->ECC = (CSD_Tab[14] & 0x03); /* Byte 15 */ MSD_csd->CRC = (CSD_Tab[15] & 0xFE) >> 1; MSD_csd->Reserved4 = 1; /* Return the reponse */ return rvalue; }
/******************************************************************************* * Function Name : MSD_GetCIDRegister * Description : Read the CID card register. * Reading the contents of the CID register in SPI mode * is a simple read-block transaction. * Input : - MSD_cid: pointer on an CID register structure * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; u8 CID_Tab[16]; /* MSD chip select low */ MSD_CS_LOW(); Delay_us(); /* Send CMD10 (CID register) */ MSD_SendCmd(MSD_SEND_CID, 0, 0xFF); /* Wait for response in the R1 format (0x00 is no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { /* Store CID register value on CID_Tab */ for (i = 0; i < 16; i++) { CID_Tab[i] = MSD_ReadByte(); } } /* Get CRC bytes (not really needed by us, but required by MSD) */ MSD_WriteByte(DUMMY); MSD_WriteByte(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } /* MSD chip select high */ MSD_CS_HIGH(); /* Send dummy byte: 8 Clock pulses of delay */ MSD_WriteByte(DUMMY); /* Byte 0 */ MSD_cid->ManufacturerID = CID_Tab[0]; /* Byte 1 */ MSD_cid->OEM_AppliID = CID_Tab[1] << 8; /* Byte 2 */ MSD_cid->OEM_AppliID |= CID_Tab[2]; /* Byte 3 */ MSD_cid->ProdName1 = CID_Tab[3] << 24; /* Byte 4 */ MSD_cid->ProdName1 |= CID_Tab[4] << 16; /* Byte 5 */ MSD_cid->ProdName1 |= CID_Tab[5] << 8; /* Byte 6 */ MSD_cid->ProdName1 |= CID_Tab[6]; /* Byte 7 */ MSD_cid->ProdName2 = CID_Tab[7]; /* Byte 8 */ MSD_cid->ProdRev = CID_Tab[8]; /* Byte 9 */ MSD_cid->ProdSN = CID_Tab[9] << 24; /* Byte 10 */ MSD_cid->ProdSN |= CID_Tab[10] << 16; /* Byte 11 */ MSD_cid->ProdSN |= CID_Tab[11] << 8; /* Byte 12 */ MSD_cid->ProdSN |= CID_Tab[12]; /* Byte 13 */ MSD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4; /* Byte 14 */ MSD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8; /* Byte 15 */ MSD_cid->ManufactDate |= CID_Tab[14]; /* Byte 16 */ MSD_cid->CRC = (CID_Tab[15] & 0xFE) >> 1; MSD_cid->Reserved2 = 1; /* Return the reponse */ return rvalue; }