/*---------------------------------------------------------------------------* * Routine: SPI_Transfer *---------------------------------------------------------------------------* * Description: * Attempt to transfer an array of bytes over the SPI channel given. * When complete, the given callback routine is called. * Inputs: * uint8_t channel -- Channel for the RDK peripheral * uint32_t numBytes -- Number of bytes to transfer * const uint8_t *send_buffer -- Pointer to bytes to send * uint8_t *receive_buffer -- Pointer to buffer to receive SPI bytes. * Can be the same location as the send_buffer. * void (*callback)(void) -- Callback function to call when complete. * Outputs: * bool -- true if successfully started, else false (busy). *---------------------------------------------------------------------------*/ bool SPI_Transfer( uint8_t channel, uint32_t numBytes, const uint8_t *send_buffer, uint8_t *receive_buffer, void(*callback)(void)) { if (G_SPI_IsBusy) return false; G_SPI_IsBusy = true; G_SPI_SendBuffer = send_buffer; G_SPI_ReceiveBuffer = receive_buffer; G_SPI_Callback = callback; G_SPI_SendIndex = 0; G_SPI_ReceiveIndex = 0; G_SPI_SendLength = numBytes; G_SPI_Channel = channel; SPI_DisableInterrupts(); SPI_CS_Assert(G_SPI_Channel); /* started by writing data to SDR[7:0] */ SIO10 = G_SPI_SendBuffer[G_SPI_SendIndex++]; G_SPI_SendLength--; SPI_EnableInterrupts(); return true; }
/******************************************************************************************************************** ** 函数名称: U8_T SD_SendCmd() Name: U8_T SD_SendCmd() ** 功能描述: 向卡发送命令,并取得响应 Function: send command to the card,and get a response ** 输 入: U8_T cmd : 命令字 Input: U8_T cmd : command byte U8_T *param : 命令参数,长度为4字节 U8_T *param : command parameter,length is 4 bytes U8_T resptype : 响应类型 U8_T resptype: response type U8_T *resp : 响应,长度为1-5字节 U8_T *resp : response,length is 1-5 bytes ** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code ********************************************************************************************************************/ U8_T SD_SendCmd(U8_T cmd, U8_T *param, U8_T resptype, U8_T *resp) { S8_T i; U8_T tmp,rlen; SPI_CS_Assert(); SPI_SendByte((cmd & 0x3F) | 0x40); /* 发送命令头和命令字 send command header and word */ for (i = 3; i >= 0; i--) SPI_SendByte(param[i]); /* 发送参数 send parameters */ if(cmd == CMD8) SPI_SendByte(CMD8_CRC); else if(cmd == CMD0) SPI_SendByte(0x95); /* CRC校验码,只用于第1个命令 CRC,only used for the first command */ else SPI_SendByte(0x00); rlen = 0; switch (resptype) /* 根据不同的命令,得到不同的响应长度 */ { /* according various command,get the various response length */ case R1: case R1B: rlen = 1; break; case R2: rlen = 2; break; case R3: case R7: rlen = 5; break; default: SPI_SendByte(0xFF); SPI_CS_Deassert(); return SD_ERR_CMD_RESPTYPE; /* 返回命令响应类型错误 return error of command response type */ break; } i = 0; do /* 等待响应,响应的开始位为0 */ { /* Wait for a response,a response is a start bit(zero) */ tmp = SPI_RecByte(); i++; }while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT)); if (i >= SD_CMD_TIMEOUT) { SPI_CS_Deassert(); return SD_ERR_CMD_TIMEOUT; /* 返回命令超时 return response timeout of command */ } for (i = rlen - 1; i >= 0; i--) { resp[i] = tmp; tmp = SPI_RecByte(); /* 循环的最后发送8clock at the last recycle,clock out 8 clock */ } SPI_CS_Deassert(); return SD_NO_ERR; /* 返回执行成功 return perform sucessfully */ }
DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { DRESULT res; if (pdrv) { return RES_PARERR; } //FATFS目前版本仅需处理CTRL_SYNC,GET_SECTOR_COUNT,GET_BLOCK_SIZ三个命令 switch(cmd) { case CTRL_SYNC: SPI_CS_Assert(); if(SD_ResetSD() == SD_NO_ERR) { res = RES_OK; } else { res = RES_ERROR; } SPI_CS_Deassert(); break; case GET_BLOCK_SIZE: *(WORD*)buff = 512; res = RES_OK; break; case GET_SECTOR_COUNT: *(DWORD*)buff = SD_GetCardInfo(); res = RES_OK; break; default: res = RES_PARERR; break; } return res; }
__interrupt static void SPI_ISRHandler(void) { uint8_t err_type; err_type = (uint8_t)(SSR13 & _SAU_OVERRUN_ERROR); SIR13 = (uint16_t)err_type; SPI_CS_Clear(G_SPI_Channel); if (1U == err_type) { /* overrun error occurs */ G_SPI_OverrunErrorCount++; } else { /* Receive a character */ G_SPI_ReceiveBuffer[G_SPI_ReceiveIndex++] = SIO31; /* Is there more data to send? */ if (G_SPI_SendLength > 0) { /* Send the next character */ SPI_CS_Assert(G_SPI_Channel); SIO31 = G_SPI_SendBuffer[G_SPI_SendIndex++]; G_SPI_SendLength--; } else { /* Data transfer complete */ SPI_CS_Clear(G_SPI_Channel); if (G_SPI_Callback) G_SPI_Callback(); G_SPI_IsBusy = false; } } }