реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> помогите с printf
kovz
сообщение May 22 2009, 12:54
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 25-07-05
Пользователь №: 7 079



Здаствуйте уважаемые форумчане!
Помогите разобраться с 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 знаю, и к этой проблеме оно отношения не имеет, помоему.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 22 2009, 13:33
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(kovz @ May 22 2009, 15:54) *
в области хранения строки формата вывода: в первом случае это 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(;;);
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kovz
сообщение May 22 2009, 14:16
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 25-07-05
Пользователь №: 7 079



Цитата(Сергей Борщ @ May 22 2009, 16:33) *
Так ведь ваша строка не является строкой формата. "%s %s" берется из флеша, как и заказывали. %s означает строку в DATA MEMORY. Увы, ни стандартом, ни разработчиками компилятора (судя по доке) не предусмотрен символ формата для строк во флеше. Остается вам только делать
Код
void main(void)
{
  printf_P(test[0]);
  printf_P(test[1]);
  for(;;);
}


да спасибо я пришел к тому же выводу, что при старте прийдётся все строки переписыватьв озу и из него уже выводить в порт. Грустно конешно, особенно после ARMов sad.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 22 2009, 14:37
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(kovz @ May 22 2009, 17:16) *
да спасибо я пришел к тому же выводу, что при старте прийдётся все строки переписыватьв озу и из него уже выводить в порт.
Зачем??? Подставляйте их в качестве форматной строки.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ARV
сообщение May 22 2009, 15:20
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



a printf в WinAVR умеет в строке формата и строку из флеша брать...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение May 22 2009, 18:02
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Никогда не пользовался printf'-ом, но давно хотел написать по поводу __flash char const __flash * test[], а тут как раз тема подвернулась.

Уже давно пользуюсь для Fujitsu MB90*** строками для вывода на дисплей определением:

const char * const text[...]=

{...,

...,

...,

};

(очень удобно :-) )

и потом print(text[i]);

И с наскоку хотел все библиотеки перекинуть для AVR-ов, но не тут-то было, компилятор все эти константы переносит в ОЗУ (SRAM) и оперативка быстро заканчивается! Приходится все красивости переводить в кривизну типа:

__flash const unsigned char text0[]={...};

__flash const unsigned char text1[]={...};

...

потом процедура копирования из (__flash const unsigned char) в буфер (buf) ОЗУ и вызов print(buf);

Может кто знает как сделать это "красиво"?
Go to the top of the page
 
+Quote Post
kovz
сообщение May 22 2009, 19:14
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 25-07-05
Пользователь №: 7 079



Цитата(ARV @ May 22 2009, 18:20) *
a printf в WinAVR умеет в строке формата и строку из флеша брать...


Вобщем всем спасибо, разобрался окончательно.
Функция printf в качестве строки формата и аргументов требует данные из ОЗУ.
Функция printf_P в качестве строки формата принимает строку из flash? а в качестве аргументов данные из ОЗУ.
Это окончательно и безповоротно (если говорить о библиотечной реализации).

Но у меня вопрос появился ещё более завёрнутый smile.gif
По умолчанию printf(_P) выводит данные в stdout. По идее, на сколько я понял, в Normal Dlib stdout linebuffered. Судя по исходникам библиотек, буфер статический на 80 байт(тоже и по документации). Так вот вопрос знатокам: возможно ли сделать так, чтоб при вызове printf(_P)данные записывались в этот буфер, а потом функция передачи по USART, построенная на прерываниях, выводила это всё в порт?
понимаю что тут могут возникнуть вопросы о целесообразности такого действия, но специфика приложения позволяет, и даже предпочтительнее освободить ресурсы ЦПУ, а данные передавать в фоне.
Честно говоря необходимость работать с printf в порт возникла впервые, посему не судите строго за ламерские вопросы laughing.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 22 2009, 19:59
Сообщение #8


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(kovz @ May 22 2009, 22:14) *
По умолчанию 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

Ой, не заметил сначала.
Цитата(kovz @ May 22 2009, 22:14) *
Функция printf_P в качестве строки формата принимает строку из flash? а в качестве аргументов данные из ОЗУ.
Это окончательно и безповоротно (если говорить о библиотечной реализации).

Смотрите то же описание avr-libc. Если имеются ввиду аргументы - числа, то это так.
Для строк поддерживается расширение:
%s - из ОЗУ, %S - из флеша.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
kovz
сообщение May 22 2009, 20:18
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 25-07-05
Пользователь №: 7 079



огромное спасибо! завтра буду пробовать.
Причина редактирования: Бездумное цитирование
Go to the top of the page
 
+Quote Post
Nick_Shl
сообщение May 22 2009, 22:30
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 17-04-08
Пользователь №: 36 850



Цитата(ReAl @ May 22 2009, 22:59) *
Для строк поддерживается расширение:
%s - из ОЗУ, %S - из флеша.
А в CodeVision будет %p из флеш.
Не понятно только одного: не ужели нельзя сделать LARGE модель с 32 битами на указатель, верхние 2 из которых использовать как признак типа памяти к которой доступаемся? А то приходится в некоторые свои функции передавать в указатели на void и признак куда он указывает, а внутри функции добавлять разбор...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 23 2009, 08:57
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Nick_Shl @ May 23 2009, 01:30) *
А в CodeVision будет %p из флеш.
не перестаю удивляться этому компилятору с "языка, похожего на С". В стандарте С %p зарезервирован под указатель...
Цитата(Nick_Shl @ May 23 2009, 01:30) *
Не понятно только одного: неужели нельзя сделать LARGE модель с 32 битами на указатель, верхние 2 из которых использовать как признак типа памяти к которой доступаемся?
Раз уж первый вопрос был про IAR, то в нем есть ключевое слово __generic для объявления таких указателей и функции printf_G и подобные для работы с ними. Для avr-gcc (WinAVR) добиться подобного эффекта тоже возможно при помощи финта ушами.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kovz
сообщение May 23 2009, 10:45
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 25-07-05
Пользователь №: 7 079



Цитата(Сергей Борщ @ May 23 2009, 11:57) *
не перестаю удивляться этому компилятору с "языка, похожего на С". В стандарте С %p зарезервирован под указатель...

В IAR это именно так
Цитата(Сергей Борщ @ May 23 2009, 11:57) *
вопрос был про IAR, то в нем есть ключевое слово __generic для объявления таких указателей и функции printf_G и подобные для работы с ними.

К сожалению функции printf_G несуществует.

Цитата
Для строк поддерживается расширение:..., %S - из флеша.

IAR не имеет такого спецификатора

Сообщение отредактировал kovz - May 23 2009, 10:48
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 23 2009, 11:47
Сообщение #13


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(kovz @ May 23 2009, 13:45) *
IAR не имеет такого спецификатора
Тьху, прошу прощения. Тут много всего упоминалось и мне показалось, что речь о gcc


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th June 2025 - 22:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.03555 секунд с 7
ELECTRONIX ©2004-2016