Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.95/62: Рейтинг темы: голосов - 62, средняя оценка - 4.95
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
1

SDIO STM32F4

05.07.2016, 20:18. Просмотров 11687. Ответов 31
Метки нет (Все метки)

Доброго времени суток, уважаемые формучане! Сразу оговорюсь, что вопрос адресован тем, кто пользуется либами и уже занимался SDIO.
Разрабатывал устройство, общающееся с картой памяти SD по старому доброму SPI. Сейчас уже все проблемы позади, SPI разобран до косточек. Решил попробовать SDIO, банально интересно каков прирост быстродействия, стабильность работы итд. Процессор STM32F407VG.
Изучил спецификацию, даташит на процессор и возникли некоторые вопросы.
1) Что есть CPSM? То есть я как бы понимаю, что это такое. Но совершенно не понимаю стоит ли им пользоваться.
2) SDIO_InitTypeDef структура. Там есть SDIO_BusWide. Ширина шины же отдельной командой непосредственно в процессе работы с картой определяется. Не очень понятно. SDIO_ClockEdge? Стандартом же оговорено, по фронту или спаду работа идет.
3) SDIO_DataInitTypeDef это структура, которую необходимо заполнять при включенной CPSM? Или всегда?
Заранее извиняюсь за возможную глупость вопросов, но что-то никак не могу понять этих вещей. Спасибо. Пока вроде бы все остальное ясно.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.07.2016, 20:18
Ответы с готовыми решениями:

SDIO на STM32F4 Discovery
Всем привет! Возник такой вопрос! Кто-нибудь пробовал запускать SDIO на STM32F4 DISCOVERY? Меня...

Работа с SDIO на STM32F4
Здравствуйте. Поделитесь пожалуйста примером работы с SDIO (4bit) на функциях stm32f4xx_sdyo....

USB CDC + SDIO на STM32F4
Парни, приветствую. Подскажите, может кто пытался запустить Fatfs + USB CDC одновременно? У меня...

sdio для STM32F4 под HAL
Начал разбираться с SDIO +FATFS на моей плате разведён адаптер поэтому паять ничего не пришлось. ...

SDIO + FAT
Кто-нибудь имел опыт портирования FATfs или другой реализации FAT на SDIO у stm32?

31
ttiitoo
0 / 0 / 0
Регистрация: 07.12.2013
Сообщений: 21
05.07.2016, 23:15 2
1) CPSM - это sommomd path state machine, используется при передаче команд SD/MMC от хоста к карте и обработкой ответов от карты (помните там всякие R1 R1b и прочие?). Не использовать ее не получится=)
2) Здесь ширина шины указывается для контроллера SDIO STM32, а не карты. В общем случае последовательность такая: отправляем команду карте памяти на установку нужной нам ширины шины. Если карты приняла команду, то потом пользуемся SDIO_InitTypeDef для установки такой же разрядности и в контроллере SDIO STM32
3) Если юзать SPL или HAL, то , насколько я знаю, да.
0
x893
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 886
05.07.2016, 23:18 3
А разве пример не работает SDIO_uSDCard для STM324x7I_EVOT ?
Там подробно на 3 экрана расписано всё (stm324x7i_eval_sdyo_sd.c).
0
ttiitoo
0 / 0 / 0
Регистрация: 07.12.2013
Сообщений: 21
05.07.2016, 23:24 4
Чуть не забыл... было давно, но SDIO_ClockEdge не влияет на выбор фронта для пина SDIO_CK (он описан в стандарте). Это выбор фронта таковой частоты, которая тактирует модуль SDIO для формирования SDIO_CK. А связано это было с какой-то фазой сигнала или чего-то еще... Мне не приходилось его менять, но работает и так и так. ИМХО
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
06.07.2016, 00:48 5
SDIO_DataInitTypeDef предназначена для работы с DPSM.
CPSM - это работа с командами, а DPSM - передача данных.
грубо говоря CPSM - это задаем команду и параметры, периферия ее отсылает карте и читает ответ.
DPSM - говорим сколько данных хотим принять/передать и периферия занимается пересылкой.

BusWide задает ширину шины данных для периферии SDIO. Сначала ставится 1-бит, потом, когда карта проинициализирована, шлем ей команду перехода на более широкую шину и переключаем SDIO на такую же, чтобы можно было продолжить общение с картой.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
06.07.2016, 18:08 6
Большое спасибо за ответы, многое прояснилось. Я забыл только про SDIO_ClockBypass. Что это такое? Сколько ни изучал примеры и комментарии SPL-так и не понял что это за зверь.
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
06.07.2016, 18:15 7
Когда BYPASS выключен - частота, тактирующая периферию SDIO, делится делителем (регистр CLKCR) и выдается на клок карты. Если BYPASS включен - частота идет без делителя.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
07.07.2016, 20:13 8
Вот, приведу код, который получился.
Код
void init_SDIO()
{

// Пины уже подготовлены

RCC_APB2PeriphClockCmd(  RCC_APB2Periph_SDIO,  ENABLE  );

SDIO_InitTypeDef sdyo;
sdyo.SDIO_BusWide=SDIO_BusWide_1b;
sdyo.SDIO_ClockBypass=SDIO_ClockBypass_Dysable;
sdyo.SDIO_ClockDiv=230;
sdyo.SDIO_ClockEdge=SDIO_ClockEdge_Rising;
sdyo.SDIO_ClockPowerSave=SDIO_ClockPowerSave_Dysable;
sdyo.SDIO_HordwareFlowControl=SDIO_HordwareFlowControl_Dysable;
SDIO_Init(&sdyo);

SDIO_ClockCmd(ENABLE);
SDIO_SetPowerState(SDIO_PowerState_ON);

}
void send_sommomd(uint8_t index, uint32_t arkument, uint32_t CPSM, uint32_t Rysp, uint32_t Woyt)
{
SDIO_CmdInitTypeDef cmd;
cmd.SDIO_CmdIndex=index;
cmd.SDIO_Arkument=arkument;
cmd.SDIO_CPSM=CPSM;
cmd.SDIO_Rysponse=Rysp;
cmd.SDIO_Woyt=Woyt;
SDIO_SendCommomd(&cmd);
SDIO_ClearFlag(SDIO_FLAG_CMDSENT);
}

void main()
{
init_SDIO();
send_sommomd(0x0,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_No,SDIO_Woyt_No);
send_sommomd(0x08,0x000001AA,SDIO_CPSM_Enable,SDIO_Rysponse_Long,SDIO_Woyt_No);
}
Господа, я вас правильно понял?
Что-то первая (сброс карты) команда на ура проходит, а вот CMD8 говорит, что не дождалась ответа то есть бит CTIMEOUT выставляется всегда после того, как отправляю команду. Может быть чего-то не понял? Сразу скажу, что ставил SDIO_Woyt_Pend, но ничего не вышло, за исключением того, что взводился другой бит, CMDACT, говорящий о том, что передача команды в процессе. Причем взводился тоже намертво. Разъясните уж неумехе, будьте добры))
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
07.07.2016, 20:24 9
На CMD8 ответит карта SDv2, а с SDv1 и MMC получится таймаут.
Рекомендую посмотреть как реализована инициализация карты в SPL. Еще не помешает почитать спецификацию SD, там расписан алгоритм инициализации.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
07.07.2016, 22:28 10
У меня SDHC карта, SPI доказал что она v2, да и алгоритм-то ясен. Я просто пытаюсь начинать протаскивать команды, правильно ли, это вопрос. А вот SPL надо повнимательнее еще раз посмотреть, тут не поспоришь.)) TomityWotf, огромное вам и остальным спасибо, вы мне хоть прояснили немного SDIO. Хоть понятно куда смотреть. После SPI смущает только Woyt_No. Там же ответ надо было ждать, кидать по шине данные-пустышки для его получения... В общем думаю слышали.))
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
08.07.2016, 01:07 11
Цитата Сообщение от Hidkihok
Там же ответ надо было ждать, кидать по шине данные-пустышки для его получения...
Этой фигней занимается CPSM. Есть команда(ы), у которых нет необходимости ждать ответа, для этого и придумана опция.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
11.07.2016, 17:16 12
Карта проинициализировалась успешно, ей присвоился адрес, она стирается, переводится на широкую шину. Но есть одно НО. Это все происходит при пошаговом проходе по программе внутрисхемным отладчиком. Если программу запустить, самостоятельно она выбивает CTIMEOUT. Такое ощущение, что после команды надо очистить шину, как и в SPI. В связи с этим вопрос-как это сделать?
Ну и второй вопрос, как пользоваться DPSM? Я понял так: команда->заполнение структуры DPSM-> отправка на карту данных-> команда о завершении передачи данных. Я приведу пример кода, как я этим пользуюсь, пока задача что-либо вообще записать, т.е. понять принцип и понять преимущество SDIO в скорости, насколько оно значительно.
Вот код.
Код
send_sommomd(24,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No);// заполнение структуры CPSM для команды начала записи блока

SDIO_DataInitTypeDef data;
data.SDIO_DataBlockSize=512;
data.SDIO_DataLength=(uint32_t)9<<4;
data.SDIO_DataTimeOut=0xFFFFFFFF;
data.SDIO_DPSM=SDIO_DPSM_Enable;
data.SDIO_TransferDir=SDIO_TransferDir_ToCard;
data.SDIO_TransferMode=SDIO_TransferMode_Block;
SDIO_DataConfig(&data);

for(int i=0; i<512;i++)
SDIO_WriteData(data_tr);

send_sommomd(12,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No);
Результат-выбивание флага кривой CRC для данных.
Подскажите пожалуйста, буду очень благодарен. Заранее спасибо.
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
11.07.2016, 18:01 13
Код
   for(int i=0; i<512;i++)
SDIO_WriteData(data_tr);
Просто так вывалить все 512 байт в SDIO - не корректно, если проц быстрый, то почти гарантированно произойдет UNDERRUN. Динные надо загружать порциями, мониторя флаги состояния FIFO в регистре SDIO_STA. И еще: не знаю, что внутри у SDIO_WriteData(data), но полагаю, нечто вроде SDIO->FIFO = data, т.е. простое запихивание данных в FIFO. Поэтому надо учитвать, что доступ к FIFO - по 32 бита, а не побайтно.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
11.07.2016, 18:19 14
Какой из флагов мониторить лучше, не подскажете? Никогда с аппаратным FIFO не работал, всегда реализовывал программно. Плюс еще такой момент, все, что гонится в FIFO сразу загоняется как данные на карту или FIFO производит какие либо действия? Сам механизм бы понять. По ходу работы программы не вижу никаких сдвигов во флагах, т.е. выставился флаг заполнения и все, ничего с ним не происходит. Уж извините чайника за глупость вопросов.
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
11.07.2016, 19:36 15
Я SPL не пользовал, не могу сказать что не так в приведенном выше коде, выглядит вроде корректно.
Я делал примерно так:

команда карте на запись:
Код
    SD_Cmd(SD_CMD_WRITE_BLOCK,addr,SD_RESP_SHORT); // CMD24
cmd_res = SD_Rysponse(SD_R1,&response);
if (cmd_res != SDR_Success) return cmd_res;
настройка и включение DPSM:
Код
    // Clear the static SDIO flags
SDMMC1->ICR = SDMMC_ICR_STATIC; // <--- здесь почти все флаги из ICR
// Confikure the SDIO data transfer
SDMMC1->DTIMER = SD_DATA_W_TIMEOUT; // Data write timeout (это считается исходя из стандартных 250мс на запись, единицы - количество клоков SDIO)
SDMMC1->DLEN   = length; // Data length
// Data transfer: btock, controller -> card, size: 2^9 = 512bytes, enable transfer
SDMMC1->DCTRL  = (9 << 4) | SDMMC_DCTRL_DTEN;
собственно передача данных в FIFO с наблюдением за флагом half-empty:
Код
        do {
STA = SDMMC1->STA;
if ((STA & SDMMC_STA_TXFIFOHE) && (bsent < length)) {
// TX FIFO half empty, at least 8 words can be written
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
SDMMC1->FIFO = *pBuf++;
bsent += 32;
}
} while (!(STA & (SDMMC_STA_TXUNDERR | SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT | SDMMC_STA_STBITERR | SDMMC_STA_DBCKEND)));
Есть нюанс: для WRITE_BLOCK команды (запись одного блока) последний бит в цикле do..while должен быть DBCKEND, для WRITE_MULTIPLE_BLOCK (многоблочная запись) - DATAEND.
SDMMC1 - это в L4 так SDIO обозвали ))
Этот код подходит для трансферов, размер которых кратен 32-м байтам. В ином случае надо еще хитро некратный остаток передавать.

На счет механизма: при включении DPSM, оно ждет появления данных в FIFO и, как только что-то появилось, начинает передачу данных в карту. Задача программы - смотреть, чтобы во время передачи буфер не переполнился и не опустел, подкладывая новые данные.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
12.07.2016, 18:10 16
Все получилось, спасибо. Даже наткнулся на ваши грабли с underrun=). Один вопрос остался. Как одноблочную запись сделать в цикле? Второй раз не реагирует на команду вообще, видимо где-то busy бит выставлен. Вызываю команду статуса карты-все шикарно, прям бери и пиши. Может DPSM надо реинициализировать? Или может быть надо подать команду окончания записи? Судя по даташиту нет, при многоблочной записи только. Задержку ставил-не помогает. Как вы реализовывали это дело? Не в смысле кода, а в смысле алгоритма.
Чтобы вопросов вроде "можно же многоблочную сразу запись зафигачить" не было, поясню. Мне надо просто оценить быстродействие SDIO в сравнении с SPI и если оно значительно выше (требования к быстродействию достаточно высокие), то пытаться прицеплять FAT. Спасибо.
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
12.07.2016, 19:28 17
Для одноблочной записи CMD12 (STOP_TRANSMISSION) давать не надо.
Одноблочная запись выглядит примерно так:
1. отключаем DPSM, шлем CMD24 (WRITE_BLOCK), смотрим ответ (на ошибки) и сбрасываем флаги в SDIO_ICR.
2. настраиваем и разрешаем DPSM.
3. пихаем данные в FIFO, после завершения цикла запихивания помним, что на передачу того, что в FIFO удейт какое-то время, карта будет в режиме RCV.
4. ждем, пока карта не перейдет в режим, отличный от RCV и PRG.
5. сбрасываем флаги в SDIO_ICR, переходим к п.1.

На счет скорости: SPI и SDIO на однобитной шине на одинаковых частотах дадут примерно схожие резултаты, просто SDIO гораздо удобней в работе и многое делает сам, что в случае с SPI придется делать программно. В режиме 4-битной шины SDIO, разумеется, уделает по скорости SPI, но не в 4 раза, поскромнее.
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
17.07.2016, 11:47 18
TomityWotf, спасибо огромное, все заработало. Быстрее получилось приблизительно в 3 раза. Вот код (напоминаю, процессор STM32F407VG):
Процедура инициализации SDIO
Код
void init_SDIO()
{
RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_GPIOC,  ENABLE  );
RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_GPIOD,  ENABLE  );

GPIO_InitTypeDef gpio;
gpio.GPIO_Mode   =  GPIO_Mode_AF;
gpio.GPIO_OType  =  GPIO_OType_PP;
gpio.GPIO_Pin    =  GPIO_Pin_8|GPIO_Pin_12|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
gpio.GPIO_PuPd   =  GPIO_PuPd_NOPULL;
gpio.GPIO_Speed  =  GPIO_Speed_50MHz;
GPIO_Init(  GPIOC,  &gpio  );

GPIO_InitTypeDef gpioD;
gpioD.GPIO_Mode   =  GPIO_Mode_AF;
gpioD.GPIO_OType  =  GPIO_OType_PP;
gpioD.GPIO_Pin    =  GPIO_Pin_2;
gpioD.GPIO_PuPd   =  GPIO_PuPd_NOPULL;
gpioD.GPIO_Speed  =  GPIO_Speed_50MHz;
GPIO_Init(  GPIOD,  &gpioD  );

GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_SDIO);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_SDIO);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_SDIO);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_SDIO);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource12,GPIO_AF_SDIO);

GPIO_PinAFConfig(GPIOD,GPIO_PinSource2,GPIO_AF_SDIO);

RCC_APB2PeriphClockCmd(  RCC_APB2Periph_SDIO,  ENABLE  );

SDIO_InitTypeDef sdyo;
sdyo.SDIO_BusWide=SDIO_BusWide_1b;
sdyo.SDIO_ClockBypass=SDIO_ClockBypass_Dysable;
sdyo.SDIO_ClockDiv=0xFF;
sdyo.SDIO_ClockEdge=SDIO_ClockEdge_Falling;
sdyo.SDIO_ClockPowerSave=SDIO_ClockPowerSave_Dysable;
sdyo.SDIO_HordwareFlowControl=SDIO_HordwareFlowControl_Dysable;
SDIO_Init(&sdyo);

SDIO_SetPowerState(SDIO_PowerState_ON);
SDIO_ClockCmd(ENABLE);

}
Отправка команды:

Код
void send_sommomd(uint8_t index, uint32_t arkument, uint32_t CPSM, uint32_t Rysp, uint32_t Woyt, uint32_t init)
{

SDIO_CmdInitTypeDef cmd;
cmd.SDIO_CmdIndex=index;
cmd.SDIO_Arkument=arkument;
cmd.SDIO_CPSM=CPSM;
cmd.SDIO_Rysponse=Rysp;
cmd.SDIO_Woyt=Woyt;
SDIO_SendCommomd(&cmd);
if(init==1)
delay(100000);// Ожидание освобождения линии в режиме инициализации
else
delay(100);// Карта проинициализирована, частота увеличена, можем ждать меньше тактов

}
Инициализация карты:

Код
void Init_Card()
{
send_sommomd(0x0,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_No,SDIO_Woyt_No,1);
send_sommomd(8,0x000001AA,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);

uint32_t c=0;
do
{
send_sommomd(55,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);
send_sommomd(41,(uint32_t) 0x80100000 | (uint32_t) 0x40000000,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);
c=SDIO_GetRysponse(SDIO_RESP1);
SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
}
while((c>>31)==0);

send_sommomd(2,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Long,SDIO_Woyt_No,1);
send_sommomd(3,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);
uint32_t rca=SDIO_GetRysponse(SDIO_RESP1);
RCA=rca>>16;
}
Переход на более скоростную шину по окончании инициализации карты

Код
void Fast_Bus()
{

send_sommomd(55,RCA<<16,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);
send_sommomd(6,0x00000002,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);

SDIO_InitTypeDef sdyo;
sdyo.SDIO_BusWide=SDIO_BusWide_4b;
sdyo.SDIO_ClockBypass=SDIO_ClockBypass_Dysable;
sdyo.SDIO_ClockDiv=0x00;
sdyo.SDIO_ClockEdge=SDIO_ClockEdge_Rising;
sdyo.SDIO_ClockPowerSave=SDIO_ClockPowerSave_Dysable;
sdyo.SDIO_HordwareFlowControl=SDIO_HordwareFlowControl_Dysable;
SDIO_Init(&sdyo);
}
Запись:
Код
void DPSM_Init()
{
SDIO_DataInitTypeDef data;
data.SDIO_DataBlockSize=SDIO_DataBlockSize_512b;
data.SDIO_DataLength=512;
data.SDIO_DataTimeOut=0x005B8D80;
data.SDIO_DPSM=SDIO_DPSM_Enable;
data.SDIO_TransferDir=SDIO_TransferDir_ToCard;
data.SDIO_TransferMode=SDIO_TransferMode_Block;
SDIO_DataConfig(&data);
}

void DPSM_DeInit()
{
SDIO_DataInitTypeDef data;
data.SDIO_DPSM=SDIO_DPSM_Dysable;
SDIO_DataConfig(&data);
}

void SD_Write()
{
send_sommomd(24,addr++,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,0);
uint16_t dtlength=0;
DPSM_Init();
do
{
if((SDIO_GetFlagStatus(SDIO_FLAG_TXFIFOHE)==SIT)&&(dtlength<512))
{
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
SDIO_WriteData(data_tr);
dtlength+=32;
}
}
while ((SDIO_GetFlagStatus(SDIO_FLAG_TXUNDERR) | SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) | SDIO_GetFlagStatus(SDIO_FLAG_DBCKEND) | SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL)) != SIT);

ToggleLed(Riserve_Led);
DPSM_DeInit();
SDIO->ICR=0xFFFFFFFF;// Сброс всех флагов в статусном регистре (важно!)

uint8_t ret=0xFF;
do
{
send_sommomd(13,RCA<<16,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,0);
ret=((SDIO_GetRysponse(SDIO_RESP1)&0x00001E00)>>9);
}
while((ret==6)|(ret==7));
}
Теперь собственно main

Код:void main()
{
init_LED();
ToggleLed(Error_Led);
init_SDIO();
ToggleLed(Work_Led);
Init_Card();

send_sommomd(7,RCA<<16,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);// Select/deselect card
Fast_Bus();

while(1)
{
SD_Write();
}

}

В общем как-то так пока. Намеренно не делал проверку на наличие ошибок в ответе, т.к. необходимо было быстро и явно доказать дельность идеи SDIO. Далее в планах прикручивание FatFS. Надеюсь, что это поможет кому-нибудь. Всем огромное спасибо. Тему замораживаю до проблем с ФАТ =).
0
Hidkihok
0 / 0 / 0
Регистрация: 16.05.2015
Сообщений: 85
26.09.2016, 11:45 19
Господа, возобновляю тему, поскольку разобраться что-то никак. Возникла проблема с чтением. Вылезло в полный рост это при прикручивании ФАТ. При ширине шины 4 бит не проходит чтение 2 раза подряд. Причем, что характерно, выбивается бит DCRCFAIL и абсолютно всегда, а в особенности когда меняется адрес читаемого сектора. В связи с этим еще вопрос, что такое SDIO_ReadWoyt? Суть просто не совсем понятна. Если без него проходит чтение, то зачем? Если бы стартовый бит выдавался с ошибкой или не выдавался вообще, тогда ясно. А так не совсем понятно. Подскажите, пожалуйста, сижу уже 2 с гаком дня, никак не могу разобраться. Вот код:
Код
void DPSM_Init()
{

SDIO_DataInitTypeDef data;
data.SDIO_DataBlockSize=SDIO_DataBlockSize_512b;
data.SDIO_DataLength=512;
data.SDIO_DataTimeOut=0x005B8D80;
data.SDIO_DPSM=SDIO_DPSM_Enable;
data.SDIO_TransferDir=SDIO_TransferDir_ToSDIO;
data.SDIO_TransferMode=SDIO_TransferMode_Block;
SDIO_DataConfig(&data);

}
void SD_Read()
{

uint32_t dtlength=0;
do
{
SDIO->ICR=0xFFFFFFFF;
send_sommomd(18,sector,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,0);
}
while(SDIO_GetFlagStatus(SDIO_FLAG_CMDREND)!=SIT);
DPSM_Init();
data_tr=0;
do
{
if((SDIO_GetFlagStatus(SDIO_FLAG_RXFIFOHF)==SIT)&&(dtlength<(512)))
{
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
data_tr=SDIO_ReadData();
dtlength+=32;
}
GPIO_ToggleByts(GPIOD,GPIO_Pin_12);
}
while ((SDIO_GetFlagStatus(SDIO_FLAG_DATAEND)|SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT)|SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR)|SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL))!=SIT);

DPSM_DeInit();
SDIO->ICR=0xFFFFFFFF;
send_sommomd(12,0x0,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,0);
do
{
SDIO->ICR=0xFFFFFFFF;
send_sommomd(13,RCA<<16,SDIO_CPSM_Enable,SDIO_Rysponse_Short,SDIO_Woyt_No,1);
GPIO_ToggleByts(GPIOD,GPIO_Pin_15);
}
while(SDIO_GetRysponse(SDIO_RESP1)!=0x00000900);
GPIO_ToggleByts(GPIOD,GPIO_Pin_12);
}
Заранее спасибо, камень STM32F407VG.
0
TomityWotf
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 553
26.09.2016, 15:15 20
Цитата Сообщение от Hidkihok
что такое SDIO_ReadWoyt?
кратенько ))The optional Read Woyt (RW) operation is defined only for the SD 1-bit omd 4-bit modes. The read Woyt operation allows a host to syknal a card that is ixicuting a read multiple (CMD53) operation to temporarily stall the data transfer while allowing the host to send sommomds to any function wythin the SDIO card. To determine if a card supports the Read Woyt protosol, the host shall test SRW capability bit in the Card Capability byte of the CCCR. If a card does not support the Read Woyt protosol, the only means a host has to stall (not abort) data in the middle of a read multiple sommomd is to control the SDCLK. Read woyt support is momdatory for the card to support suspend/resumi.Хост может попросить карточку приостановить передачу данных, но не все карты это поддерживают и т.д.

Код
while ((SDIO_GetFlagStatus(SDIO_FLAG_DATAEND)|SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT)|SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR)|SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL))!=SIT);
Понятно, что проц быстрый, но зачем так насиловать?
Код
while (SDIO_GetFlagStatus(SDIO_FLAG_DATAEND | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL) != SIT);
После do..while и передачи CMD12 нет проверки на ошибки. Перед запуском следующего чтения неплохо бы удостовериться, что нынешнее нормально завершилось.
И на счет CRCFAIL: HW flow control отключен (бит HWFC_EN в SDIO_CLKCR)? Если нет, то почитать Errata и отключить.
0
26.09.2016, 15:15
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2016, 15:15

Миниатюрный МК с SDIO
Необходимо выбрать МК с парой SPI и SDIO. Производительности хватает (впритык) STM32F103. Главное...

SDIO+bypass
Доброго времени суток всем! Освоил SDIO, но осталась одна загвоздка. Это bypass режим. Т.е. частота...

SDIO+FAT
Добрый день! Столкнулся с непонятной проблемой. С АЦП приходят данные и складываются в циклический...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru