kovz 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба Здаствуйте уважаемые форумчане! Помогите разобраться с printf, a точнее с printf_P. На колько я понял из документации разница между ними только в области хранения строки формата вывода: в первом случае это DATA MEMORY, во втором CODE. Пример простейшей программки в IARAVR5.20 #include <pgmspace.h> __flash char const __flash * test[]={ "Hellow World!", "With fucking printf_P" }; void main(void) { printf_P("%s %s",test[0],test[1]); for(;;); } компилирую с опцией --string_literals_in_flash. проц мега 164, Normal Dlib, изменение prinf_formatter не могают. в результате выводится только пробел. при копании в исходниках библиотек обнаружил, что после того как распарсится первых два символа строки формата вывода(%s), правильно определяется адресс первого символа строки "Hellow World!"(в CODE MEMORY), но на вывод идёт то, что по тому же адресу в DATA памяти. Помогите пожалуйста кто сталкивался, как красиво выводить строки лежащие во флеше, в моём случае это уарт, про переопределение __write знаю, и к этой проблеме оно отношения не имеет, помоему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба в области хранения строки формата вывода: в первом случае это DATA MEMORY, во втором CODE. ... правильно определяется адресс первого символа строки "Hellow World!"(в CODE MEMORY), но на вывод идёт то, что по тому же адресу в DATA памяти. Так ведь ваша строка не является строкой формата. "%s %s" берется из флеша, как и заказывали. %s означает строку в DATA MEMORY. Увы, ни стандартом, ни разработчиками компилятора (судя по доке) не предусмотрен символ формата для строк во флеше. Остается вам только делать void main(void) { printf_P(test[0]); printf_P(test[1]); for(;;); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kovz 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба Так ведь ваша строка не является строкой формата. "%s %s" берется из флеша, как и заказывали. %s означает строку в DATA MEMORY. Увы, ни стандартом, ни разработчиками компилятора (судя по доке) не предусмотрен символ формата для строк во флеше. Остается вам только делать void main(void) { printf_P(test[0]); printf_P(test[1]); for(;;); } да спасибо я пришел к тому же выводу, что при старте прийдётся все строки переписыватьв озу и из него уже выводить в порт. Грустно конешно, особенно после ARMов :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба да спасибо я пришел к тому же выводу, что при старте прийдётся все строки переписыватьв озу и из него уже выводить в порт.Зачем??? Подставляйте их в качестве форматной строки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба a printf в WinAVR умеет в строке формата и строку из флеша брать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
M_Andrey 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба Никогда не пользовался printf'-ом, но давно хотел написать по поводу __flash char const __flash * test[], а тут как раз тема подвернулась. Уже давно пользуюсь для Fujitsu MB90*** строками для вывода на дисплей определением: const char * const text[...]= {..., ..., ..., }; (очень удобно :-) ) и потом print(text); И с наскоку хотел все библиотеки перекинуть для AVR-ов, но не тут-то было, компилятор все эти константы переносит в ОЗУ (SRAM) и оперативка быстро заканчивается! Приходится все красивости переводить в кривизну типа: __flash const unsigned char text0[]={...}; __flash const unsigned char text1[]={...}; ... потом процедура копирования из (__flash const unsigned char) в буфер (buf) ОЗУ и вызов print(buf); Может кто знает как сделать это "красиво"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kovz 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба a printf в WinAVR умеет в строке формата и строку из флеша брать... Вобщем всем спасибо, разобрался окончательно. Функция printf в качестве строки формата и аргументов требует данные из ОЗУ. Функция printf_P в качестве строки формата принимает строку из flash? а в качестве аргументов данные из ОЗУ. Это окончательно и безповоротно (если говорить о библиотечной реализации). Но у меня вопрос появился ещё более завёрнутый :) По умолчанию printf(_P) выводит данные в stdout. По идее, на сколько я понял, в Normal Dlib stdout linebuffered. Судя по исходникам библиотек, буфер статический на 80 байт(тоже и по документации). Так вот вопрос знатокам: возможно ли сделать так, чтоб при вызове printf(_P)данные записывались в этот буфер, а потом функция передачи по USART, построенная на прерываниях, выводила это всё в порт? понимаю что тут могут возникнуть вопросы о целесообразности такого действия, но специфика приложения позволяет, и даже предпочтительнее освободить ресурсы ЦПУ, а данные передавать в фоне. Честно говоря необходимость работать с printf в порт возникла впервые, посему не судите строго за ламерские вопросы :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба По умолчанию printf(_P) выводит данные в stdout. По идее, на сколько я понял, в Normal Dlib stdout linebuffered. Судя по исходникам библиотек, буфер статический на 80 байт(тоже и по документации). Так вот вопрос знатокам: возможно ли сделать так, чтоб при вызове printf(_P)данные записывались в этот буфер, а потом функция передачи по USART, построенная на прерываниях, выводила это всё в порт?"всё не так" . Нужен не printf, а fprintf. Определяем функцию, которая "выводит байт в UART" (на самом деле она может помещать его в циклический буфер, выгребаемый из прерываний, а уж если там нет места - тогда ждать) и определяем файловый объект #include <stdio.h> int console_putc(char ch, FILE*stream) { (void)stream; while( uart_tx_buffer_full() ); uart_tx_buffer_put(ch); return 0; } FILE console_file = FDEV_SETUP_STREAM(console_putc, 0, _FDEV_SETUP_WRITE); #define fconsole (&console_file) Теперь можно так: fprintf_P( fconsole, PSTR("Hello %5d times!!!"), 1000); А можно так: void dbg_printf_P(dbg_level lev, const prog_char * fmt, ...) { if (lev <= curr_lev) { va_list va; va_start(va, fmt); vfprintf_P(fconsole, fmt, va); va_end(va); } } Что приятно - это не мешает параллельно создать файловый объект ЖКИ-индикатора (настроив его на соответствующую функцию вывода) или "ещё чего надо" и выводить тем же fprintf-ом и туда тоже. А вообще - смотрите описание avr-libc Ой, не заметил сначала. Функция printf_P в качестве строки формата принимает строку из flash? а в качестве аргументов данные из ОЗУ. Это окончательно и безповоротно (если говорить о библиотечной реализации). Смотрите то же описание avr-libc. Если имеются ввиду аргументы - числа, то это так. Для строк поддерживается расширение: %s - из ОЗУ, %S - из флеша. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kovz 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба огромное спасибо! завтра буду пробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_Shl 0 22 мая, 2009 Опубликовано 22 мая, 2009 · Жалоба Для строк поддерживается расширение: %s - из ОЗУ, %S - из флеша. А в CodeVision будет %p из флеш. Не понятно только одного: не ужели нельзя сделать LARGE модель с 32 битами на указатель, верхние 2 из которых использовать как признак типа памяти к которой доступаемся? А то приходится в некоторые свои функции передавать в указатели на void и признак куда он указывает, а внутри функции добавлять разбор... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 23 мая, 2009 Опубликовано 23 мая, 2009 · Жалоба А в CodeVision будет %p из флеш.не перестаю удивляться этому компилятору с "языка, похожего на С". В стандарте С %p зарезервирован под указатель...Не понятно только одного: неужели нельзя сделать LARGE модель с 32 битами на указатель, верхние 2 из которых использовать как признак типа памяти к которой доступаемся?Раз уж первый вопрос был про IAR, то в нем есть ключевое слово __generic для объявления таких указателей и функции printf_G и подобные для работы с ними. Для avr-gcc (WinAVR) добиться подобного эффекта тоже возможно при помощи финта ушами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kovz 0 23 мая, 2009 Опубликовано 23 мая, 2009 (изменено) · Жалоба не перестаю удивляться этому компилятору с "языка, похожего на С". В стандарте С %p зарезервирован под указатель... В IAR это именно так вопрос был про IAR, то в нем есть ключевое слово __generic для объявления таких указателей и функции printf_G и подобные для работы с ними. К сожалению функции printf_G несуществует. Для строк поддерживается расширение:..., %S - из флеша. IAR не имеет такого спецификатора Изменено 23 мая, 2009 пользователем kovz Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 23 мая, 2009 Опубликовано 23 мая, 2009 · Жалоба IAR не имеет такого спецификатораТьху, прошу прощения. Тут много всего упоминалось и мне показалось, что речь о gcc Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться