Master_Interface/Core/Src/SD_SPI_Driver.c

311 lines
7.4 KiB
C
Raw Normal View History

2022-07-03 17:33:09 +02:00
/*
* 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;
}