repstosw 18 6 октября, 2023 Опубликовано 6 октября, 2023 · Жалоба 1 hour ago, sasamy said: не видел чтобы он использовался Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 октября, 2023 Опубликовано 7 октября, 2023 (изменено) · Жалоба Собрал наконец-то самостоятельно полностью newlib для ABI=call0 с поддержкой printf с floating point. Очень было нужно. За основу брал всё тот-же небезызвестный newlib-esp32, которой использовал японец при построении тулчейна с помощью crosstool-ng. В винде не получилось сделать Makefile, потому что MSYS на базе MinGW не очень любит сторонние таргеты. И намертво прибитый гвоздями к окружению Винды и MinGW он не давал корректного мейкфайла для xtensa. Тема: https://electronix.ru/forum/index.php?/topic/173554-configureautoconf-хост-win32-таргет-xtensa/ Пришлось всё сделать в Линуксе. Там всё оказалось намного проще. Но есть две проблемы с исходниками. Первая здесь: https://github.com/espressif/newlib-esp32/blob/esp_based_on_4_1_0/newlib/libc/include/ieeefp.h#L152 Вылетала ошибка, в итоге плюнул и жёстко задал такую конфигурацию: #define LDBL_MANT_DIG 53 #define EXT_EXPBITS 11 #define EXT_FRACHBITS 20 #define EXT_FRACLBITS 32 #define __ieee_ext_field_type unsigned long Не знаю, насколько она правильна для компилятора и архитектуры xtensa. Вторая здесь: https://github.com/espressif/newlib-esp32/blob/esp_based_on_4_1_0/libgloss/libnosys/pthread.c#L30 Компилятору не понравилось, что параметру функции не задали имя, а указали всего-лишь его тип. И там таких ошибок много. Непонятно, как эти треды затесались в билд, при построении использовал флаг - без тредов(об этом ниже) . И не понятно как они С-компилятор заставили это компилить. Какой ключ у Си есть чтобы это компилировать без ошибки? Пришлось скомпилировать этот исходник С++, который переваривает параметры без имён, не забыв добавить в начало: #ifdef __cplusplus extern "C" { #endif и в конец файла: #ifdef __cplusplus } #endif Иначе С++ создаст манглированные имена, которые не увидит С. Флаги для конфигурации использовал такие: ./configure \ --with-newlib \ --enable-newlib-reent-small \ --enable-newlib-io-pos-args \ --enable-newlib-io-c99-formats \ --enable-newlib-io-long-long \ --enable-newlib-io-long-double \ --enable-newlib-io-float \ --disable-multilib \ --disable-newlib-multithread \ --disable-newlib-reent-check-verify \ --disable-newlib-supplied-syscalls \ --disable-newlib-nano-formatted-io \ --disable-newlib-mb \ --disable-newlib-atexit-dynamic-alloc \ --disable-option-checking \ --program-transform-name="s&^&xtensa-hifi4-elf-&" \ --with-target-subdir=xtensa-hifi4-elf \ --target=xtensa-hifi4-elf Тоесть выкинул нафиг треды, проверку на повторное вхождение (мне оно не нужно). А НАНО-опции отключил, потому что с ними printf не печатает float. А мульти-байты напротив - не нужны. В итоге вылепил - конфету. Чему я собственно и рад! P.S. Ещё попутно нарвался на то, что если обработчик прерывания написан на С++, а используется в сишном или ассемблерном сорце, то используется дефолтный обработчик -функция с атрибутом weak. Тоесть - другой обработчик, который пустой ))) Добавил к С++ функции обработчика exten "C" и оно заработало как надо по вполне очевидным причинам (манглирование имён в С++). Изменено 7 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 7 октября, 2023 Опубликовано 7 октября, 2023 · Жалоба Игнорировать отсутствие имён параметров фуекци это кажется плюсовая фича... по мне в си коое не должно жить. Про парамеиры плавучки. Раз это сопррцессор арму то походе должен формат с тем что арм ядрах Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 189 7 октября, 2023 Опубликовано 7 октября, 2023 · Жалоба 24 минуты назад, GenaSPB сказал: Игнорировать отсутствие имён параметров фуекци это кажется плюсовая фича... по мне в си коое не должно жить. Нет, не плюсовая. В прототипах функций что в Си, что в C++ могут отсутствовать имена параметров, компилятору они не нужны. P.S. Перешел по ссылке. Да, в сишном файле в определении функции не задано имя. Программисту оторвать руки Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 октября, 2023 Опубликовано 7 октября, 2023 (изменено) · Жалоба 12 minutes ago, Arlleex said: В прототипах функций что в Си, что в C++ могут отсутствовать имена параметров, компилятору они не нужны. В моём случае это не прототипы. А функции с телами. Надо попробовать -std=gnu99. Про то, что в прототипах можно указывать типы без имён - знаю. Это вполне логично. Ну они могли бы пойти и дальше - разрешить указывать параметры без имен, если они не используются. Например если это заглушки. Хотя это будет нагрузка на стек. Или лишние присвоения регистров. Зависит от конвенции передачи параметров. Изменено 7 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 октября, 2023 Опубликовано 7 октября, 2023 (изменено) · Жалоба 42 minutes ago, GenaSPB said: Про парамеиры плавучки. Раз это сопррцессор арму то походе должен формат с тем что арм ядрах Сравнил со встроенными дефайнами тулчейна: echo | %TOOLCHAIN%gcc -dM -E - > output.txt #define __FLT32X_MANT_DIG__ 53 #define __FLT64_MANT_DIG__ 53 #define __FLT_MANT_DIG__ 24 #define __FLT32_MANT_DIG__ 24 #define __LDBL_MANT_DIG__ 53 #define __DBL_MANT_DIG__ 53 #define __SIZEOF_LONG_DOUBLE__ 8 #define __SIZEOF_DOUBLE__ 8 Вроде выбрал опции в ieeefp.h правильно. Как я понял, чудес на этой архитектуре ждать не приходится : LONG DOUBLE = DOUBLE. У обоих мантисса 53 бита, а общая длина 64 бита(8 байт). Изменено 7 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 октября, 2023 Опубликовано 7 октября, 2023 · Жалоба 49 minutes ago, repstosw said: В моём случае это не прототипы. А функции с телами. Надо попробовать -std=gnu99. Не помогло. make[3]: Entering directory `/c/newlib-esp32/xtensa-hifi4-elf/libgloss/libnosys' xtensa-hifi4-elf-cc -B/c/newlib-esp32/xtensa-hifi4-elf/newlib/ -isystem /c/newlib-esp32/xtensa-hifi4-elf/newlib/targ-include \ -isystem /c/newlib-esp32/newlib/libc/include -B/c/newlib-esp32/xtensa-hifi4-elf/libgloss/xtensa \ -L/c/newlib-esp32/xtensa-hifi4-elf/libgloss/libnosys -L/c/newlib-esp32/libgloss/xtensa \ -g -O2 -std=gnu99 -O2 -I. -I../../.././libgloss/libnosys/.. -c -g -O2 -std=gnu99 ../../.././libgloss/libnosys/pthread.c И всё-же - как это переварить С ? Интересно...🤣 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 7 октября, 2023 Опубликовано 7 октября, 2023 (изменено) · Жалоба Его наверное собирали g++. Забей. Поправьте нормалтно. Я еще встречал в линукс драйверах как забывают писать struct при использовании типов. А это уже точно не расширения. Это с++ . Изменено 7 октября, 2023 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 189 7 октября, 2023 Опубликовано 7 октября, 2023 · Жалоба По уму, так, переписать надо (поправить). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба Сделал замену функции printf. Ранее использовался вариадический макрос, что вызывало определённые неудобства: нужно было постоянно инклудить хедер с этим макросом в каждый файл, где используется printf. Реализация printf: void UART_putc(u8 c) { while(!(UART_LSR&(1<<6))); UART_THR=c; } void UART_puts(const char *s) { while(*s) { if(*s=='\n')UART_putc('\r'); UART_putc(*s++); } } #include <stdio.h> #include <stdarg.h> #include "UART.h" #define PRINTF_BUFFER_SIZE 256 static char printf_buffer[PRINTF_BUFFER_SIZE]; int puts(const char *s) { UART_puts(s); UART_putc('\r'); return '\n'; } int printf(const char *format,...) { memset(printf_buffer,0,PRINTF_BUFFER_SIZE); //? можно убрать va_list args; va_start(args,format); int r=vsprintf(printf_buffer,format,args)-1; //на 1 меньше, так как символ конца строки(=0) не считается в printf va_end(args); UART_puts(printf_buffer); return r; } Дополнительно объявлена замена функции puts, потому что при сильной оптимизации компилятор вместо вывозва printf подсовывает puts - в случаях, когда указана просто одна строка: printf("\nHiFi4 DSP...\n\n"); puts можно исключить, добавив флаг компиляции: -fno-builtin-printf. Тупо замена функции _write( ), как это делается в STM'ах или ARM'ах - тут не прокатывает. Потому что newlib взята от самого IBM, а они любят усложнизмы. Там куча проверок на реентабельность и завязано всё на файловый ввод-вывод. Тест: printf("\nHiFi4 DSP...\n\n"); long double x=2.01234567890123456789012345678901234567890123456789; double y=2.01234567890123456789012345678901234567890123456789; float z=2.01234567890123456789012345678901234567890123456789; printf("%1.50Lf\n",x); printf("%1.50lf\n",y); printf("%1.50f\n\n",z); unsigned long long temp=0x123456789ABCDEF0; printf("temp=0x%llX\n",temp); Выход: HiFi4 DSP... 2.01234567890123461353368838899768888950347900390625 2.01234567890123461353368838899768888950347900390625 2.01234579086303710937500000000000000000000000000000 temp=0x123456789ABCDEF0 Изменено 8 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба Возвращаемся значение что у printf, что у vsprintf одинаковый смысл имеют. Зы: откройте для себя vsnprintf Кстати в стандарте говорится о том что эффект от переопределения у себя функций стандартный библиотеки может вам удивить... Сделайте себе UART_printf и нет даже потенциальных проблем... Изменено 8 октября, 2023 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба 1 hour ago, GenaSPB said: Возвращаемся значение что у printf, что у vsprintf одинаковый смысл имеют. Здесь почему-то сказано, что vsprintf возвращает число символов включая завершающий ноль: https://vsokovikov.narod.ru/New_MSDN_API/Add_func_runtime_C/fn_vsprintf.htm Quote Функции vsprintf and vswprintf возвращают число записанных символов, включая символ завершающего нуля, или отрицательное значение, если происходит ошибка при выводе. Хотя другие источники говорят, что без завершающего. 1 hour ago, GenaSPB said: Зы: откройте для себя vsnprintf Чем он лучше, чем vsprintf ? Более стандартизирован возвращаемому значению числа выведенных символов не включая \0 ? 1 hour ago, GenaSPB said: Кстати в стандарте говорится о том что эффект от переопределения у себя функций стандартный библиотеки может вам удивить... Перекомпилировал все проекты, где есть много вызовов printf в разных файлах. Подвоха не заметил. И почему сделан упор на "стандартную" библиотеку? В чём её стандартность заключается? Она никуда не прибита намертво, и она пересобирается. Так что не знаю на счёт стандартности, по мне - обычная библиотека, как и все другие. 1 hour ago, GenaSPB said: Сделайте себе UART_printf и нет даже потенциальных проблем... Вы предлагаете переправлять в нескольких десятках файлов чужих исходников printf на UART_printf ? Переопределение printf как раз было задумано, чтобы вызовы printf не приводили к зависаниям, а программисту - не переправлять тонны исходников. Изменено 8 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба 31 minutes ago, repstosw said: Чем он лучше, чем vsprintf ? Более стандартизирован возвращаемому значению числа выведенных символов не включая \0 ? Да. Лучше. Стандартизировано возвращаемое значение. И безопаснее. Позволяет заранее узнать размер строки и выделить динамически память под строку. Так как использую GCC с разрешением VLA, то вместо malloc/free можно использовать VLA. Код printf теперь такой: int printf(const char *format,...) { va_list args; va_start(args,format); size_t n=vsnprintf(NULL,0,format,args)+1; //+1 for the '\0' char buf[n]; int r=vsnprintf(buf,n,format,args); va_end(args); UART_puts(buf); return r; } Помогло понять вот это: https://stackoverflow.com/questions/7315936/which-of-sprintf-snprintf-is-more-secure Изменено 8 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба Нет отличий. Обращайтесь к первоисточник. C99 Изменено 8 октября, 2023 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 53 8 октября, 2023 Опубликовано 8 октября, 2023 (изменено) · Жалоба 4 часа назад, repstosw сказал: Переопределение printf как раз было задумано, чтобы вызовы printf не приводили к зависаниям, а программисту - не переправлять тонны исходников. Честно говоря уже с незапамятных времен использую собственный printf, он гораздо компактнее, да и чтоб не зависеть от различных его реализаций и от этого тем более... 3 часа назад, repstosw сказал: выделить динамически память под строку. Изменено 8 октября, 2023 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться