| Форум РадиоКот https://radiokot.ru/forum/ |
|
| stm32 libc FILE https://radiokot.ru/forum/viewtopic.php?f=59&t=139954 |
Страница 1 из 1 |
| Автор: | _kp [ Вс дек 25, 2016 17:55:24 ] |
| Заголовок сообщения: | stm32 libc FILE |
Здравствуйте. Недавно занялся процессорами stm32, и вот, хочу поспрашивать про библиотеку LibC. Портирую проект с OrangePI(клон Raspberry), который ранее работал очень медленно и на AVR. В предыдущих версиях проектов я работал с TFT дисплеем, малельким дисплейчиком, устройствами i2c, uart и консолью через файлы. На Linux работать с файлами элементарно, и на AVR библиотека LIBC тоже это позволяла без проблем. А на stm32 этот момент как то плохо описан, максимум попадается "прибитие гвоздями" uart к printf. Хочется перенести код типа такого: СпойлерКод: //создаются файлы для работы с устройствами FILE *uart_stream; FILE *log_stream; FILE *lcd_info_stream; FILE *tft_console_stream; ... //есть фунукции работы с железом extern int uart0_putchar(char c, FILE *stream __attribute__ ((__unused__)) ); extern int tft_putchar(char c, FILE *stream __attribute__ ((__unused__)) ); extern int tft_console_putchar(char c, FILE *stream __attribute__ ((__unused__)) ); ... //связываем файловые потоки с "железом" (это пример для AVR, а на linux открываем с помощью fopen файлы устройств) uart_stream = fdevopen(uart0_putchar, uart0_getcharL); //send , receive functions tft_stream = fdevopen(tft_putchar, NULL); //send , receive functions tft_console_stream = fdevopen(tft_console_putchar, keyboard_getchar); //send , receive functions ... //далее работаем с разными устройствами. для примера, пусть будет libc.printf fprintf(log_stream,"some var=%6u",v); fprintf(tft_console_stream,"\e[31mText.."); //при работе с файлами на AVR приходится дополнительно связать структуру stdio.FILE со структурой "FILE" из библиотеки для работы с SD картой. На Lunux лишние действия не требуются. Рассмотрев библиотеку LIBC для STM32, в упор не заметил работающую структуру FILE. И не обнаружил примеров работающих с stdio.FILE. (Кроме примеров как жестко "повесить" printf на Uart через переопределение функции _write/putchar) А вот примеров создания нескольких потоков FILE для ввода/вывода не нашел. Да, можно сделать ветвление в функции _write, но точно я не буду мешать все устройства и файловые операции придачу в одной функции. Писать костыли под такую LIBC как то нет желания. Как бы не легче было другую libc прикрутить. Надеюсь, я просто чего то не заметил. Или эта задача делается на stm32 иначе. Подскажите как правильно делаются потоки ввода вывода на stm32. |
|
| Автор: | ARV [ Вс дек 25, 2016 19:27:09 ] |
| Заголовок сообщения: | Re: stm32 libc FILE |
так вроде бы потоки так и делаются, а вот файловая система - за вами. я боюсь ошибиться, но по-моему товарищ Чен давно эту проблему решил: http://elm-chan.org/fsw/ff/00index_e.html |
|
| Автор: | _kp [ Пн дек 26, 2016 17:02:12 ] |
| Заголовок сообщения: | Re: stm32 libc FILE |
Да, библиотеки товарища Чена рабочие, что то я даже использовал. Но проблему с потоками не решал, боле того он их не использовал вовсе. Обычно, имеющиеся у потока/файла функции чтения, записи и прочие, описаны или в самой структуре или сслылаются на другую структуру устройства(или на драйвер). Всё ,больше о работе с железом знать никому не надо, и библиотеке stdio особенно. В структуре FILE библиотеки LIBC определены поля _read, _write, но оно не работает, и ни примеров ни описаний. |
|
| Автор: | Shapa [ Ср дек 28, 2016 02:13:51 ] |
| Заголовок сообщения: | Re: stm32 libc FILE |
_kp писал(а): Да, можно сделать ветвление в функции _write, но точно я не буду мешать все устройства и файловые операции придачу в одной функции. Ну вот, ядро за вас делает а вы не хотите! Но write(fd) и read(fd) хотите. Не бывает так (UNIX: все есть файл) _kp писал(а): a В структуре FILE библиотеки LIBC определены поля _read, _write, но оно не работает, и ни примеров ни описаний. А что вы в примере ожидаете увидеть? Посмотрите на реализацию методов в ядре (linux kernel). Ничего там военного нет, вам нужно реализовать несколько syscall'ов. _open, _close, _seek, _write, _read, может быть _flush. и все. Пример с "прибиванием гвоздями printf" вполне релевантен. Он работает с одним fd (скорее всего в вашем в случае примеров что вы видели - тупо забивает на него), вам же нужно расширить поддержку до кастомных дескрипторов связанных с вашей FS. PS: fd - file descriptor, если вы не знаете что это, задача съест много вашего времени |
|
| Автор: | _kp [ Ср дек 28, 2016 05:16:46 ] |
| Заголовок сообщения: | Re: stm32 libc FILE |
Нашел как работать с потоками на stm32! Открытие потока со своими функциями делается функцией - fopencookie() Практически, расширенный аналог, того что на avr делала функция fdevopen() Когда разобрался, то и небольшое количество примеров нашлось, по ключевому слову fopencookie , а в стандартных примерах, почему то вовсе не упоминается столь важная функция. Итак, решение: //Создаём функции обычного блочного чтения/записи для работы с железом, но тип аргументов должен совпадать с требуемым в stdio.h //В параметре _cookie можно передать произвольный аргумент, например для однотипных функций, работающих с разным железом (я не использую) ssize_t uart1_write( void *_cookie, const char *buffer, size_t length); ssize_t uart1_read(void *_cookie, char *buffer, size_t length); ssize_t tft_write( void *_cookie, const char *buffer, size_t length); ssize_t tft_cons_write( void *_cookie, const char *buffer, size_t length); ssize_t tft_cons_read( void *_cookie, char *buffer, size_t length); //Теперь главное //Объявляем файловые потоки и связываеи их с железом uart1_init(); //Инициализируем железо перед чтением/записью FILE f_uart1 = fopencookie( NULL, "rw+", (cookie_io_functions_t){ uart1_read, uart1_write, NULL, NULL } ); //создаём поток setvbuf(f_uart1 , NULL, _IONBF, 0); //отключем буферизацию (если требуется) tft_init(); FILE f_tft = fopencookie( NULL, "w+", (cookie_io_functions_t){ NULL, tft_write , NULL, NULL } ); //только режим записи setvbuf(f_tft , NULL, _IONBF, 0); tft_console_init(); FILE f_tft_console = fopencookie( NULL, "rw+", (cookie_io_functions_t){ tft_cons_read, tft_cons_write, NULL, NULL } ); //Готово. Можно использовать откуда угодно через потоки. fputs(f_uart1 ,"Text to uart"); fputs(f_tft,"Text to console"); fprintf(tft_console,"\e[%u;%uH\e[%sm%s",y,x,dattr,str ); Примечание. C помощью setvbuf() можно отключить буферизацию на уровне библиотеки stdio. Та буферизация не альтернатива буферизции с помощью DMA/прерываний, а для многопоточного кода. Кроме того, она абсолютно вредна для нетекстовых данных, и быстодействияя не прибавляет, и даже наооборот уменьшает. Но она полезна при записи в один поток данных из многопоточного кода(и только многопоточного), например ведение лог-файла, и при использовании буферизации данные будут смешаны не побайтно, а постройно, то есть будут читаемы. ps: Потоки хороши тем, что их можно перенаправить, в отличие от жестких функций работы с железом. |
|
| Автор: | Golum [ Ср мар 25, 2020 07:24:37 ] |
| Заголовок сообщения: | как работать с потоками на stm32, рабочий пример |
#include <stdio.h> ssize_t myWrite(void *cookie, const char *buf, size_t n) // wrapper function { return Serial.write((uint8_t*)buf, n); } cookie_io_functions_t myVectors = { 0, myWrite, 0, 0 }; FILE *myOut; void setup() { Serial.begin(9600); myOut = fopencookie((void *)(&Serial), "w", myVectors); setlinebuf(myOut); fprintf(myOut, "This is an fprintf demo\n"); } void loop(void) { fprintf(myOut,"frintf\n\r"); delay(3000); } |
|
| Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


