/* * SD_SPI_Driver.c * * Created on: 20.06.2022 * Author: max */ #include "SD_SPI_Driver.h" #define SPI_TIMEOUT 1000 // TODO: Why is this defined twice? extern SPI_HandleTypeDef* sdspi; void SD_SPI_Driver_Init(SPI_HandleTypeDef* hspi) { sdspi = hspi; } uint8_t SPI_SD_Init(BYTE pdrv) { uint8_t resbuf[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; SD_Power_Up_Seq(); HAL_Delay(10); SD_setIdleState(); SD_send_if_condition(resbuf); SD_read_OCR(resbuf); uint8_t result = 0xFF; while (result != 0x00) { SD_sendAppCMD(); result = SD_sendOpCond(); } SD_read_OCR(resbuf); } uint8_t SPI_SD_Status(BYTE pdrv) {} uint8_t SPI_SD_Write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {} uint8_t SPI_SD_Read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {} uint8_t SD_Blockread(uint8_t* buff, uint32_t sector) { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = CMD17; cmd.arg1 = (uint8_t)(sector >> 24) & 0xFF; cmd.arg2 = (uint8_t)(sector >> 16) & 0xFF; cmd.arg3 = (uint8_t)(sector >> 8) & 0xFF; cmd.arg4 = (uint8_t)sector & 0xFF; cmd.crc = 0x00; SD_SPI_Send_Command(cmd); uint8_t sdstatus = SD_PollForResponseR1(); uint8_t resp = 0xFF; while (resp != 0xFE) { HAL_SPI_Receive(sdspi, &resp, 1, SPI_TIMEOUT); } HAL_SPI_Receive(sdspi, buff, BLOCKSIZE, 200); uint8_t crc[2]; // HAL_SPI_Receive(sdspi, crc, 2, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); } uint8_t SD_Blockwrite(uint8_t* buf, uint32_t sector) { uint8_t dummybuffer = 0xFF; uint8_t starttoken = 0xFE; uint8_t crc[2] = {0}; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = CMD24; cmd.arg1 = (uint8_t)(sector >> 24) & 0xFF; cmd.arg2 = (uint8_t)(sector >> 16) & 0xFF; cmd.arg3 = (uint8_t)(sector >> 8) & 0xFF; cmd.arg4 = (uint8_t)sector & 0xFF; cmd.crc = 0x00; SD_SPI_Send_Command(cmd); uint8_t sdstatus = SD_PollForResponseR1(); HAL_SPI_Transmit(sdspi, &starttoken, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, buf, BLOCKSIZE, SPI_TIMEOUT); // HAL_SPI_Transmit(sdspi, crc,2,SPI_TIMEOUT); uint8_t responsetoken = 0xFF; for (int i = 0; i < 128; i++) { HAL_SPI_Receive(sdspi, &responsetoken, 1, SPI_TIMEOUT); if (responsetoken != 0xFF) { break; } } HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); } uint8_t SD_setIdleState() { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = 0x40; cmd.arg1 = 0; cmd.arg2 = 0; cmd.arg3 = 0; cmd.arg4 = 0; cmd.crc = 0x94 | 0x01; SD_SPI_Send_Command(cmd); uint8_t sdstatus = SD_PollForResponseR1(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); return sdstatus; } void SD_Power_Up_Seq() { SD_CS_High(); uint8_t dummybuf[10] = {0xFF}; for (int i = 0; i < 10; i++) { dummybuf[i] = 0xFF; } HAL_SPI_Transmit(sdspi, dummybuf, 10, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, dummybuf, 1, SPI_TIMEOUT); } void SD_CS_Low() { HAL_GPIO_WritePin(SD_Select_GPIO_Port, SD_Select_Pin, GPIO_PIN_RESET); } void SD_CS_High() { HAL_GPIO_WritePin(SD_Select_GPIO_Port, SD_Select_Pin, GPIO_PIN_SET); } HAL_StatusTypeDef SD_SPI_Send_Command(SD_Command cmd) { uint8_t sdspirxbuf[6] = {0}; uint8_t sdspitxbuf[6] = {0}; sdspitxbuf[0] = cmd.command; sdspitxbuf[1] = cmd.arg1; sdspitxbuf[2] = cmd.arg2; sdspitxbuf[3] = cmd.arg3; sdspitxbuf[4] = cmd.arg4; sdspitxbuf[5] = cmd.crc; return HAL_SPI_TransmitReceive(sdspi, sdspitxbuf, sdspirxbuf, 6, SPI_TIMEOUT); } uint8_t SD_PollForResponseR1() { /* uint8_t rxbuf[8] = {0}; uint8_t txbuf[8]; for(int i = 0;i<8;i++) { txbuf[i] = 0xFF; } HAL_SPI_TransmitReceive(sdspi, txbuf ,rxbuf, 8, SPI_TIMEOUT); for(uint8_t i = 0; i<8;i++) { if((rxbuf[i] & 0x80) == 0x00) { return rxbuf[i]; } }*/ uint8_t res = 0xFF; uint8_t dummytx = 0xFF; for (int i = 0; i < 8; i++) { HAL_Delay(1); HAL_SPI_TransmitReceive(sdspi, &dummytx, &res, 1, SPI_TIMEOUT); if ((res & 0x80) == 0) { return res; } } return 0; } uint8_t SD_PollForResponseR7(uint8_t* resultbuf) { uint8_t rxbuf; for (uint8_t i = 0; i < 8; i++) { HAL_SPI_Receive(sdspi, &rxbuf, 1, SPI_TIMEOUT); if (rxbuf != 0xFF) { resultbuf[0] = rxbuf; HAL_SPI_Receive(sdspi, &resultbuf[1], 4, SPI_TIMEOUT); return 0; } } return 1; } void SD_send_if_condition(uint8_t* resbuf) { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = CMD8; cmd.arg1 = 0; cmd.arg2 = 0; cmd.arg3 = 0x01; cmd.arg4 = 0xAA; cmd.crc = CMD8_CRC; SD_SPI_Send_Command(cmd); if (!SD_PollForResponseR7(resbuf)) { } HAL_SPI_Transmit(sdspi, &dummybuffer, 10, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); } void SD_read_OCR(uint8_t* resbuf) { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = CMD58; cmd.arg1 = 0; cmd.arg2 = 0; cmd.arg3 = 0x00; cmd.arg4 = 0x00; cmd.crc = 0x00; SD_SPI_Send_Command(cmd); if (!SD_PollForResponseR7(resbuf)) { } HAL_SPI_Transmit(sdspi, &dummybuffer, 10, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); } uint8_t SD_sendAppCMD() { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = CMD55; cmd.arg1 = 0; cmd.arg2 = 0; cmd.arg3 = 0; cmd.arg4 = 0; cmd.crc = 0x00; SD_SPI_Send_Command(cmd); uint8_t sdstatus = SD_PollForResponseR1(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); return sdstatus; } uint8_t SD_sendOpCond() { uint8_t dummybuffer = 0xFF; HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_Low(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_Command cmd; cmd.command = ACMD41; cmd.arg1 = 0x40; cmd.arg2 = 0; cmd.arg3 = 0; cmd.arg4 = 0; cmd.crc = 0x00; SD_SPI_Send_Command(cmd); uint8_t sdstatus = SD_PollForResponseR1(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); SD_CS_High(); HAL_SPI_Transmit(sdspi, &dummybuffer, 1, SPI_TIMEOUT); return sdstatus; }