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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> newlib stdio, перенаправление ввода/вывода
Spym
сообщение Nov 2 2010, 15:14
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Добрый вечер.

Разбираюсь с newlib; сейчас попытался перенаправить стандартный вывод, и столкнулся с такой проблемой:
переопределил функции:
Код
_ssize_t _read_r(struct _reent *r, int file, void *ptr, size_t len);
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, size_t len);

(и прочие низкоуровневые вызовы для newlib)
и вызвал printf(), после чего обнаружил, что _write_r не вызывается.
Попробовал так же вместо указанных функций переопределять лишь
Код
int _read (int file, char *ptr, int len);
int _write(int file,char *ptr,int len);

результат тот же.

Ключи линкера:
Код
LIBS = -lstdc++ -lc -lgcc -lm
LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref $(LIBS) -T$(TARGET).ld


В качестве референса использовал этот проект: http://www.siwawi.arubi.uni-kl.de/avr_proj...ects/#gcc_stdio
Toolchain из последней сборки yagarto.

Итак, вопрос: как переопределить стандартный ввод/вывод, и что я делаю не так?

upd: версия newlib: 1.18

Сообщение отредактировал Spym - Nov 2 2010, 19:25
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 2 2010, 19:24
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Попробую издалека:
Поднимите руки, кто использует yagarto и printf.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 2 2010, 19:52
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Spym @ Nov 2 2010, 20:14) *
Ключи линкера:
Код
LIBS = -lstdc++ -lc -lgcc -lm
LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref $(LIBS) -T$(TARGET).ld


Покажите $(TARGET).ld чтольsmile.gif
Я пробовал переопределять
Код
int _write(int file, char *buffer, unsigned int count)

, работало.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 2 2010, 19:55
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Цитата(AHTOXA @ Nov 2 2010, 22:52) *
Покажите $(TARGET).ld чтольsmile.gif

Запросто.
Прикрепленный файл  gcc_freertos_test.ld.txt ( 4.59 килобайт ) Кол-во скачиваний: 253


Сообщение отредактировал Spym - Nov 2 2010, 19:56
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 2 2010, 20:18
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Хм. Не вижу криминала.
Вспоминаю, что читал что-то такое про yagarto... Ага, нашёл:
Цитата
This is because codesourcery build newlib (c library) with
--disable-newlib-supplied-syscalls whereas yagarto builds the default
system calls.

Так что, если это правда, то в yagarto - никак. Берите CodeSourcery, или сборки от klen-а, если есть склонность к экспериментамsmile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 2 2010, 20:29
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Цитата(AHTOXA @ Nov 2 2010, 23:18) *
Так что, если это правда, то в yagarto - никак.

Цитата(AHTOXA @ Nov 2 2010, 22:52) *
Я пробовал переопределять
Код
int _write(int file, char *buffer, unsigned int count)

, работало.

То есть, вы не с yagarto эксперементировали.
Ок, благодарю за содействие, сейчас посмотрю, какие есть альтернативы.

upd:
Посмотрел Вашу ссылку:
Цитата
Also yagarto is a arm-elf toolchain, and the codesourcery is a arm-eabi
toolchain.

Это же неверное утверждение.

Кстати, тогда вопрос по Yagarto: как там определён стандартный ввод/вывод?

Сообщение отредактировал Spym - Nov 2 2010, 20:36
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 2 2010, 22:40
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Прикрутил вместо yagarto/arm-none-eabi сборку kgp-arm-eabi_x86_32_HALLOWEEN_EDITIION от Klen, результат тот же: stdout не перенаправляется.
Я озадачен.

Сообщение отредактировал Spym - Nov 2 2010, 22:41
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 3 2010, 05:55
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Меня немного смущает слово "перенаправляется". Что Вы имеете в виду? printf() выполняет вывод в поток stdout (при наличии перечисленных в документации системных вызовов, а именно, close, fstat, isatty, lseek, read, sbrk, write). Таким образом, перенаправление stdout - это просто присваивание ему другого значения. Может у Вас просто в stdout что-то не то?
Покажите, как Вы открываете поток, что присваиваете stdout...

Сообщение отредактировал alx2 - Nov 3 2010, 05:56


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 3 2010, 10:09
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Spym @ Nov 3 2010, 01:29) *
Цитата
Also yagarto is a arm-elf toolchain, and the codesourcery is a arm-eabi
toolchain.

Это же неверное утверждение.

Так год-то прошлый. Сейчас yagarto перешло на arm-eabi, да.

Цитата(Spym @ Nov 3 2010, 03:40) *
Прикрутил вместо yagarto/arm-none-eabi сборку kgp-arm-eabi_x86_32_HALLOWEEN_EDITIION от Klen, результат тот же: stdout не перенаправляется.


Очень странно. Посмотрите ещё вот в этой теме, я там приаттачивал тестовый проект с printf. Он для cortex-m3, но может поможет.

-----
Ещё мысль пришла. Если у вас C++ проект, то функции надо объявлять как
extern "C":

Код
extern "C" int _write(int file, char *buffer, unsigned int count)
{
    for (i=0; i<count; ++i) {
        lcd_put_char(*buffer++);
    }
    return count;
}


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 3 2010, 13:22
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Цитата(alx2 @ Nov 3 2010, 08:55) *
...перенаправление stdout - это просто присваивание ему другого значения. Может у Вас просто в stdout что-то не то?
Покажите, как Вы открываете поток, что присваиваете stdout...

stdout ничего не присваиваю, т.к. достаточно переопределить низкоуровневые функции, которые Вы уже перечислили, разве нет? При входе в main видно, что stdout уже существует (см. ниже).
Цитата(AHTOXA @ Nov 3 2010, 13:09) *
Очень странно. Посмотрите ещё вот в этой теме, я там приаттачивал тестовый проект с printf. Он для cortex-m3, но может поможет.

Посмотрел, принципиальных отличий не нашел.
Цитата(AHTOXA @ Nov 3 2010, 13:09) *
Ещё мысль пришла. Если у вас C++ проект, то функции надо объявлять как extern "C":

Эти функции определены в syscalls.c, всё в порядке.
Да, я забыл упомянуть, что при вызове printf управление всё же передавалось в:
Код
int _fstat_r(struct _reent *r, int file, struct stat *st);
int _isatty_r(struct _reent *r, int file);

Но вместо _write_r затем уходило в __swrite.

Попробовал сейчас перед вызовом printf() руками определить указатель на _write_r():
Код
stdout->_write = reinterpret_cast<typeof(stdout->_write)>(_write_r);

Пока я этого не сделал, stdout->_write указывал на NULL.
Вызвал printf(), смотрю значение stdout->_write - теперь указывает на __swrite.
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 3 2010, 14:53
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Я прозрел; как выяснилось, вывод корректно работает даже в Yagarto.

Из первого вызова printf вызывается __sinit, где происходит инициализация stdout/stdin/stderr. После этого stdout->_write указывает на __swrite, откуда как раз и происходит вызов _write_r, а отсюда, в свою очередь, вызывется пользовательский _write; но и _write_r можно переопределить.

Моя проблема заключалась в том, что вызов printf, где строка формата не содержит управляющих последовательностей:
Код
printf("Something string");

в newlib не приводит к выводу этой строки в stdout; после замены на:
Код
printf("%s", "Just string\r\n");

все ВНЕЗАПНО заработало.
Почему так? Ведь в этом случае в stdout должно было уйти "Something string".
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 3 2010, 18:01
Сообщение #12


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Spym @ Nov 3 2010, 19:53) *
Я прозрел; как выяснилось, вывод корректно работает даже в Yagarto.

Это радует, значит Yagarto потихоньку движется в сторону, так сказать, общепринятых тенденций. И eabi, и --disable-newlib-supplied-syscalls. Больше тулзов, хороших и разных! smile.gif
Цитата
Почему так?

Мне кажется, что это кривизна newlib. Хотя неясно, чем отличается _write из вашего файла syscalls.c от _write дефолтного.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
r301
сообщение Nov 3 2010, 18:37
Сообщение #13





Группа: Участник
Сообщений: 13
Регистрация: 20-10-07
Пользователь №: 31 533



Цитата(Spym @ Nov 3 2010, 17:53) *
Почему так? Ведь в этом случае в stdout должно было уйти "Something string".


обычная буферизация. попробуйте так
Код
printf("Something string");
fflush(stdout);

Go to the top of the page
 
+Quote Post
klen
сообщение Nov 3 2010, 19:00
Сообщение #14


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Цитата(Spym @ Nov 3 2010, 01:40) *
Прикрутил вместо yagarto/arm-none-eabi сборку kgp-arm-eabi_x86_32_HALLOWEEN_EDITIION от Klen, результат тот же: stdout не перенаправляется.
Я озадачен.

давайте прикрутим вместе. но после праздникрв пролетариата - я уже пикирую.
не думаю что есть проблемы где есть исходный код smile.gif

всех форумчан с празгиком, история нашего народа однако...
Go to the top of the page
 
+Quote Post
Spym
сообщение Nov 4 2010, 11:51
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 24-02-08
Из: Москва
Пользователь №: 35 348



Цитата(r301 @ Nov 3 2010, 21:37) *
обычная буферизация. попробуйте так
Код
printf("Something string");
fflush(stdout);

Действительно.
Интересно, как я могу управлять размером буфера?
И почему использование управляющих последовательностей не приводит к буферизации вывода?

Цитата(klen @ Nov 3 2010, 22:00) *
давайте прикрутим вместе.

В прикручивании как раз проблем не возникло - достаточно указать в PATH путь к toolchain же.
Да, кстати, при -O0 ваш KGP собрал 160кБ кода против 202кБ -O0 yagarto (-lc -lm -lgcc -lstdc++) при прочих равных, на первый взгляд всё работало. Хотя это сейчас мало о чем говорит, да и полученный код я не тестировал пока толком.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:17
Рейтинг@Mail.ru


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