Jump to content

    

FatFS и прерывания

Процессор F407, карта SD класс 10. Использую двойную буферизацию. Буфера заполняются в прерывании. Со включенным прерыванием больше 21К / сек не вытягивает. Если пишу с остановкой потока перед f_write, карта с успехом пишет 42К / сек поток. В чем может быть косяк?

Если писать поток выше 21К с без отключения прерываний, возникает ошибка записи диска низкого уровня 0х01. В прерывании небольшой кусок кода занимает 20 - 30 мкс. Либо я где - то накосячил.

 

Edited by Димон Безпарольный

Share this post


Link to post
Share on other sites
37 minutes ago, Димон Безпарольный said:

Либо я где - то накосячил.

Адназначна!!!))))

По делу: карте по-барабану на прерывания, ей, главное, соблюсти протокол. Вы его точно соблюдаете? Логический анализатор есть?

Насколько я помню, перед записью/чтением нужно ждать готовности карты, а после записи необходимо ждать окончания.

Вполне возможно, что включенные прерывания нарушают либо времянки, либо атомарность доступа к какой-либо переменной.

40 minutes ago, Димон Безпарольный said:

сли писать поток выше 21К с без отключения

Кстати, а как можно писать намеренно с какой-то скоростью? Я так понимаю, карта сама позволит это.

Share this post


Link to post
Share on other sites
4 hours ago, haker_fox said:

Кстати, а как можно писать намеренно с какой-то скоростью?

У всех современных sd карт есть дополнительные уникальные команды управления, которые делятся на базовые по стандарту, и то что придумал производитель. Базовые определяются переключением стандарта, это требует полной смены алгоритма общения с картой. То-есть недостаточно просто повысить скорость интерфейса и использовать те-же функции - нужно читать поддержку стандарта конкретной sd, и перенаправлять функции чтения/записи/проверки. Стандартный драйвер от st - использует базовые команды 1,0 , и выше прыгнуть чисто физически не может. 

Уникальные команды от производителя доступны с версии 2,0. Там конечно бардак и полный хаос, но общий принцип описания команд достаточно простой - в виде hml. Место где расположено описание, у каждого производителя уникальное. По этому нужно читать id карты и использовать свои таблицы. Уникальные команды позволяют достичь максимальной скорости общения с картой. Ради экспериментов можно распотрошить драйвер от современного кардридера, там это почти в текстовом варианте записано.

Share this post


Link to post
Share on other sites
36 minutes ago, AVI-crak said:

Ради экспериментов можно распотрошить драйвер от современного кардридера, там это почти в текстовом варианте записано.

Ага, интересную информацию для себя почерпнул. Но всё-таки ТС говорит о скоростях 20 и 40 кБайт/сек. Тут повышением скорости и не пахнет, ибо если точно помню, почти все карты дают 25 Мбит на SPI-шине. По-крайней мере те карты, которые у меня были в наличие.

Share this post


Link to post
Share on other sites
8 hours ago, haker_fox said:

Адназначна!!!))))

Насколько я помню, перед записью/чтением нужно ждать готовности карты, а после записи необходимо ждать окончания.

Пытаюсь понять насколько правильно это делает FatFS. Но это слишком глубоко в железе.

 

8 hours ago, haker_fox said:

Кстати, а как можно писать намеренно с какой-то скоростью? Я так понимаю, карта сама позволит это.

Пожно. По таймеру раз в 2мс как и должно быть в изделии. Только возможности не хватает  нужно 80К/сек, о факту - только 21.

2 hours ago, haker_fox said:

Тут повышением скорости и не пахнет, ибо если точно помню, почти все карты дают 25 Мбит на SPI-шине. По-крайней мере те карты, которые у меня были в наличие.

SPI по спецификации если не ошибаюсь 20МГц. На каких же скоростях там все летает?

Share this post


Link to post
Share on other sites
4 minutes ago, Димон Безпарольный said:

Пытаюсь понять насколько правильно это делает FatFS. Но это слишком глубоко в железе.

Это не FatFS. Это драйвер карты и интерфейса. Самой FatFs глубоко индифферентна физика.

5 minutes ago, Димон Безпарольный said:

SPI по спецификации если не ошибаюсь 20МГц. На каких же скоростях там все летает?

И всё-таки 25) У меня пишет 300 кБайт/сек, читает около 2 Мбайт/сек. SPI. Измерения делал косвенно через тотал коммандер (железяка ещё и ftp-сервер организует).

Share this post


Link to post
Share on other sites
3 minutes ago, Димон Безпарольный said:

Используете двойную буферизацию? Размер буфера не подскажите?

Удивительно, но не использую буферов вообще. Драйвер FatFs напрямую общается с драйвером карты. Вот как-то так.

Share this post


Link to post
Share on other sites
1 minute ago, haker_fox said:

Удивительно, но не использую буферов вообще. Драйвер FatFs напрямую общается с драйвером карты. Вот как-то так.

Значит допустимы потери или поток не постоянен - у меня нет. Поток идет каждые 2мс и потери недопустимы.  Карта по спецификации имеет задержки до 250мс кажется.

Edited by Димон Безпарольный

Share this post


Link to post
Share on other sites
1 minute ago, Димон Безпарольный said:

Значит допустимы потери или поток не постоянен - у меня нет.

В конкретном приборе одна задача (FreeRTOS) копирует данные с внутренних носителей на карту. Файл за файлом. Тоже самое можно делать и через фтп-сервер. Поток может быть непостоянен, но потери данных недопустимы.

Share this post


Link to post
Share on other sites
9 hours ago, haker_fox said:

либо атомарность доступа к какой-либо переменной.

Похоже так. Если не останавливать поток, даже f_mount выполняется с ошибкой. sprintf не хочет печатать в буфер имя файла. В потоке не такой уж сложный код - почему он так влияет - не пойму. Может кто намекнет, как отлавливать сей баг - почему прерывание по таймеру с несложным кодом так влияет на основной процесс? Гешил на стек - добавил. Не помогло.

Share this post


Link to post
Share on other sites

Для ускорения процесса нашел вот эту статью:

 /* Предварительное выделение кластеров (чтобы предотвратить переполнение буфера
 при потоковой записи) */
    res = f_open(file, recfile, FA_CREATE_NEW | FA_WRITE); /* Создание файла */
    res = f_lseek(file, PRE_SIZE);           /* Предварительное выделение кластеров */
    if (res || f_tell(file) != PRE_SIZE) ... /* Проверка - было ли успешным 
 увеличение размера файла */
    res = f_lseek(file, DATA_START);         /* Запись потока данных без задержек
 на выделение кластеров */
    ...
    res = f_truncate(file);                  /* Обрезка неиспользуемого пространства */
    res = f_lseek(file, 0);                  /* Запись заголовка файла */
    ...
    res = f_close(file);

http://microsin.net/programming/file-systems/fatfs-seek-file.html

Но мне кажется - уж не вредитель ее писал или я настолько туп? 

res = f_lseek(file, DATA_START);         /* Запись потока данных без задержек
 на выделение кластеров */

Как f_lseek может что  - то записать? Это же просто перемещение указателя?

Или это: res = f_lseek(file, 0); /* Запись заголовка файла */

Не пойму я этого. 

 

Share this post


Link to post
Share on other sites
2 часа назад, Димон Безпарольный сказал:

Как f_lseek может что  - то записать? Это же просто перемещение указателя?

Или это: res = f_lseek(file, 0); /* Запись заголовка файла */

Что? Какие записи этой функцией...  Если уже есть файл определенного размера, и в нем что-то заменить без его увеличения, еще куда ни шло.  Или использовать ее для позиционирования в конец файла с послед. дописыванием с увеличением размера на то, что дописали.

ЗЫ. Ускорить запись средствами ФС можно только, если убрать синхронизацию после добавления фрагмента, но если при этом пропадет питание или перезагрузка, то все, после последней синхронизации или закрытия\открытия файла потеряется.

Проверьте линейную запись на карту памяти(без ФС), работайте с секторами 4К, а не 512 байт.

Share this post


Link to post
Share on other sites
6 hours ago, Димон Безпарольный said:

почему прерывание по таймеру с несложным кодом так влияет на основной процесс?

Ну дело тут не в сложности или простоте кода. А в его действиях. Например, этот обработчик прерывания будет влиять на основной процесс. Основательно влиять. Так, что тот уже никогда не получит управления. А код очень простой на самом деле.

void IsrHandler() {
  __disable_irq();
  while(1);
}

 

6 hours ago, Димон Безпарольный said:

уж не вредитель ее писал

Читайте оригинал. Ведь это не статья. А просто перевод.

Share this post


Link to post
Share on other sites
6 hours ago, haker_fox said:

Читайте оригинал. Ведь это не статья. А просто перевод.

Так и в оригинале тоже самое - переводчик не наврал.

res = f_lseek(fp, DATA_START);           /* Record data stream WITHOUT cluster allocation delay */
    ...                                      /* Write operation should be aligned to sector boundary to optimize the write throughput */

http://elm-chan.org/fsw/ff/doc/lseek.html

Как может f_lseek делать Record data stream WITHOUT cluster allocation delay? Где - то в этой последовательности должно быть F_Write.

Edited by Димон Безпарольный

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now