Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SDIO+Bypass STM32F4
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Hedgehog
Здравствуйте уважаемые форумчане!
Разбираюсь с SDIO режимом STM32F407VG. Встал вопрос скорости. Решил попробовать Bypass, т.е. брать чистые, неразделенные 48 MHz для тактирования карты. Команды вроде бы проходят, а вот взаимодействие (запись) с флеш-картой не завелось. Регулярно выбивается бит TXUNDERR, что говорит о незаполненности FIFO. Пользуюсь SPL, но даташит не игнорирую. Привожу код:
CODE
void Fast_Bus()// Перевод в режим быстрой шины после инициализации
{
send_command(7,RCA<<16,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,1);
send_command(55,RCA<<16,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,1);
send_command(6,0x00000002,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,1);

SDIO_SetPowerState(SDIO_PowerState_OFF);
SDIO_InitTypeDef sdio;
sdio.SDIO_BusWide=SDIO_BusWide_4b;
sdio.SDIO_ClockBypass=SDIO_ClockBypass_Enable;
sdio.SDIO_ClockDiv=0x00;
sdio.SDIO_ClockEdge=SDIO_ClockEdge_Rising;
sdio.SDIO_ClockPowerSave=SDIO_ClockPowerSave_Disable;
sdio.SDIO_HardwareFlowControl=SDIO_HardwareFlowControl_Disable;
SDIO_Init(&sdio);
SDIO_SetPowerState(SDIO_PowerState_ON);

do
{
SDIO->ICR=0xFFFFFFFF;
send_command(13,RCA<<16,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,0);
}
while(SDIO_GetResponse(SDIO_RESP1)!=0x00000900);
}

void DPSM_Init()// Инициализация DPSM
{

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 SD_Write(uint8_t const sector_data[],uint32_t sector,uint16_t count)// Собственно запись
{

uint32_t dtlength=0;

GPIO_ToggleBits(GPIOD,GPIO_Pin_12);

for(int i=0;i<128*count;i++)
{
data_tr[i]=0x0;
}
uint32_t counter=0;

for(int i=0;i<128*count;i++)
{
data_tr[i]|=(sector_data[counter++]);
data_tr[i]|=(sector_data[counter++]<<8);
data_tr[i]|=(sector_data[counter++]<<16);
data_tr[i]|=(sector_data[counter++]<<24);
}

send_command(25,sector,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,0);
DPSM_Init();
counter=0;

do
{
if((SDIO_GetFlagStatus(SDIO_FLAG_TXFIFOHE)==SET)&&(dtlength<(512)))
{

SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
SDIO_WriteData(data_tr[counter++]);
dtlength+=32;
}

}
while ((SDIO_GetFlagStatus(SDIO_FLAG_DATAEND)|SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT)|S
DIO_GetFlagStatus(SDIO_FLAG_TXUNDERR)|SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL))!=SET); //

DPSM_DeInit();
send_command(12,0x0,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,0);// Вот здесь флаг выставлен.
if(SDIO_GetResponse(SDIO_RESP1)!=0x00000900)
{
DPSM_DeInit();
do
{
SDIO->ICR=0xFFFFFFFF;
send_command(13,RCA<<16,SDIO_CPSM_Enable,SDIO_Response_Short,SDIO_Wait_No,0);
}
while(SDIO_GetResponse(SDIO_RESP1)!=0x00000900);
SDIO->ICR=0xFFFFFFFF;
}
else
{
DPSM_DeInit();
SDIO->ICR=0xFFFFFFFF;
}

}


Вот как-то так. Помогите чайнику разобраться, очень бы хотелось активировать этот режим, т.к. иначе работа без запаса по времени почти. FAT губит все быстродействие(( Заранее благодарю откликнувшихся.
segment
Читайте STM32F40x and STM32F41x Errata sheet — "SDIO clock divider BYPASS mode may not work properly"
Genadi Zawidowski
А по DMA не проще будет "кормить" карту данными?
Hedgehog
Genadi Zawidowski,DMA не используется по указанию свыше, т.е. руководитель проекта настоятельно не рекомендует его использовать. Почему-вопрос, но видимо есть причины.
Сега, про Err Datasheet спасибо, просто не знал о его существовании, сейчас буду пробовать. О результатах отпишусь, может поможет кому.
Спасибо.

Сега сверился с ErrData.
Цитата
In high speed communication mode, when SDIO_CK is equal to 48 MHz
(PLL48_output = 48 MHz), the BYPASS bit is equal to ‘1’ and the NEGEDGE bit is equal to
‘0’ (respectively bit 10 and bit 13 in the SDIO_CLKCR register), the hold timing at the I/O pin
is not aligned with the SD/MMC 2.0 specifications.

Биты выставлены именно так, т.е. BYPASS=1, NEGEDGE=0. Карта поддерживает 48 МГц, это UHS-I.
Может быть, проблема в том, что я не перевел командой CMD6 в некий высокоскоростной режим?
jcxz
Цитата(Hedgehog @ Oct 17 2016, 09:29) *
Genadi Zawidowski,DMA не используется по указанию свыше, т.е. руководитель проекта настоятельно не рекомендует его использовать. Почему-вопрос, но видимо есть причины.

smile3009.gif жесть какая.... Видимо начальник сам пробовал и у него не получилось.... или слышал звон...
Чувствуется - Вы сами толком не понимаете что Вам надо и как это работает.
Вообще-то DMA, при правильно организованной системе, нужен для разгрузки CPU. А на увеличение скорости обмена он напрямую не влияет.
Хотя.... в STM32 с их дохлой периферией без FIFO может быть всякое.....
Тупое увеличение частоты может совсем не принести нужного эффекта. Сначала нужно найти узкое место - где именно тормозит? И как построена работа с картой? И решить для себя вопрос - а сколько нужно-то (скорости)?
Возможно тогда поможет просто переписывание lowlevel-функций обмена с картой, ниже файловой системы. А также кеширование дисковых операций на этом уровне.
Hedgehog
Цитата
в STM32 с их дохлой периферией без FIFO

Как это без FIFO? В SDIO есть FIFO, другой вопрос почему оно не заполняется корректно, а после первой же итерации (судя по содержимому регистров) выплевывает ошибку. Причем именно в bypass режиме, в 24 МГц вежиме все классно, без затыков. Функции чтения/записи оптимизированы по самое нехочу, что там можно еще убрать-пока что непонятно.
Цитата
Вы сами толком не понимаете что Вам надо

Прекрасно понимаю, надо считать данные с АЦП, сложить их в циклический буфер, читай программное FIFO, и успевать их выплевывать в файл, чтобы буфер не переполнялся. Частота считывания 200 КГц. Понимаю как работает DMA, но думаю, что оно не принесет ожидаемого прироста. А учитывая, что с DMA никогда не работал+требование руководства высказанное еще в пору AVR (раньше Xmega 64 была), экспериментировать не очень хочется, тем более не все выжато из SDIO.

Понимаете, скорости обмена хватает. Но впритык. Поэтому хотелось бы иметь запасец, на случай долгого "отдыха" карты после записи итд, ну сами понимаете, всякое может быть, лучше выжать максимум. Поэтому и заморочился 48 МГц режимом.

Хотя согласен с вами, некоторые вещи не совсем понятны на аппаратном уровне. DMA и SDIO к ним не относятся.
Тут дело либо в непереведенной в "быстрый режим" карте (хотя почему команды проходят тогда?), либо в том, что опыты ставлю на дискавери, через проводки (укороченные, но все же...). Либо еще в чем-то мною неизведанном пока что.
jcxz
Цитата(Hedgehog @ Oct 17 2016, 10:54) *
Прекрасно понимаю

Ну так если понимаете, то тогда ещё раз - где именно тормоза? Что именно надо ускорить? Именно сам обмен с картой? (Вы вообще смотрели временные диаграммы обмена по шине?) Или всё-таки программную обработку на уровне FS (или каком другом)? Или ваша работа на пользовательском уровне по запихиванию данных в файлы? Или операции записи/стирания на карту? Или ещё где? Где оценочный расклад какая часть процесса сколько занимает (в %)?
Как правило, когда для ускорения хотят тупо поднять частоту, то толком не понимают как именно работает весь процесс, где возникают основные расходы времени и тормоза.
Просто даже 24МГц - это даже для SPI очень прилично (3МБ/сек), такой поток процессору уровня Cortex-M и всему ПО, которое работает с этим потоком (файловая система и т.п.) уже довльно сложно переварить. А тут у Вас SDIO! Там ещё в разы больше поток. всё это говорит о том, что львиная доля времени будет уходить не на обмен с картой, а на программную обработку. И просто поднятие частоты даст прирост скорости всего на пару процентов.
Т.е. - Вы роете совсем не в том направлении.
Да и вообще что-то непонятно - как именно поток данных с АЦП на 200кГц может перегрузить карту работающую на 24МГц? Или у Вас несколько каналов или Вы ещё какие-то данные пишете на карту вместе?
Ещё раз вопрос - какие всё-таки требования по скорости записи??? какова скорость потока записываемых данных?
Hedgehog
Цитата
Что именно надо ускорить?


На данный момент именно обмен с картой надо довести до максимально возможного. Именно НИЗКОУРОВНЕВЫЕ функции надо оптимизировать/ускорить по максимуму. Я сейчас откинул в сторону ФС, отлаживаю только низкий уровень, обмен с картой. И кстати, переполнения при записи в файл идут именно в процессе чтения/записи, поэтому это я и полирую до блеска.
Цитата
Вы вообще смотрели временные диаграммы обмена по шине?


Если речь идет о диаграммах в документации-то да, неоднократно.
Цитата
Вы роете совсем не в том направлении.


Вполне возможно, но на этом этапе моя задача отполировать SDIO, задействовать его по полной программе. Я понимаю, что библиотека FAT не оптимальна, но ведь SDIO должна быть доведена до конца, т.е. скорость обмена должна быть максимальна.
Цитата
как именно поток данных с АЦП на 200кГц может перегрузить карту работающую на 24МГц


Вот это мне не понятно. В режиме SPI при 24 МГц все тоже на соплях пролазило. Где-то задержка-буфер переполнен. Хотя запись шла вообще без ФС, просто по секторам.
Цитата
Или у Вас несколько каналов или Вы ещё какие-то данные пишете на карту вместе?


Нет, на карту пишется только файл, правда Вы я думаю понимаете, что запись через FAT это не запись по секторам, т.е. медленнее дело идет, записывается дополнительная информация.
Цитата
Ещё раз вопрос - какие всё-таки требования по скорости записи?


Ну вот смотрите: одна выборка - 5 мкс. Буфер может содержать до 40 тыс выборок, то бишь переполняется за 200 мс. Частота именно выкидывания данных должна быть где-то 10-20 КГц. Чем больше, тем меньше вероятности попасть в переполнение. Понятно, что карта пишет быстрее, иначе бы даже на соплях ничего бы не проходило. Но учитывая прихлопы ФАТ, открытие файла, заполнение, закрытие, итд итп скорость обмена заметно падает. Именно обмена, а не записи. То есть программа не оптимизирована, я согласен, наверняка в библиотеке есть места, которые можно выбросить или оптимизировать. НО! Сейчас, именно сейчас, стоит задача выжать все из SDIO, чтобы больше к нему не возвращаться.

Цитата
какова скорость потока записываемых данных?


Именно данные пишутся с мегабитными скоростями. Сейчас. Но опрос скажем занятости карты, завершения записи-все это тоже требует времени. Т.е. все вкупе выполняется медленнее, чем хотелось бы.

Поймите правильно, сейчас я вижу, что скорость обмена с картой можно увеличить, в том числе и для команд. И это надо реализовать, а не упереться в то что "не работает, ну и фиг с ним, займусь оптимизацией FAT". Вот я почему так настырно хочу увеличить частоту. После этого я переползу в FAT и спокойно буду оптимизировать его, зная что из SD выжат максимум, все что возможно.
jcxz
Цитата(Hedgehog @ Oct 17 2016, 12:09) *
Я сейчас откинул в сторону ФС, отлаживаю только низкий уровень, обмен с картой. И кстати, переполнения при записи в файл идут именно в процессе чтения/записи, поэтому это я и полирую до блеска.

Ну это и правильно - вначале надо отладить процесс обмена с картой без ФС.
Если у Вас идут переполнения, да ещё при таком огромном буфере (на 200 мсек), то смотрите временные диаграммы работы карты. А именно - время выполнения операций записи/стирания. Возможно у Вас тормоза именно в моменты когда карта внутренне пишет данные или стирает перед ними. Возможно надо ей давать команды предварительного стирания блоков (я работал с SD давно - деталей не помню). Попробуйте разные карты. Посмотрите в CSD всё что касается размеров блоков стирания и времён.
Карта при такой внутренней записи/стирании долго не выдаёт сигнал готовности.

Цитата(Hedgehog @ Oct 17 2016, 12:09) *
Если речь идет о диаграммах в документации-то да, неоднократно.

Речь не о диаграммах в доках, а о диаграммах на экране осциллографа или логического анализатора. Сигналов на шине SDIO.

Цитата(Hedgehog @ Oct 17 2016, 12:09) *
Нет, на карту пишется только файл, правда Вы я думаю понимаете, что запись через FAT это не запись по секторам, т.е. медленнее дело идет, записывается дополнительная информация.

Блин! Опять 25!
Мы здесь не телепаты чтобы знать как Вы эти свои 200kS/s выборок АЦП на карту пишете!
Это у Вас там все исходники и если спрашиваете помощи, то непонятно почему и тогда толком не расскажете что именно делаете?
Какова разрядность данных с АЦП? Сколько каналов АЦП? Как пишете просто бинарные данные или в текстовый вид преобразуете или ещё какую инфу к ним добавляете?
Т.е. - какова требуемая скорость потока записи в байтах/сек??? Я уже не знаю как ещё понятнее спросить.....

Цитата(Hedgehog @ Oct 17 2016, 12:09) *
Ну вот смотрите: одна выборка - 5 мкс. Буфер может содержать до 40 тыс выборок, то бишь переполняется за 200 мс.

Ну что-ж - размер буфера выбран вроде достаточным.

Цитата(Hedgehog @ Oct 17 2016, 12:09) *
Но учитывая прихлопы ФАТ, открытие файла, заполнение, закрытие, итд итп скорость обмена заметно падает. Именно обмена, а не записи.

Стоп! А вы что при записи каждой порции данных потока данных в файл его открываете/закрываете? а зачем??
А так - операции с FAT ускоряются например кешированием содержимого карты в ОЗУ.
Hedgehog
Цитата
Т.е. - какова требуемая скорость потока записи в байтах/сек??? Я уже не знаю как ещё понятнее спросить.....


А я уже не знаю как ответить. Сейчас АЦП, считывание и прочая святотень откинуты. Идет работа только с SDIO, записью. Я просто беру и пишу всякую фигню на карту, без АЦП. И это надо сделать максимально быстро, а не как получится. Я понимаю, чего Вы от меня хотите. Но Вы похоже не понимаете, чего я хочу от Вас. Я хочу разобраться с 48 МГц режимом, а не оптимизировать запись с АЦП, это другая часть работы.

Цитата
Мы здесь не телепаты чтобы знать как Вы эти свои 200kS/s выборок АЦП на карту пишете!


Это отдельная песня, упомянул АЦП только потому, что хотел чтобы общее видение устройства сложилось. Повторюсь, сейчас пишу мусор.

Код
  while(1)
  {
      delay(1000);
          SD_Write(temp,i++,1);      
      GPIO_ToggleBits(GPIOD,GPIO_Pin_14);
  }


Вот именно так сейчас выглядит main (опущены процедуры инициализации). Т.е. про АЦП забыли, нету его. Извиняюсь, если внес сумятицу упоминанием об АЦП.

Цитата
Стоп! А вы что при записи каждой порции данных потока данных в файл его открываете/закрываете? а зачем??


Зачем, действительно. Я создаю и пишу файл, который содержит 2 минуты записи с АЦП. Потом закрываю. Потом создаю новый без отрыва от считывания данных с АЦП и так далее. Требования такие.

По поводу диаграмм. Смотрел на осцилле, неоднократно.

Вот еще что. Название темы у нас SDIO+Bypass, а не отладка быстродействия карты памяти. Давайте будем обсуждать режим bypass, который надо запустить. А не сторонние вещи, вроде его необходимости в отдельно взятой программе. Это первая и не последняя работа с картами памяти. Чем больше я исследую сейчас SDIO, тем меньше придется изучать его потом.
501-q
Цитата(Hedgehog @ Oct 17 2016, 14:56) *
А я уже не знаю как ответить. Сейчас АЦП, считывание и прочая святотень откинуты. Идет работа только с SDIO, записью. Я просто беру и пишу всякую фигню на карту, без АЦП. И это надо сделать максимально быстро, а не как получится. Я понимаю, чего Вы от меня хотите. Но Вы похоже не понимаете, чего я хочу от Вас. Я хочу разобраться с 48 МГц режимом, а не оптимизировать запись с АЦП, это другая часть работы.


RM0090 Reference manual, Doc ID 018909 Rev 6, p.1005/1710:

SDIO_CK is the clock to the card: one bit is transferred on both command and data lines
with each clock cycle. The clock frequency can vary between 0 MHz and 20 MHz (for a
MultiMediaCard V3.31), between 0 and 48 MHz for a MultiMediaCard V4.0/4.2, or between
0 and 25 MHz (for an SD/SD I/O card).

Так что 25 МГц -- это максимум для работы с SD карточкой. Кроме того, без DMA передача данных в SDIO будет прерываться на время обработки прерываний, что вызовет TXUNDERR. То, что у вас есть буфер на 200 мс -- это хорошо, но мало. Внимательно почитайте раздел 4.13 Speed Class Specification в документе SD Specifications Part 1 Physical Layer Simplified Specification; максимальное допустимое время обновления FAT для карточек -- 750 мс. Так что буфера менее чем на 800 мс может не хватить.

При записи на карточку основное время уходит на ожидание готовности карточки. Сама передача занимает вряд ли более 10% времени (при записи по одному сектору). Так что увеличение частоты в 2 раза, если бы это можно было сделать, даст прирост не более 5%. Гораздо больший выигрыш даст правильное выравнивание данных в памяти (чтобы писать блоками по 4 или 8 кБ за раз) и на карточке и предварительная подготовка карточки.

И еще про заполнение FIFO SDIO. При частоте 48 МГц (допустим, модуль будет работать) данные в FIFO нужно добавлять в среднем каждые 28 тактов (у вас же 4 линии данных?, ядро работает на частоте 168 МГц?). Функция SDIO_WriteData -- это не макрос! Вызов, возврат, считывание слова из памяти, запись в FIFO -- это всё запросто может длиться более 28 тактов. Так что без DMA вообще никак.

Илья
Hedgehog
501-q, читал подобные строки, поэтому меня и обуяли сомнения вообще в реализуемости этого режима. Где-то в спецификации SDIO видел, что UHS может работать на 48 МГц, отсюда и все метания по поводу допкоманды.
Спасибо за подробный ответ это было то, что нужно. Кстати, как ни странно, на соплях и с танцами с клоком процессор успешно проходит через прерывания и один файл пишет успешно, без переполнений.
Allregia
Есть еще один нюанс, который не все знают, я на эти грабли когда-то наступил, даже добавил в фирмварю проверку скорости записи/чтения карточек при разной длине блока.
Скорость записи на карту ОЧЕНЬ сильно зависит от размера блока записи, и от того, как, точнее ЧЕМ она отформатирована.
Если ее не дай бог форматнули штатными средствами Винды - все, тушите свет. Скорость падает в РАЗЫ (вплоть до десятка раз!).
Есть программа - SDFormatter (гугглом легко находится), надо ею.
Но самое интересное - после нее многие карточки работали даже быстрее чем в "заводском" виде (т.е новая неюзанная карточка с магазина).
И писать блоками хотя бы по 4-8К, а лучше по 16-32, тогда достигается максимальная скорость.
Rash
Запускал на 48МГц по DMA и без DMA на ST32F429, всё работает, скорость возрастала минимум в раз 1.5 раза. На постоянку пока не оставлял из-за ограничений в документации, т.к. проект пока тестовый. Основная проблема скорости это задержки между записью/чтением блоков и при использовании Fat эти задержки приходится ждать обычными while или попытаться сделать что нибудь полезное в это время. При чтении задержки меньше в 1,5-2 раза чем при записи. Например при чтении будут 500 мксек, а при записи 2000 мксек. Переодически возникают более длительные задержки, скорее всего при переходе между секторами карты порядка 5-30 мсек. Задержки зависят от размера блока, чем больше, тем больше задержка, но писать большими блоками выгоднее. Блоки больше 16-32кб в большинстве случаев выигрыша по скорости не дадут.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.