311 lines
7.4 KiB
C
311 lines
7.4 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|