#include "define.h"
extern unsigned int __Vectors;
unsigned int crc16(unsigned char* dat, unsigned int cnt);
unsigned int crc7(unsigned char* dat, unsigned int cnt);
struct sd_info {
unsigned char csd_version;
unsigned int ccs;
unsigned int unit;
unsigned int multi;
unsigned long long size;
unsigned int block;
unsigned char pattern;
unsigned long long page;
unsigned char man_id;
unsigned char prd_name[5];
unsigned char prd_sn[4];
union {
unsigned char r7[4];
unsigned char r3[4];
} rx;
};
struct sd_command_s {
unsigned char cmd;
unsigned char parm[4];
unsigned char crc;
};
void sd_cs(int high) {
if (high) {
gpiod->bsrr = 0x800;
} else {
gpiod->brr = 0x800;
}
}
void init_spi(void) {
// unsigned short int* spi1_i2scfgr = (unsigned short int*)(spi1 + 0x1C);
rcc->apb2enr &= ~0x0035; // disable GPIOD GPIOA GPIOC AFIO
rcc->apb1enr &= ~0x8000; // disable SPI3
rcc->apb1rstr |= 0x8000; //reset SPI3
rcc->apb1rstr &= ~0x8000; //restore SPI3
rcc->apb2enr |= 0x0035; //GPIOD GPIOA GPIOC AFIO
rcc->apb1enr |= 0x8000; //SPI3
rcc->ahbenr |= 0x02; //enable dma2
gpiod->crh &= ~(0x0000F000); //SD_CS PD11
gpiod->crh |= 0x00003000; //PD11 output PP 50M
sd_cs(1);
afio->mapr |= 0x10000000; //SPI3 remap
gpioc->crh &= ~0x000FFF00; //reset GPIOC 10 11 12
gpioc->crh |= 0x00000B00; //PC10 SPI3_SCK Alt Push-pull output 50M
gpioc->crh |= 0x0000B000; //PC11 SPI3_MISO Alt Push-pull output 50M
gpioc->crh |= 0x000B0000; //PC12 SPI3_MOSI Alt Push-pull output 50M
spi3->cr1 = 0x0304; // 8bit(11b) MSB(7b) Baud-rate/2(5-3b) master(2b) CPOH 2nd-edge(1b)
// spi3->cr1 = 0x033C; // 8bit(11b) MSB(7b) Baud-rate/256(5-3b) master(2b) CPOH 2nd-edge(1b)
spi3->cr2 = 0x0;
spi3->cr2 = 0x3; // enable spi3 dma
// spi3->i2scfgr &= ~(0x0800); //disable i2s
spi3->cr1 |= 0x40; //enable spi1
}
void stop_spi(void) {
spi3->cr2 &= ~0x03; // disable spi3 dma
spi3->cr1 &= ~0x40; // disable spi3
rcc->ahbenr &= ~0x02; // disable spi3 dma rcc
rcc->apb1enr &= 0x8000; // disable spi3 rcc
}
void init_nvic(void) {
nvic->icer.at[1] = 0x01000000; //disable IRQ56
nvic->icpr.at[1] = 0x01000000; //clear pending
nvic->iser.at[1] = 0x01000000; //enable IRQ56
scb->vtor = (unsigned int)(&__Vectors) & 0x3FFFFF80;
}
void stop_nvic(void) {
nvic->icpr.at[1] = 0x01000000; //clear pending
nvic->icer.at[1] = 0x01000000; //disable IRQ56
}
unsigned char sd_bytedata(unsigned char cmd) {
unsigned char output;
while (((spi3->sr)&0x2)==0) {} //TXE empty
spi3->dr = cmd;
while (((spi3->sr)&0x1)==0) {} //RXNE empty
output = (unsigned char)(spi3->dr);
return output;
}
void sd_init() {
int ii;
sd_cs(1);
//sending dummy data few times
for (ii=0; ii<0xF; ii++) {
sd_bytedata(0xFF);
}
}
unsigned int dma_inv_state;
unsigned char* common_dat;
unsigned char common_buf1[514];
unsigned char common_buf2[514];
unsigned int common_cnt;
unsigned char common_response;
unsigned char common_dummy = 0xFF;
struct sd_command_s common_cmd;
#define SD_DMA_DAT_ONCE 0x1
#define SD_DMA_RESPONSE 0x2
#define SD_DMA_DATATOKEN 0x4
#define SD_DMA_READDATA 0x10
#define SD_DMA_WRITEDATA 0x20
#define SD_DMA_COMPLETE 0x100
void sd_start_dma_read(unsigned char* cmd, unsigned char* rtn, unsigned int cnt) {
// rcc->ahbenr |= 0x02; //enable dma2
// spi3->cr2 = 0x3; // enable spi3 dma
dma2->ch1.ccr &= ~0x01; //disable chnnel1
dma2->ch1.ccr = 0x0080; //MINC:yes P->M
if (dma_inv_state) {
dma2->ch1.ccr |= 0x2; // interrupt setup
}
dma2->ch1.cndtr = cnt;
dma2->ch1.cpar = (unsigned int)&(spi3->dr);
dma2->ch1.cmar = (unsigned int)rtn;
dma2->ch2.ccr &= ~0x01; //disable channel2
dma2->ch2.ccr = 0x0010; //MINC:no M->P
dma2->ch2.cndtr = cnt;
dma2->ch2.cpar = (unsigned int)&(spi3->dr);
dma2->ch2.cmar = (unsigned int)cmd;
dma2->ifcr = 0xFF; //clear event
dma2->ch1.ccr |= 0x01; //enable channel1
dma2->ch2.ccr |= 0x01; //enable channel2
}
void sd_start_dma_write(unsigned char* cmd, unsigned char* rtn, unsigned int cnt) {
// rcc->ahbenr |= 0x02; //enable dma2
// spi3->cr2 = 0x3; // enable spi3 dma
dma2->ch1.ccr &= ~0x01; //disable chnnel1
dma2->ch1.ccr = 0x0000; //MINC:no P->M
if (dma_inv_state) {
dma2->ch1.ccr |= 0x2; // interrupt setup
}
dma2->ch1.cndtr = cnt;
dma2->ch1.cpar = (unsigned int)&(spi3->dr);
dma2->ch1.cmar = (unsigned int)rtn;
dma2->ch2.ccr &= ~0x01; //disable channel2
dma2->ch2.ccr |= 0x0090; //MINC:yes M->P
dma2->ch2.cndtr = cnt;
dma2->ch2.cpar = (unsigned int)&(spi3->dr);
dma2->ch2.cmar = (unsigned int)cmd;
dma2->ifcr = 0xFF; //clear event
dma2->ch1.ccr |= 0x01; //enable channel1
dma2->ch2.ccr |= 0x01; //enable channel2
}
void sd_stop_dma(void) {
dma2->ifcr = 0xFF; //clear event
dma2->ch1.ccr &= ~0x01; //disable channel and interrupt
dma2->ch2.ccr &= ~0x01; //disable channel
// spi3->cr2 &= ~0x03; // disable spi3 dma
// rcc->ahbenr &= ~0x02; //disable dms2
}
void sd_command_dir(struct sd_command_s* cmd) {
cmd->cmd |= 0x40;
cmd->crc = crc7((unsigned char*)cmd, 5);
cmd->crc <<= 1;
cmd->crc |= 1;
sd_bytedata(cmd->cmd);
sd_bytedata(cmd->parm[0]);
sd_bytedata(cmd->parm[1]);
sd_bytedata(cmd->parm[2]);
sd_bytedata(cmd->parm[3]);
sd_bytedata(cmd->crc);
}
void sd_command_dma(struct sd_command_s* cmd) {
unsigned char rr[1];
// struct spi_s* spi3_i = spi3; // for debug
// struct rcc_s* rcc_i = rcc; // for debug
// struct dma_s* dma2_i = dma2; // for debug
cmd->cmd |= 0x40;
cmd->crc = crc7((unsigned char*)cmd, 5);
cmd->crc <<= 1;
cmd->crc |= 1;
sd_start_dma_write((unsigned char*)cmd, rr, 6);
while ((dma2->isr & 0x20) == 0); //check finish event
while ((dma2->isr & 0x02) == 0); //check finish event
sd_stop_dma();
}
void sd_command_dma_inv(struct sd_command_s* cmd) {
unsigned char rr[1];
// struct spi_s* spi3_i = spi3; // for debug
// struct rcc_s* rcc_i = rcc; // for debug
// struct dma_s* dma2_i = dma2; // for debug
cmd->cmd |= 0x40;
cmd->crc = crc7((unsigned char*)cmd, 5);
cmd->crc <<= 1;
cmd->crc |= 1;
dma_inv_state = SD_DMA_DAT_ONCE;
sd_start_dma_write((unsigned char*)cmd, rr, 6);
while (dma_inv_state & SD_DMA_DAT_ONCE);
}
void sd_command_dma_inv_sss() {
// struct spi_s* spi3_i = spi3; // for debug
// struct rcc_s* rcc_i = rcc; // for debug
// struct dma_s* dma2_i = dma2; // for debug
common_cmd.cmd |= 0x40;
common_cmd.crc = crc7((unsigned char*)&common_cmd, 5);
common_cmd.crc <<= 1;
common_cmd.crc |= 1;
sd_start_dma_write((unsigned char*)&common_cmd, &common_response, 6);
}
void sd_command(struct sd_command_s* cmd) {
sd_command_dma_inv(cmd);
//sd_command_dma(cmd);
//sd_command_dir(cmd);
}
void spi3_hdr_complete(void) {
unsigned char* rr;
if (dma_inv_state & SD_DMA_DAT_ONCE) {
dma_inv_state &= ~SD_DMA_DAT_ONCE;
} else if (dma_inv_state & SD_DMA_RESPONSE) {
rr = (unsigned char*)dma2->ch1.cmar;
if (((*rr)&0x80)==0) {
dma_inv_state &= ~SD_DMA_RESPONSE;
}
} else if (dma_inv_state & SD_DMA_DATATOKEN) {
rr = (unsigned char*)dma2->ch1.cmar;
if (*rr==0xFE) {
dma_inv_state &= ~SD_DMA_DATATOKEN;
}
} else if (dma_inv_state & SD_DMA_READDATA) {
dma_inv_state &= ~SD_DMA_READDATA;
}
}
void spi3_hdr_nextproc(void) {
unsigned char* rr;
unsigned char* dm;
if (dma_inv_state & SD_DMA_RESPONSE) {
rr = (unsigned char*)dma2->ch1.cmar;
dm = &common_dummy;
sd_start_dma_read(dm, rr, 1);
} else if (dma_inv_state & SD_DMA_DATATOKEN) {
rr = (unsigned char*)dma2->ch1.cmar;
dm = &common_dummy;
sd_start_dma_read(dm, rr, 1);
} else if (dma_inv_state & SD_DMA_READDATA) {
rr = (unsigned char*)common_dat;
dm = &common_dummy;
sd_start_dma_read(dm, rr, common_cnt);
} else if (dma_inv_state & SD_DMA_COMPLETE) {
sd_cs(1);
sd_bytedata(0xFF);
dma_inv_state &= ~SD_DMA_COMPLETE;
}
}
void DMA2_Ch1_
评论3
最新资源