STM8 работает и с FatFs

Но только не так как хотелось бы. Пожалуй это первый мой минус IAR'у.
Тем, кто не может молча читать текст с ошибками — под кат не заглядывать! Блог личный.


Попробовал я, значится, собрать FatFs от всем известного Elm-ChaN'а, и это у меня получилось. Всё Работает без плясок с буббном. Но запустить у меня получилось только в read-only версии (см. вложение). Поддержка записи ушла за отведенное IAR ограничение в 8кБайт кода, при чем без права на помилование — одним только файлом ff.c.

Откуда ноги растут
Всё из той же архитектуры и не совсем удовлетворяющей работы оптимизатора. Код FatFs изобилует 32-битной арифметикой. Более того, он практически полностью из неё состоит. И повсеместный инлайнинг операций с 32-битными значениями раздувает код до немыслимых размеров. И к сожалению не только код, но и время выполнения оставляет желать лучшего.
Методы выбранные оптимизатором я пожалуй бы сравнил с WPF. Всё достаточно универсально и работает, но не самая лучшая реализация, излишне усложненная.
Нет, всё сделано так как и просили. Просили сдвиг 32битного значения — вот вам сдвиг 32битного значения. Просили макрос — пожалуйста — вот его и встроили. И ничего что там можно было обойтись простой перестановкой байт местами (что собственно и требовалось). И ничего что указатель у нас уже есть в регистре, и его надо просто сместить на +-1, мы же можем его загрузить из памяти и добавить новое смещение, какая разница, нам же всё равно прибавлять надо.
Честно. Я поражен. Я и не ожидал что остались текие оптимизаторы. Благо что хоть умножение на степени двойки оптимизирует сдвигом.

Как с этим жить
На самом деле не всё так плохо, проблема решаема. Некоторые попытки её решения были предприняты. В итоге в 8кБайт удалось поместить пример записи файла (см. UPD2). НО. Для этого пришлось работать напильником. Пришлось лезть в саму библиотеку и править её код. Я не считаю это хорошим решением.
Так же можно было бы воспользоваться методом библиотек. Или компиляторами от Cosmic или ренисанса (или как их), у которых лимит 16-32кБайта. А стм контроллер с 32кБайтами не такая редкость и стоит рублей на 10 дороже. Но мне был интересен вариант использования stm8s103f3 (у которой 8кБайт всего).

Отсюда делаем заключение, что просто взять самый дешёвый контроллер и просто запустить на нем готовое решение — не всегда получится. Надо работать, работать и работать. Ну или не выпендриваться и взять контроллер по толще :)

UPD: Оппа, минуса. Просьба прокомментировать что не понравилось :)
UPD2:
Проведена примерно следующая доработка кода:
В файле ff.h вместо строк:
#define	LD_WORD(ptr)		(WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define	LD_DWORD(ptr)		(DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
#define	ST_WORD(ptr,val)	*(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
#define	ST_DWORD(ptr,val)	*(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)

Используем следующие определения
#define	LD_WORD2(to,ptr)	ld_word2((BYTE*)(void*)(to),(BYTE*)(void*)(ptr)+1)
#define	LD_DWORD2(to,ptr)	ld_dword2((BYTE*)(void*)(to),(BYTE*)(void*)(ptr)+3)
#define	ST_WORD(ptr,val)	st_word((ptr),val)
#define	ST_WORD2(ptr,from)	ld_word2((BYTE*)(void*)(ptr),(BYTE*)(void*)(from)+1)
#define	ST_DWORD(ptr,val)	*(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
#define	ST_DWORD2(ptr,from)	ld_dword2((BYTE*)(void*)(ptr),(BYTE*)(void*)(from)+3)

Не забываем так же описать добавленные функции
void st_word(BYTE* to, WORD val);
void ld_word2(BYTE* to, BYTE* ptr);
void ld_dword2(BYTE* to, BYTE* ptr);

В файле ff.c вместо строк:
#define LD_CLUST(dir)	(((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}

Используем
#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
#define LD_CLUST2(to,dir)	ld_clust2((BYTE*)(void*)(to),(BYTE*)(void*)(dir))
#define ST_CLUST2(dir,from)	st_clust2((BYTE*)(void*)(dir),(BYTE*)(void*)(from))

И так же добавляем функции:
void ld_word2(BYTE* to, BYTE* ptr)
{
  *to++ = *ptr--;
  *to = *ptr;
}
void ld_dword2(BYTE* to, BYTE* ptr)
{
  *to++ = *ptr--;
  *to++ = *ptr--;
  *to++ = *ptr--;
  *to = *ptr;
}
void st_word(BYTE* to, WORD val)
{
  *to++ = val;
  *to = val>>8;
}
void ld_clust2(BYTE* to, BYTE* dir)
{
  ld_word2(to, dir+DIR_FstClusHI);
  ld_word2(to+2, dir+DIR_FstClusLO);
}
void st_clust2(BYTE* dir, BYTE* from)
{
  ld_word2(dir+DIR_FstClusHI, from);
  ld_word2(dir+DIR_FstClusLO, from+2);
}

Строки вида var = MACROS(ptr[]) заменяются на конструкции вида MACROS2(&var, ptr); Условия if(MACROS(ptr[]) == var) заменяем на VARTYPE tmp; MACROS2(&tmp, ptr); if(tmp == var); Строки с константами в параметрах не меняем.
Ну и выбрасываем кучу ненужного кода их mmc/main/…
Как ни странно, вынос даже «столь маленьких» функций положительно сказывается как на размере (+1/2кБайт) так и на времени выполнения (за счет исключения 32битной арифметики).
  • +3
  • 05 марта 2012, 12:15
  • angel5a
  • 1
Файлы в топике: stm8s_ffsample.zip

Комментарии (51)

RSS свернуть / развернуть
А если компилировать в версии release? У меня разница у них была 20кБ и 11кБ.
0
  • avatar
  • PRC
  • 05 марта 2012, 12:26
RO — debug — в притык в 8к поместилось с дебаг-выводом.
RW — release оптимизация по размеру, кроссколл, запрет инлайна — в притык после допиливания и с выводом только ок/файл.
0
Это такие пироги с максимальной оптимизацией по размеру? Вроде сильная сторона IAR'а — как раз common subexpression elimination, ориентированная на выпиливание всех этих макросов… А хотя, inline'ы к ним не относятся и с ними IAR работает не очень.

А проблем с порядком байт не возникло?
ренисанса (или как их)
Raisonance. Эхехе, когда уже GCC под STM8 запилят…
А как Cosmic/Raisonance по оптимизации в сравнении с IAR?
Попробывал
Поправь на «попробовал», плиз.
0
  • avatar
  • Vga
  • 05 марта 2012, 12:32
А проблем с порядком байт не возникло?
Косвенные проблемы как раз из-за них. Так код FatFs содержит макросы для «побайтового чтения» (см. макрос _WORD_ACCESS) и при их развороте и генерируются монструозные последовательности с 32битными сдвигами. Про их (LD_WORD, LD_DWORD, ...) оптимизацию я и говорил.
сабэкспрешены там не прошли, помоему, ввиду постоянно разных областей памяти. Замена макросов на функции решает проблему, но требует несколько иного подхода.
А как Cosmic/Raisonance по оптимизации в сравнении с IAR?
В работе с библиотеками я отписывал что с указанными компеляторами у меня не сложилось, так что и проверить их уж извиняйте — никак.
Поправь на «попробовал», плиз.
Ну раз уж вы настаиваете.
А вообще писал пост прям в окне браузера, и не задумывался даже об ошибках/опечатках. А дабы и не думать в дальнейшем я вовесил предупреждение.
0
А вообще писал пост прям в окне браузера, и не задумывался даже об ошибках/опечатках. А дабы и не думать в дальнейшем я вовесил предупреждение.
Я тащемта тоже в браузере пишу (причем браузер без спеллчека). Написав блок — вычитываю. Несколько ошибок обычно остается, их по мере обнаружения мной или кем-то еще выпиливаю. Чем меньше в моем тексте остается — тем довольней встроенный граммар-наци)
0
Честно. Я поражен. Я и не ожидал что остались текие оптимизаторы.
)))
IAR — тормоз страшнючий!!! ))))
Cosmic получше будет…
0
Пробовал FatFS. Вроде ничего так. На размер кода не обращал внимания, так ради поиграцца. В свое время запилил простенький драйвер для FAT. Меня устраивает…
0
На размер кода я обратил внимание, только исходя из начально-поставленной для себя задачи: Использование stm8s103f3 в мелких задачах. Одна группа задач (всё что работает с картами памяти) отпала. Обидно конечно, но пережить можно (АРМы никто не отменял).
0
При компиляции FatFS (запись и чтение) занимают 6Кб. Лучше поиграйтесь с настройками компилятора.
32бита в FatFs необходимая вещь.
0
  • avatar
  • a9d
  • 05 марта 2012, 14:38
Также есть облегченная версия для маленьких МК.
0
При всему моем уважении к FatFS (FatFS – лучшая открытая embedded реализация FAT, а Elm-ChaN – легендарный embedded'ер), данная реализация содержит несколько спорных (IMHO) моментов:

1. Библиотека содержит собственные реализации аналогов memset(), memcmp() и т. д (функции mem_set, mem_cmp в ff.c). Это приводит к тому, что в проекте дублируется код, делающий одно и тоже – «библиотечные» функции (а куда без них в реальном проекте) и «кастомные» внутри ff.c.

2. Автор FatFS в отдельном файле определяет типы BYTE, UCHAR, CHAR и т. д. Зачем это сделано понятно – переносимость и т. д. Но почему не использовать специально предназначенные для этого uint8_t, int8_t и т. д.

Это не «наезд», просто мысли вслух. Или в подходе ChaN, а есть proffit о котором я не знаю?
0
1.а. Да, есть такое дело, но никто вам не запрещает переделать их на макрос, вызывающий стандартные функции.
1.б. Существуют стандартные библиотеки, которые оказываются очень тяжелыми для мк, и лучше их не использовать.
1.в. Сам не знаю почему это не сделано конфигурируемым параметром (мол юзать стд или свои).
2.а. Это типы винды, если посмотрите исходники, то для вин-версии эти определения игнорируются. Зачем эти типы, а не uint8_t и пр., вполне понятно. Fat является Windows системой и использование Win-типов вполне оправдано. да и uint8_t не является стандартом, они были позже внесены для удобства, и в некоторых компиляторах попросту отсутствуют, или определены в неизвестно каких файлах. Так что BYTE это было лучшее решение.
2.б. А учтите ещё и разный порядок байт на разных системах. В этом отношение DWORD говорит не просто что 4 байта, а «4 байта как их понимает Windows». это если вспомнить что вынь32 работает только на х86 архетектуре.

Продолжим спор? :)
0
Продолжим спор? :)

Да разве я с спорю? Я указал на те моменты, которые я считаю спорными. В любом случае эти моменты не принципиальны.

Но все же:

но никто вам не запрещает переделать их на макрос

Переопределить можно, но я, как и Вы, не люблю править чужие либы без необходимости. А вот вынести это в настройку – самое оно (ИМХО).

uint8_t не является стандартом

Почему? <inttypes.h> включен в стандарт С начиная с С99

В любом случае, все это не принципиально, FatFS – отличная библиотека.
0
А из бесплатных для Fat32 какие Вы знаете библиотеки? Если такие есть.
И ещё вопрос, для ext2 не встречали библиотек под мк? А то не сильно хочется исходники линукса ковырять. Хотя чем linux'овые, лучше minix'овые (не ext2 правда), те под BSD лицензией идут.
0
А из бесплатных для Fat32 какие Вы знаете библиотеки?
Когда-то, пользовался efsl. Но FatFS, IMHO, лучше.

А вот embedded-ориентированных реализаций ext2 я не встречал.
+1
Всё дело именно в переносимости…
1. Из-за различий библиотечных функций…

2. Не все компиляторы понимают uint8_t, int8_t и т. д.… старенький хайтеч STD, например…
0
Ответил выше.
0
UPD: Оппа, минуса. Просьба прокомментировать что не понравилось :)

Помог чем мог, ради восстановления справедливости :)

А вообще – не понимаю тех людей, кто анонимно минусует.
В данном случае – что Вам не понравилось? Топикстартер поделился опытом/исходниками. Сватья в личном блоге. Если есть объективная критика – отпишитесь в комментариях, получится конструктивный диалог.

Просто, по собственному опыту, знаю, что «слив» статьи без комментирования своих действий демотивирует автора. А новые стати и так редко появляются.
0
А ничего удивительного нет. Ничего не понятно из статьи. Что-то было переписано но что?
вместо того, чтоб изменить настройки компилятора автор полез в исходники, которые итак хороши. Для оптимизации по размеру «Qs» не достаточно.

Если уж совсем не в моготу, то чан специально для этого разработал облегченную версию. На нее есть ссылка на страничке FatFs.
0
elm-chan.org/fsw/ff/00index_p.html

Для тех кто не нашел ссылку. Куда еще меньше не знаю.
0
Но никто не говорит что это мега-статья на тему FatFS. Я сам, изначально, воздержался от голосования (т. к. не использую ни IAR, ни STM8, но это лично мои проблемы: ). Но автор и не утверждает, что это «феерическая расстановка точек над FatFS». Это обычная (IMHO) статья для личного блога.
Вопрос – зачем анонимно сливать статью? Если «тема не раскрыта» — отпишитесь в комментариях, возможно, автор допишет статью, и будет всем profit.
+1
Ничего не понятно из статьи.
Статья в личном блоге исключительно как «я сделал, работает» с целью поделиться исходниками кому потребуются. Цель разжевать, да помочь проглотить не ставилась (тогда бы постил в публичный).
Что-то было переписано но что?
Исходники прилогаются, времени свободного було не много.
Кстати, изменения скоро перенесу в пост и исходники удалю (не совсем соблюден копирайт). Это что бы не кричали потом «а где сорцы», даже их нет.
вместо того, чтоб изменить настройки компилятора автор полез в исходники
Настройки компилятора разные тестировались, добиться 8кБайт таак и не удалось. В итоге после анализа ассемблерных листингов делался вывод что править, а что трогать не стоит.
Если уж совсем не в моготу, то чан специально для этого разработал облегченную версию.
Еще раз перечитайте «постановку задачи». Это был эксперемент поместится ли именно FatFs в именно STM8F103F3. Я в курсе и про PetitFs и про изначально большое количество избыточного кода в примере. Но весь этот избыточный код изначально позиционировался как «резервирование места под целевую задачу». Или вы считаете что мк будет только «Hello World!» на флешку писать? :)

Эксперемент поставлен, результаты приведены. Желающие могут ими воспользоваться.
0
Благодарю. Не обязательно было.

А вообще – не понимаю тех людей, кто анонимно минусует.
Я сам не святой. Минусую анонимно посты-вопросы. Просто устал уже смотреть как люди блог превращают в форум. И писать об этом устал. Если просят — отпишу.
0
Сорцы RW версии удалил, оставил «инструкцию» по доработке. Можете для себя решить какая версия понятнее :)
0
А почему вместо доработанной версии лежат сорци обычной? Их с оф сайта скачать не?
0
Смотрите ответ (на ваш комментарий) http://we.easyelectronics.ru/angel5a/stm8-rabotaet-i-s-fatfs.html#comment48148:
Кстати, изменения скоро перенесу в пост и исходники удалю (не совсем соблюден копирайт). Это что бы не кричали потом «а где сорцы», даже их нет.
Изменения описаны в «UPD2». Сорцы доработанной библиотеки выложу не раньше чем решу вопросы копирайта.
0
FatFs либу можно значительно упростить если настроить ее на конкретную файловую систему FAT12/FAT16/FAT32.
Так, что лучше добавь дефайн в котором можно определить одну файловую систему. Это даст выигрыш почти в 2Кб.
0
Это само собой, только вот какое дело. Великий и могучий финдовс полагает что (примерно) флешки <64Мб идут в фат12, до 2Гб в фат16, свыше только фат32. Соответственно если я исключаю поддержку какой-либо системы, я могу использовать только флешки определенного объема. То есть как средство переноса данных с/на комп (для чего оно имеет смысл) оно резко теряет в функциональности. А если данные на комп не таксать, так нам и фат нахрен не нужна, спокойно изобретаем свой велосипед на 1-2кБ кода и в путь.
А так, можно ещё и поддержку разных типов носителей убрать, и размер вбить в ручную. +1кБ получаем, кто спорит.
0
Для большинства девайсов вполне можно и ограничить размер флешки. Кроме того, можно и вручную задать в какой ФС флешку форматировать. Зато появится возможность использовать флешку с F3.
Для большинства применений с МК ограничение «до двух гиг, только FAT16» вполне разумно.
0
С учетом того, что размер только растет и сейчас типовая карточка это гига 4, последний вариант выглядит более рациональным, как по мне.
0
В этом и проблема, что сейчас в основном SDHC и FAT32. А их поддержка и занимает больше всего места.
Новая карточка стоит всего ничего 300р, но это считай 300р к цене устройства.
С другой стороны у меня из карточек для «поиграцца» 256 метров. Но не факт что они будут рабочие сскажем через год.
0
Тут, я думаю, конкретное решение зависит от конкретной ситуации.
0
Из соображений совместимости (пока еще) найти SD на 1-2ГБ не проблема. А выше — нужно поддерживать SDHC. Кроме того, microSDHC могут не поддерживать SPI.
Впрочем, FAT16 вроде можно и с более крупными флешками использовать. Ограничение на 2ГБ я предлагаю именно из-за SDHC.
0
Нет, ограничение из-за количества адресуемых секторов.
я тут чё подумал. Даже SDHC же можно под FAT16 разметить, предварительно разбив её на 2 раздела. Так что это наверное самое оптимальное решение.
0
В моем случае используется одна и таже память. И она всегда будет форматироваться в FAT12. И таких ситуаций много.
Есть куча девайсов в которых карта памяти не меняется.
0
Файловая система определяется не по размеру а по количеству кластеров.
0
Да, Fat12 позволит хорошо сократить размер. Считай возможность исключить 32битную арифметику. Но таких карточек сейчас днем с огнём не сыщешь. А для дискет у меня флопика в компе нет со времени покупки.
0
А кто говорит о карточках? Это чип флеша. Которых как грязи. И на них ставится только FAT12.
0
Кстати а где это там поддержка разных типов носителей? Я в ff.c этого кода не наблюдаю.
0
Это в diskio (mmc.c) разные типы обрабатываются. Там варианты MMC/SD/SDHC.
0
Так это уже особо к FatFs и не относится.
0
Как некоторый итог демагогии (сами мной же и начатой):
— Да, можно убрать всё не нужные версии ФС.
— Да, можно заточить под конкретную карточку.
Это вместе с занимаемым объемом сократит «удобство» использования, и так же потребует ковыряния исходников библиотеки.
Я не исключаю такие варианты, но тут правильнее будет рассматривать конкретную задачу, а не абстрактного коня в вакууме. Есть свои плюсы, есть свои минусы, каждый решает для себя что для него важнее.
0
Обрезать код почти во всех функциях под конкретную файловую систему довольно просто.
Там переменная которая определяет файловую систему делается константой. Компилятор после этого весь бесмысленный код выпиливает.
0
Удобство при этом никак не потеряется. Будет тоже самое.
Мир клином не сошелся на sd картах.
0
при юзание FAT12 всё равно отанутся лишние операции с 32битными полями (в описание то структур они 32бита для вмещения цего угодно).
Вообщем сяду как-нибудь посмотрю.
Мир клином не сошелся на sd картах.
Да, есть ещё USB-stick :D
0
продолжение с мини fatFS будет?
0
Светлых мыслей.
Нужные веши пишешь.
А можно рассказать как сделать логер температуры
на LM75
чтоб просто запись вёл в файл CVS формата (разделение табуляцией)
1 столбец номер второй температура.
0
Самое простое:
Счетчик номера храните в eeprom мк. Код для чтения температуры с LM75 в другом посте. формируете буфер для записи и просто дописываете в файл новую строку (а это примеры самой FatFS).

Посложнее: Сначала считываете из файла последнюю строку и выдёргиваете из неё номер (sscanf/atoi), а далее как в первом способе.

Все это крутиться в цикле с требуемой задержкой.
0
Счетчик номера храните в eeprom мк
В этом варианте стоит почитать апноут атмела (ну или еще кого-нить) про то, как продлить жизнь ЕЕПРОМ при хранении часто обновляемых данных.
0
Кто пробовал это в SDCC проделать?
0
Пока только в планах. далеких. Оптимизация у SDCC никакая, надо будет много переделывать.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.