Перейти к содержанию
    

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

 

Разбираюсь с 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ключи линкера:

LIBS = -lstdc++ -lc -lgcc -lm
LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref $(LIBS) -T$(TARGET).ld

 

Покажите $(TARGET).ld чтоль:)

Я пробовал переопределять

int _write(int file, char *buffer, unsigned int count)

, работало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Покажите $(TARGET).ld чтоль:)

Запросто.

gcc_freertos_test.ld.txt

Изменено пользователем Spym

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хм. Не вижу криминала.

Вспоминаю, что читал что-то такое про yagarto... Ага, нашёл:

This is because codesourcery build newlib (c library) with

--disable-newlib-supplied-syscalls whereas yagarto builds the default

system calls.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так что, если это правда, то в yagarto - никак.

Я пробовал переопределять

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Я озадачен.

Изменено пользователем Spym

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Покажите, как Вы открываете поток, что присваиваете stdout...

Изменено пользователем alx2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Also yagarto is a arm-elf toolchain, and the codesourcery is a arm-eabi

toolchain.

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

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

 

Прикрутил вместо 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;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...перенаправление stdout - это просто присваивание ему другого значения. Может у Вас просто в stdout что-то не то?

Покажите, как Вы открываете поток, что присваиваете stdout...

stdout ничего не присваиваю, т.к. достаточно переопределить низкоуровневые функции, которые Вы уже перечислили, разве нет? При входе в main видно, что stdout уже существует (см. ниже).

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

Посмотрел, принципиальных отличий не нашел.

Ещё мысль пришла. Если у вас 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я прозрел; как выяснилось, вывод корректно работает даже в 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".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Почему так?

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему так? Ведь в этом случае в stdout должно было уйти "Something string".

 

обычная буферизация. попробуйте так

printf("Something string");
fflush(stdout);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Я озадачен.

давайте прикрутим вместе. но после праздникрв пролетариата - я уже пикирую.

не думаю что есть проблемы где есть исходный код :)

 

всех форумчан с празгиком, история нашего народа однако...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

обычная буферизация. попробуйте так

printf("Something string");
fflush(stdout);

Действительно.

Интересно, как я могу управлять размером буфера?

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

 

давайте прикрутим вместе.

В прикручивании как раз проблем не возникло - достаточно указать в PATH путь к toolchain же.

Да, кстати, при -O0 ваш KGP собрал 160кБ кода против 202кБ -O0 yagarto (-lc -lm -lgcc -lstdc++) при прочих равных, на первый взгляд всё работало. Хотя это сейчас мало о чем говорит, да и полученный код я не тестировал пока толком.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...