реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> microSD SDIO, Помогите начать
MiklPolikov
сообщение Oct 30 2014, 17:11
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Коллеги, добрый день.

Пытаюсь подключить microSD карту к интерфейсу SDIO STM32L151RDT
Возникла проблема с чтением.

Инициализация проходит.
На CMD2 , CMD3 карта отвечает.
Посылаю CMD7, получаю ответ с верным CRC
Посылаю CMD17 , получаю ответ с верным CRC
Перевожу SDIO в режим чтения. Он выдаёт ~40 клоков , после чего выставляет бит ошибки "не получен старт бит" .

Вопрос 1: правильно ли я понимаю, что "старт бит" должен быть выдан картой одновременной по всем линиям D0-D3 ?

Вопрос 2: Вижу по осциллографу, что на линии D0 во время пачки клоков что-то есть, на остальных высокий уровень(они все подтянуты к питанию) .
Можно ли предположить, что карта в SPI режиме ?

Вопрос 3 : Если карта на самом деле в SPI режиме, то как она должна попасть в SDIO режим ? Если это происходит путём подачи CMD0 в то время как линия DAT3/CS в высоком уровне, то это условие у меня выполняется, т.к. линии D0-D3 подтянуты к питанию.

Вопрос 4 : Правильно ли я понимаю алгоритм чтения в режиме SDIO ? Проинициализировались - > CMD7 c верным RCA -> CMD17 с одресом -> и карта начинает выдавать данные.
Не совсем понятно, надо ли в ответах на CMD7 CMD17 проверять ещё что-то, помимо того что они просто получены ? "карта начинает выдавать данные" - в ответ на клоки SDIO контроллера ? И перед данными выдаёт старт-бит ?

Заранее спасибо !


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Oct 30 2014, 18:36
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



И ещё, ни как не могу понять, что именно делает CMD7 . В документации написано "SELECT / DESELECT CARD". Ну а как понять, выбрана оказалась карта после очередной CMD7 , или наоборот ? Отпарвляю CMD7 , получаю ответ. Все последующие отправки-ответа нет.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 1 2014, 17:34
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Разобрался. Выкладываю свой максимально простой код. Надеюсь что кому-нибудь поможет. Кое-где есть функции операционной системы, ожидающие прерывания от выставления флагов в регистре состояния SDIO. Их легко заменить простой проверка этого регистра в бесконечном цикле, прерывание при этом надо отключить.

Ноги процессора настраиваются так. Принципиально, что на всех подтяжка к +

////////////////////
void SD_INTERFACE_INIT(void)
{
//включаем тактирование порта
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
RCC->AHBLPENR|=RCC_AHBLPENR_GPIOCLPEN;

RCC->AHBENR |= RCC_AHBENR_GPIODEN;
RCC->AHBLPENR|=RCC_AHBLPENR_GPIODLPEN;

__dsb(15);

//скорость порта максимальная
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8|GPIO_OSPEEDER_OSPEEDR9|GPIO_OSPEEDER_OSPEEDR10|GPIO_OSPEE
DER_OSPEEDR11| GPIO_OSPEEDER_OSPEEDR12;
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2;

//SD1 SDIO
GPIOC->MODER &= ~GPIO_MODER_MODER8;
GPIOC->MODER |= GPIO_MODER_MODER8_1;
GPIOC->MODER &= ~GPIO_MODER_MODER9;
GPIOC->MODER |= GPIO_MODER_MODER9_1;
GPIOC->MODER &= ~GPIO_MODER_MODER10;
GPIOC->MODER |= GPIO_MODER_MODER10_1;
GPIOC->MODER &= ~GPIO_MODER_MODER11;
GPIOC->MODER |= GPIO_MODER_MODER11_1;
GPIOC->MODER &= ~GPIO_MODER_MODER12;
GPIOC->MODER |= GPIO_MODER_MODER12_1;

GPIOD->MODER &= ~GPIO_MODER_MODER2;
GPIOD->MODER |= GPIO_MODER_MODER2_1;

GPIOC->PUPDR &=~ GPIO_PUPDR_PUPDR8;
GPIOC->PUPDR |= GPIO_PUPDR_PUPDR8_0;
GPIOC->PUPDR &=~ GPIO_PUPDR_PUPDR9;
GPIOC->PUPDR |= GPIO_PUPDR_PUPDR9_0;
GPIOC->PUPDR &=~ GPIO_PUPDR_PUPDR10;
GPIOC->PUPDR |= GPIO_PUPDR_PUPDR10_0;
GPIOC->PUPDR &=~ GPIO_PUPDR_PUPDR11;
GPIOC->PUPDR |= GPIO_PUPDR_PUPDR11_0;
GPIOC->PUPDR &=~ GPIO_PUPDR_PUPDR12;
GPIOC->PUPDR |= GPIO_PUPDR_PUPDR12_0;

GPIOD->PUPDR &=~ GPIO_PUPDR_PUPDR2;
GPIOD->PUPDR |= GPIO_PUPDR_PUPDR2_0;

GPIOC->AFR[1]|=(12<<0);
GPIOC->AFR[1]|=(12<<4);
GPIOC->AFR[1]|=(12<<8);
GPIOC->AFR[1]|=(12<<12);
GPIOC->AFR[1]|=(12<<16);

GPIOD->AFR[0]|=(12<<8);
}

SDIO настраивается так. Включены прерывания по всем важным флагам по итогам передачи команды и данных.
PLL настроен так, что частота процессора 32МГц, промежуточная частота PLL, от которой тактируется SDIO, 48МГц


//////////////////////////настраиваем SDIO для SD ///////////////////////////////////////////////////////
void SD_SDIO_INIT(void)
{
RCC->APB2ENR|=RCC_APB2ENR_SDIOEN; // включаем тактирование
RCC->APB2LPENR|=RCC_APB2LPENR_SDIOLPEN;

RCC->APB2RSTR|=RCC_APB2RSTR_SDIORST;
RCC->APB2RSTR&=~RCC_APB2RSTR_SDIORST; //сброс настроек

SDIO->CLKCR|=SDIO_CLKCR_HWFC_EN; //HW Flow Control is enabled
SDIO->CLKCR|=SDIO_CLKCR_WIDBUS_0; // 4-wide bus mode: SDIO_D[3:0] used ++
SDIO->CLKCR|=SDIO_CLKCR_PWRSAV; //SDIO_CK is only enabled when the bus is active
SDIO->CLKCR|=SDIO_CLKCR_CLKEN; //SDIO_CK is enabled ++


SDIO->DCTRL|=SDIO_DCTRL_SDIOEN;
SDIO->DCTRL|=SDIO_DCTRL_RWMOD; //Read Wait control using SDIO_CK ///Непонятно, что это
SDIO->DCTRL|=SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DBLOCKSIZE_3; // размер блока 512 ++
SDIO->DCTRL|=SDIO_DCTRL_DMAEN; //DMA enabled. ++

///////включаем прерывания
SDIO->MASK|=SDIO_MASK_STBITERRIE;
SDIO->MASK|=SDIO_MASK_DATAENDIE;
SDIO->MASK|=SDIO_MASK_CMDRENDIE;
SDIO->MASK|=SDIO_MASK_DTIMEOUTIE;
SDIO->MASK|=SDIO_MASK_CTIMEOUTIE;
SDIO->MASK|=SDIO_MASK_DCRCFAILIE;
SDIO->MASK|=SDIO_MASK_CCRCFAILIE;
SDIO->MASK|=SDIO_MASK_CMDSENTIE;

NVIC_SetPriority(SDIO_IRQn, 11);
NVIC_EnableIRQ(SDIO_IRQn);

SDIO->POWER|=SDIO_POWER_PWRCTRL ; //Включаем SDIO

}

функция передачи CMD команды. После начала передачи функция ждёт прерывания от выставления флагов в SDIO STA . У меня операционка, но её можно выкинуть, заменив просто поллингом регистра STA, или передачей флага из прерывания через глобальную переменную.

////////////////////////////////////////
__inline char SEND_CMD(char sd_n, unsigned char cmd, unsigned long int argument, unsigned char response_type, unsigned int* ansver )
{
unsigned int SDIO_CMD_MASK;
EventBits_t SDIO_STA_MASK;

//Clear the Command Flags
SDIO->ICR=0xFFFFFFFF; //(SDIO_STA_CCRCFAIL | SDIO_STA_CTIMEOUT | SDIO_STA_CMDREND | SDIO_STA_CMDSENT);
SDIO->ARG=argument; //First adjust the argument (because I will immediately enable CPSM next)
SDIO_CMD_MASK=cmd; //The last argument is to enable CSPM
SDIO_CMD_MASK |=SDIO_CMD_CPSMEN; //The last argument is to enable CSPM
switch(response_type){
case RESPONSE_0_BIT :
SDIO_CMD_MASK &=~SDIO_CMD_WAITRESP_0;
SDIO_CMD_MASK &=~SDIO_CMD_WAITRESP_1;
break;
case RESPONSE_48_BIT :
SDIO_CMD_MASK |=SDIO_CMD_WAITRESP_0;
SDIO_CMD_MASK &=~SDIO_CMD_WAITRESP_1;
break;
case RESPONSE_136_BIT :
SDIO_CMD_MASK |=SDIO_CMD_WAITRESP_0;
SDIO_CMD_MASK |=SDIO_CMD_WAITRESP_1;
default :
SDIO_CMD_MASK |=SDIO_CMD_WAITRESP_0;
SDIO_CMD_MASK |=SDIO_CMD_WAITRESP_1;
}

xEventGroupClearBits(x_SDIO_Transmit_EventGroup,0xFFFFFFF);
SDIO->CMD=SDIO_CMD_MASK; //запускаем передачу команды

if (response_type==RESPONSE_0_BIT)
{
SDIO_STA_MASK=xEventGroupWaitBits(x_SDIO_Transmit_EventGroup, SDIO_STA_CMDSENT | SDIO_STA_CTIMEOUT, pdTRUE, pdFALSE, 5);
if(SDIO_STA_MASK & SDIO_STA_CTIMEOUT)
return SD_ERROR;
return SD_OK;
}
else //SHRESP or LNRESP or R3RESP
{
SDIO_STA_MASK=xEventGroupWaitBits(x_SDIO_Transmit_EventGroup, SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL, pdTRUE, pdFALSE, 5);

if(SDIO_STA_MASK & SDIO_STA_CTIMEOUT)
return SD_ERROR;
if(SDIO_STA_MASK& SDIO_STA_CCRCFAIL)
{
if(cmd==CMD41)
{
ansver[0]=SDIO->RESP1;
ansver[1]=SDIO->RESP2;
return SD_OK;
}
else
return SD_ERROR;
}
if(SDIO_STA_MASK & SDIO_STA_CMDREND)
{
ansver[0]=SDIO->RESP1;
ansver[1]=SDIO->RESP2;
if(response_type==RESPONSE_136_BIT)
{
ansver[2]=SDIO->RESP3;
ansver[3]=SDIO->RESP4;
}
return SD_OK;
}
}
return SD_ERROR;
}


Функция настройки DMA для передачи SDIO <> буфер памяти
///////////////////////////////////////////////////////////////////////////////////
void SD_DMA_INIT(void)
{
RCC->AHBENR|=RCC_AHBENR_DMA2EN; //включили тактирование DMA
RCC->AHBLPENR|=RCC_AHBLPENR_DMA2LPEN;

RCC->AHBRSTR&=~RCC_AHBRSTR_DMA2RST;//перестаём сбрасывать настройки DMA

//передача и приём
DMA2_Channel4->CCR&=~DMA_CCR4_EN;// выключили канал
DMA2_Channel4->CCR|=DMA_CCR4_TCIE;// прерывание при конце передачи
DMA2_Channel4->CCR|=DMA_CCR4_MSIZE_1; //размер памяти 32
DMA2_Channel4->CCR|=DMA_CCR4_PSIZE_1; //размер периферии 32
}
}

Функции запуска DMA для чтения и для записи
///////////////////////////////запускаем чтение SD по DMA /////////////////////////////////
void SD_DMA_START_READ(char sd_n, unsigned char *p_buf_r, int data_size)
{
// "периферия" -откуда берутся данные
// "память" -куда идёт данные
if(sd_n==SD1)
{
DMA2_Channel4->CCR&=~DMA_CCR4_EN; // канал приёма и передачи

DMA2_Channel4->CNDTR=data_size/4; //т.к. data_size в байтах, а размер регистра 32 байта
DMA2_Channel4->CMAR=(uint32_t)p_buf_r; // сюда идут данные
DMA2_Channel4->CPAR=(uint32_t)(&SDIO->FIFO); // отсюда идут данные
DMA2_Channel4->CCR|=DMA_CCR4_MINC;
DMA2_Channel4->CCR &=~ DMA_CCR4_PINC;


DMA2_Channel4->CCR|=DMA_CCR4_EN;

}

}

///////////////////////////////запускаем запись в SD по DMA /////////////////////////////////
void SD_DMA_START_WRITE(char sd_n, unsigned char *p_buf_w, int data_size)
{
// "периферия" -откуда берутся данные
// "память" -куда идёт данные

DMA2_Channel4->CCR&=~DMA_CCR4_EN; // канал приёма и передачи

DMA2_Channel4->CNDTR=data_size/4; //т.к. data_size в байтах, а размер регистра 32 байта
DMA2_Channel4->CPAR=(uint32_t)p_buf_w; // сюда идут данные
DMA2_Channel4->CMAR=(uint32_t)(&SDIO->FIFO); // отсюда идут данные
DMA2_Channel4->CCR|=DMA_CCR4_PINC;
DMA2_Channel4->CCR&=~DMA_CCR4_MINC;

DMA2_Channel4->CCR|=DMA_CCR4_EN;
}

Инициализация карты. Работает только на картах больше 2Гб. См. комментарии.
///// Как это работает написано в документе Part_1_Physical_Layer_Simplified_Specification_Ver3.01_Final_100518-1.pdf страница 115
char SD_initialize (char sd_n)
{
unsigned int cmd_ansver[4];
char result;
unsigned long int time;
unsigned int C_SIZE;

time=xTaskGetTickCount()+(2000/portTICK_RATE_MS);

SD_SCK_DIV_60(sd_n)

SEND_CMD(sd_n, CMD0,0,RESPONSE_0_BIT,&cmd_ansver[0]);
SEND_CMD(sd_n, CMD0,0,RESPONSE_0_BIT,&cmd_ansver[0]); //почему то c одним CMD0 не работает
result=SEND_CMD(sd_n, CMD8,0x1AA,RESPONSE_48_BIT,&cmd_ansver[0]);
if(result==SD_OK) //карта ответила на CMD8
{
if((cmd_ansver[0] & 0x1FF)!=0x1AA) //контрольная цифра не верна
{
result= FR_DISK_ERR;
}
else
{
while(1)
{
result=SEND_CMD(sd_n, CMD55,0,RESPONSE_48_BIT,&cmd_ansver[0]);
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD41, /*(1<<31)*/ 0x80000000 |(1<<20)|(1<<30)|(1<<28) ,RESPONSE_48_BIT,&cmd_ansver[0]); //|(1<<28) включает макс.скорость
if(result==SD_OK)
{
if((cmd_ansver[0] & /*(1<<31)*/ 0x80000000)!=0) //инициализация пройдена
{
if((cmd_ansver[0] & (1<<30))!=0) //CCS=1
CardType[sd_n]=SDHC_SDXC;
else //CCS=0
CardType[sd_n]=SDSC;

result=SEND_CMD(sd_n, CMD2,0,RESPONSE_136_BIT,&cmd_ansver[0]);
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD3,0,RESPONSE_48_BIT,&cmd_ansver[0]);
if(result==SD_OK)
sd_RCA[sd_n]=(cmd_ansver[0])>>16;
break;
}
}
else
{
result= FR_DISK_ERR;
break;
}

if(xTaskGetTickCount()>time)
{
result= FR_DISK_ERR;
break;
}
}
}
}
else //карта не ответила на CMD8
{
while(1)
{
result=SEND_CMD(sd_n, CMD55,0,RESPONSE_48_BIT,&cmd_ansver[0]);
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD41, /*(1<<31)*/ 0x80000000 |(1<<20)|(1<<28) ,RESPONSE_48_BIT,&cmd_ansver[0]);
if(result==SD_OK)
{
if((cmd_ansver[0] & /*(1<<31)*/ 0x80000000)!=0) //инициализация пройдена
{
CardType[sd_n]=SDSC;
result =FR_OK;
break;
}
}
else
{
result= FR_DISK_ERR;
break;
}

if(xTaskGetTickCount()>time)
{
result= FR_DISK_ERR;
break;
}
}
}

//Включаем частоту шины в соответствии с классом скорости карты. Надо бы сделать получение класса скорости от карты.
SD_SCK_DIV_8(sd_n)

//Узнаём количество секторов на карте
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD9, sd_RCA[sd_n]<<16, RESPONSE_136_BIT, &cmd_ansver[0]);
if(CardType[sd_n]==SDHC_SDXC)
{
C_SIZE =((cmd_ansver[1] & 0x1F)<<17) + ((cmd_ansver[2] & 0xFFFF0000)>>16); //биты 69-48
sd_total_sectors[sd_n]=C_SIZE*1024;
}
else
{
sd_total_sectors[sd_n]=0; //тут надо бы сделать обработку старых карт
}

if(result==SD_OK)
result=SEND_CMD(sd_n, CMD7, sd_RCA[sd_n]<<16, RESPONSE_48_BIT, &cmd_ansver[0]);
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD55, sd_RCA[sd_n]<<16 , RESPONSE_48_BIT, &cmd_ansver[0]);
if(result==SD_OK)
result=SEND_CMD(sd_n, CMD6, 0x02, RESPONSE_48_BIT, &cmd_ansver[0]); //выбираем шину 4 бита


return result;
}

Функция чтения
/////////////////////////////////////////////////////////////////////
__inline DRESULT TRY_disk_read (
BYTE Drive, /* Physical drive number */
BYTE* pBuffer, /* Pointer to the read data buffer */
DWORD SectorNumber, /* Start sector number */
BYTE SectorCount /* Number of sectros to read */
)
{
unsigned long int sd_adress,number_of_block;
unsigned long int i;
unsigned char result;
char sd_n =Drive;
EventBits_t SDIO_STA_MASK;

unsigned int cmd_ansver[4];

if(CardType[sd_n]==SDHC_SDXC)
sd_adress=SectorNumber;
else
sd_adress=SectorNumber*0x200;

number_of_block=SectorCount;

for(i=0;i<number_of_block;i++)
{
result=SEND_CMD(sd_n, CMD17, sd_adress+(i*512), RESPONSE_48_BIT, &cmd_ansver[0]);
if(result!=SD_OK)
{
ADD_EVENT_MESSAGE_SDx(sd_n,"#!!! ERROR: TRY_disk_read: CMD18: Ошибка 2#");
return RES_ERROR;
}

//xSemaphoreTake(x_SD_Multi_Transmit_Complite[sd_n],0);//
xEventGroupClearBits(x_SDIO_Transmit_EventGroup,0xFFFFFFF);
SD_DMA_START_READ(sd_n,pBuffer+(i*512),512);

SDIO->ICR=0xFFFFFFFF;

SDIO->DTIMER= 0xffffff;
SDIO->DLEN=512;

SDIO->DCTRL=SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DBLOCKSIZE_3; // размер блока 512
SDIO->DCTRL|=SDIO_DCTRL_DMAEN; //DMA enabled.
SDIO->DCTRL|=SDIO_DCTRL_DTDIR; //Direction. //направление передачи из дарты в процессор
SDIO->DCTRL|=SDIO_DCTRL_RWSTART; //
SDIO->DCTRL|=SDIO_DCTRL_DTEN; //DPSM is enabled //запускаем передачу данных

//Ждём выставления флагов в прерывании. По результатам судим о успехе/не успехе передачи
SDIO_STA_MASK=xEventGroupWaitBits(x_SDIO_Transmit_EventGroup, SDIO_STA_DBCKEND | SDIO_STA_STBITERR /*| SDIO_STA_DATAEND */ | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL, pdTRUE, pdFALSE, 10);
if(SDIO_STA_MASK & SDIO_STA_CTIMEOUT)
return RES_ERROR;

if(SDIO_STA_MASK & (SDIO_STA_STBITERR | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL ))
return RES_ERROR;
}
return RES_OK;
}

И очень похожая функция записи
/////////////////////////////////////////////////////////////////////
__inline DRESULT TRY_disk_write(
BYTE Drive, /* Physical drive number */
unsigned char* pBuffer, /* Pointer to the read data buffer */
DWORD SectorNumber, /* Start sector number */
BYTE SectorCount /* Number of sectros to read */

)
{
char sd_n=Drive;
char result;
unsigned long int i;
unsigned long int sd_adress,number_of_block;
EventBits_t SDIO_STA_MASK;

unsigned int cmd_ansver[4];

if(CardType[sd_n]==SDHC_SDXC)
sd_adress=SectorNumber;
else
sd_adress=SectorNumber*0x200;

number_of_block=SectorCount;

for(i=0;i<number_of_block;i++)
{
result=SEND_CMD(sd_n, CMD24, sd_adress+(i*512), RESPONSE_48_BIT, &cmd_ansver[0]);
if(result!=SD_OK)
{
ADD_EVENT_MESSAGE_SDx(sd_n,"#!!! ERROR: TRY_disk_write: CMD24: Ошибка 2#");
return RES_ERROR;
}

xEventGroupClearBits(x_SDIO_Transmit_EventGroup,0xFFFFFFF);
SD_DMA_START_WRITE(sd_n,pBuffer+(i*512),512);

SDIO->ICR=0xFFFFFFFF;

SDIO->DTIMER= 0xffffff;
SDIO->DLEN=512;

SDIO->DCTRL=SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DBLOCKSIZE_3; // размер блока 512
SDIO->DCTRL|=SDIO_DCTRL_DMAEN; //DMA enabled.
SDIO->DCTRL &=~ SDIO_DCTRL_DTDIR; //Direction. //направление передачи из процессора в карту
SDIO->DCTRL|=SDIO_DCTRL_DTEN; //DPSM is enabled //запускаем передачу

SDIO_STA_MASK=xEventGroupWaitBits(x_SDIO_Transmit_EventGroup, SDIO_STA_DBCKEND | SDIO_STA_STBITERR /*| SDIO_STA_DATAEND */ | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL, pdTRUE, pdFALSE, 10);
if(SDIO_STA_MASK & SDIO_STA_CTIMEOUT)
return RES_ERROR;

if(SDIO_STA_MASK & (SDIO_STA_STBITERR | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL ))
return RES_ERROR;
}
return RES_OK;

}


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 1 2014, 18:49
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Аминьsm.gif
Кстати, у вас в SEND_CMD() не хватает break-а в ветке case RESPONSE_136_BIT. Просто глаз зацепился.
Ну и в тэги [сode]/[сodebox] бы код оформить...


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 1 2014, 21:33
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ Nov 1 2014, 22:49) *
Ну и в тэги [сode]/[сodebox] бы код оформить...


Сколько раз пробовал, у меня код в этих тегах разъезжается. Перед каждой строчкой появляется непредсказуемое количество пробелов, причём редактировать их количество так что бы становилось ровно не получается.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 4 2014, 02:41
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Подскажите, какой командой в режиме SDIO узнают, готова ли карта для приёма следующего блока данных ? При записи нескольких блоков подряд происходит ошибка, а если вставить задержки то всё хорошо.
И то же самое при мультиблочной записи(CMD25) . На втором блоке SDIO выставляет флаг ошибки STA DCRCFAIL . А если блоки разделить задержками, то всё хорошо. Что на самом деле нужно делать между отправками блоков в мультиблочной записи ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 4 2014, 06:18
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Перед отправкой команд CMD24/CMD25 нужно дожидаться готовности карты.
Для этого читать статус (CMD13_SEND_STATUS), и проверять бит READY_FOR_DATA.
После этого можно писать. (Между блоками в мультиблочной записи проверять готовность не нужно. По крайней мере, если пишем через DMA).
Точно так же нужно проверять готовность перед командами чтения (CMD17/CMD18).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 4 2014, 15:18
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ Nov 4 2014, 10:18) *
Перед отправкой команд CMD24/CMD25 нужно дожидаться готовности карты.
Для этого читать статус (CMD13_SEND_STATUS), и проверять бит READY_FOR_DATA.
После этого можно писать. (Между блоками в мультиблочной записи проверять готовность не нужно. По крайней мере, если пишем через DMA).
Точно так же нужно проверять готовность перед командами чтения (CMD17/CMD18).


Спасибо.
У меня проблема исчезла, после того как вставил CMD13 с проверкой бита READY_FOR_DATA между блоками в мультиблочной передаче(CMD25). Перед CMD25 проверка READY_FOR_DATA не помогла.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 4 2014, 15:18
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ Nov 4 2014, 10:18) *
Перед отправкой команд CMD24/CMD25 нужно дожидаться готовности карты.
Для этого читать статус (CMD13_SEND_STATUS), и проверять бит READY_FOR_DATA.
После этого можно писать. (Между блоками в мультиблочной записи проверять готовность не нужно. По крайней мере, если пишем через DMA).
Точно так же нужно проверять готовность перед командами чтения (CMD17/CMD18).


Спасибо.
У меня проблема исчезла, после того как вставил CMD13 с проверкой бита READY_FOR_DATA между блоками в мультиблочной передаче(CMD25). Перед CMD25 проверка READY_FOR_DATA не помогла.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 4 2014, 17:49
Сообщение #10


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Я что-то не понял. Вы что, блоки отправляете по одному? Так ведь вся суть команды CMD25 в том, что можно отправить сразу много блоков одной пачкой!
Допустим, у вас 4К данных. Вы ждёте готовности (CMD13), потом даёте команду CMD25, и натравливаете DMA на все свои 4К. И все 4К сразу и передаются.
Где здесь "между блоками"?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 4 2014, 19:13
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ Nov 4 2014, 21:49) *
Где здесь "между блоками"?


Почему-то я был уверен, что блоки можно отправлять только по одному, и после каждого надо ждать выставления флагов в SDIO STA . Сейчас попробовал все разом, и действительно, заработало !


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 27 2015, 19:42
Сообщение #12


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Нет ли у кого-нибудь информации о том, в каких типах карт допустима невыравненная мультиблоковая запись? На некоторых SDHC я проверял - работает. Пока неработающую не встретил. А т.к. винда злостно форматирует кластеры на невыравненных адресах, то разбивать 4К кластер на 4+2+1+1 сектор записи вместо одной в 8 секторов - это непозволительная роскошь. Насколько я заметил, стыковка даже мультиблоков делается самой картой (SDHC) и только в момент ухода с какой-то внутренней грануляции карты возникает процесс записи и выдача BUSY. Вопрос насколько старые карты так умеют делать? MMC? SD ver1?

Цитата(AHTOXA @ Nov 4 2014, 10:18) *
... Между блоками в мультиблочной записи проверять готовность не нужно. ...

При невыравненном доступе - нужно. Прямо между блоками может 50 мс BUSY встрять.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 27 2015, 19:50
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(GetSmart @ Mar 27 2015, 22:42) *
Нет ли у кого-нибудь информации о том, в каких типах карт допустима невыравненная мультиблоковая запись?


Не совсем понятно, что значит "невыровненная". Речь идёт о выравнивании адреса на 0x200 байт , или о чём-то ещё ?
И , ради любопытства, зачем Вам это ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 27 2015, 20:08
Сообщение #14


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Нееее. У SDHC передаётся сразу номер блока/сектора (т.н. сектор = 512 байт блок).

А невыровненная это когда по адресу блока допустим 0x0015 пишется блок длиной 0x003F блоков. Здесь уже и адрес и длина блока невыровненные. Но длина блока некратная степени двойки это я ещё не проверял. Но , думаю, на SDHC вполне может работать.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 27 2015, 20:23
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(GetSmart @ Mar 27 2015, 23:08) *
по адресу блока допустим 0x0015 пишется блок длиной 0x003F блоков. Здесь уже и адрес и длина блока невыровненные.


Я давно и много работаю с самыми разными SD , но Ваших слов почему-то не понимаю.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th April 2024 - 21:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01567 секунд с 7
ELECTRONIX ©2004-2016