среда, 8 апреля 2009 г.

Гарвардская архитектура и реализация printf()

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

Итак, потратив целый день на анализ кода различных вариаций printf() доступных в используемой clib (да, дизассемблер наш лучший друг) можно сделать следующие заключения. В предлагаемой в комплекте с IAR clib нет реализации printf() корректно работающей, когда и строка форматирования и аргументы расположены во флеше. Выход один - копировать в локальный буфер и выводить (привет ребятам и Гарварда, да идея мухи(код) отдельно, котлеты(код) отдельно неплоха, но если заранее не известно чего будет больше данных или кода, то получаем костыли компилятора типа __flash, позполяющие располагать данные в сегменте кода, и при уданом стечении обстоятельст пробежимся по все памяти обязательно).

Мысль следующая. Человеческая лень - неистребимое зло. Гораздо легче найти в интернете хрен знает какой код, чем почитать документаци. Вывод: если не хватает функционала, а самому писать лень или таланту не хватает, то следует использовать следующие варианты с понижением приоритета:
  • стандартная библиотека
  • сторонние реализации (чем более распространена реализация, тем лучше)
  • все-таки писать самому и подружиться с отладчиком
Наконец, последнее.
за это нужно гнать из профессии:
#ifdef printf
#undef printf
#endif
#define printf printf_P

2 комментария:

Анонимный комментирует...

Почему изначально printf_P() не использовали и зачем нужны эти танцы с макросами?
Ну и по моему, использование функций вроде printf/scanf для МК не есть самой хорошей идеей,
Кстати один из минусов большого количества строк в ОЗУ, это то что они при старте должны быть все-равно переписаны из FLASH памяти, так что происходит двойное расходование ресурсов, ну и время старта увеличивается, что тоже плохо.

Unknown комментирует...

Итак, по-порядку.
Танцы с макросами не нужны. Они достались в наследство со всеми остальными прелестями кода. Почему printf_P() не использовали изначально, могу только предположить, что просто не знали о нем, а когла оказалось поздно (начала кончаться память) пошли читать, правда избрали такой оригинальный путь замены всех printf() на printf_P().

Использование printf()/scanf() не преступление, отказ от библиотечной реализации должен быть одним из последних способов оптимизации по памяти/скорости, когда все остальные методы уже исчерпаны.

Ну и про FLASH. На ATmeg'е вполне допустимо писать/читать данные из области программного флеша и при определенной организации кода нет необходимости копировать данные в ОЗУ. Так что, сильно "двойного" расходования ресурсов не происходит.