-
- Прочти этого Aвтора в интересующем разделе bnb62(1 знак., 01.05.2024 04:59, ссылка)
- Спасибо, отличный автор! Жаль что прекратил выпуск статей. - Mty1(02.05.2024 16:21)
- Внимание, опрос! IBAH(42 знак., 30.04.2024 21:24, ссылка, картинка)
- Не хватает пункта: HAL, но не "принципиально", а по пути наименьшего сопротивления и якобы временно. - Argon(30.04.2024 23:27)
- У меня таймеры/ UART/ GPIO все в LL HAL. Удобнее на мой взгляд. - A.L.(28.04.2024 21:22)
- У чом промблемма? Референс мануал:регистер дескрипшен: mse homjak(1062 знак., 28.04.2024 19:58)
- Это не STM32 регистры. Это китаёзный RISC-V - RxTx(29.04.2024 22:14)
- Он цэльнотянутый с СТМ. - mse homjak(29.04.2024 22:20)
- Спасибо большое! - Mty1(29.04.2024 00:18)
- Позанудничаю. "USART2->CTLR2 =(uint16_t)0;",
"tmp!=(uint8_t)0x0d", "USART2->BRR =
(uint16_t)baudesRate115200;". Вот эти явные приведения типа ничего,
кроме незнания, как работает язык Си, не показывают. SciFi(233 знак., 28.04.2024 20:20)
- Это, чтобы он мне варнингов не накидывал. Причом, иногда
накидывает, иногда, нет. Потому, так. - mse homjak(28.04.2024 20:39)
- Как "USART2->CTLR2 =(uint16_t)0;" может накидать варнингов?
Поднимите мне веки. - SciFi(28.04.2024 21:22)
- Это не STM32. Китайцы там могли нахуеверить чего угодно. Объявление регистра идет с volatile. Вариант II: что-то либо с адресом, либо специфический RISC-V warn. Но всё это гадание, лучше mse пусть скопипастит что за варниг и также свою строку компилера что там понавключал. - RxTx(29.04.2024 22:19)
- А тут ужэ работает копипаста. Потом два щелчка мышей, пишем букву, два щелчка, и идёт поцказка после "->". Не ругаеца, так и % с ним. - mse homjak(28.04.2024 23:34)
- Как "USART2->CTLR2 =(uint16_t)0;" может накидать варнингов?
Поднимите мне веки. - SciFi(28.04.2024 21:22)
- Ты просто не постиг всей глубины компиляторостроения. Так делают,
чтобы код гарантированно собирался любыми компиляторами, с любыми
ключами и любыми оптимизациями. Nikolay_Po(190 знак., 28.04.2024 20:36)
- Нет. Просто компилер ругается что хз как его представлять. Был
момент, когда он ругался на 16р переменную, в которую грузил другую
16р переменную указателем на 16р переменную. - mse homjak(28.04.2024 20:50)
- Не верю. Без улик нещитово. - SciFi(28.04.2024 21:24)
- Тю... Включи все предупреждения, какие только есть у компилятора.
Возьми указатель на переменную volatile uint_16t и попробуй
присвоить переменной uint16_t значение по указателю на первую. - Nikolay_Po(28.04.2024 21:51)
- А указатель какого типа, ЫЫyкпy(116 знак., 29.04.2024 07:46)
- А вы и так, и так попробуйте. Всё одно спросит, там или там. - Nikolay_Po(29.04.2024 13:54)
- А указатель какого типа, ЫЫyкпy(116 знак., 29.04.2024 07:46)
- Тю... Включи все предупреждения, какие только есть у компилятора.
Возьми указатель на переменную volatile uint_16t и попробуй
присвоить переменной uint16_t значение по указателю на первую. - Nikolay_Po(28.04.2024 21:51)
- Не верю. Без улик нещитово. - SciFi(28.04.2024 21:24)
- Нет. Просто компилер ругается что хз как его представлять. Был
момент, когда он ругался на 16р переменную, в которую грузил другую
16р переменную указателем на 16р переменную. - mse homjak(28.04.2024 20:50)
- Это, чтобы он мне варнингов не накидывал. Причом, иногда
накидывает, иногда, нет. Потому, так. - mse homjak(28.04.2024 20:39)
- Это не STM32 регистры. Это китаёзный RISC-V - RxTx(29.04.2024 22:14)
- ??? Как это? Почему у меня везде любое количество байт из буфера
уходит командой HAL_UART_Transmit_IT()? От 2 байт до 1280. Иногда
можно и DMA, когда масса других прерываний. - Лaгyнoв(28.04.2024 18:08)
- Ну я имел в виду, что если на передачу делать буференный вывод
через очередь freertos или кольцевой буфер, то надо сначала из
printf передавать в переписанный fputc(), а потом по 1 байту
вынимать из очереди и передавать в HAL_UART_Transmit_IT(). Или по
другому можно -- в отдельной задаче из очереди класть в буфер
передачи, а потом разом передавать в HAL_UART_Transmit_IT или в DMA
transmit - Mty1(28.04.2024 18:32)
- ужас какой. Хорошо, что я всего этого не знаю. :-) - Лaгyнoв(28.04.2024 19:35)
- Ну в принципе так, только можно оптимизировать уже внутри самой инфраструктуры printf. Для GCC инфраструктуры это перекрыв _write() , по умолчанию объявленную в syscalls.c. Юзать вместо _IT функции _DMA ничто не мешает. Равно как и писать напрямую в регистры DMA... - RxTx(28.04.2024 18:37)
- пока искал, что это за функция, нашел примеры, где её насилуют
постоянными вызовами. наверно оттуда и ноги растут - Vit(28.04.2024 18:26)
- У ST правило именования всех функций (DMA, SPI, I2C, Timers и так
далее) : 1. Софтварный поллинг (функция не выйдет, пока не
отработает): Просто название функции. 2. Через прерывание: дописано
_IT. 3. Через DMA: дописано _DMA. - RxTx(28.04.2024 18:33)
- Ну дык у ТС об _IT. Лагунов вот и удивляется, нахрена по байту пихать. - Vit(28.04.2024 18:46)
- Я понимаю о чем ты и сам так не пишу. Но. HAL_UART_Transmit_IT()
работает совершенно спокойно для передачи по 1 байту и будет так
работать без всяких сбоев. Конечно перегружая проц лишним
оверхедом. Я наталкивался где-то на подобное извращение. - RxTx(28.04.2024 19:02)
- то понятно. ТС когда сдался насчет printf и попыток навернуть непонятный буфер из очередей для fputc, стало грустно, потому как даже DMA не сильно в таком помогает, ибо опять нужен линейный вход (буфер) и/или ожидание. там скорее вопрос нужно задавать о возможности выделить буфер достаточного размера - Vit(28.04.2024 19:41)
- Коллега еще увлекается таким: он вызывает исходные функции
HAL_UART_Transmit_IT() / HAL_UART_Receive_IT() и проч. Но прям
внутри HAL функций прерываний (файлик stm32??xx_it.c) он всегда пишет свой примитивный код:
читает или пишет прямиком из UART регистра. Это работает. Но я
крайне советую обязательно обслуживать ошибки UART, потому что
ошибка UART будучи необработанной так и остается висеть и причиняет
прерывание снова и снова. - RxTx(28.04.2024 19:13)
- А вот тут вы, батенька, неправы... Прерывание общее для TDBE/RDBF
(и ошибок, если включено). Соответственно, чтение регистра
состояния в прерывании обязательно, для правильной обработки. А при
чтении данных после чтения регистра состояния, все ошибки
сбрасываются аппаратно... Idler(171 знак., 28.04.2024 20:19)
- Скажите, а причем TDBE и RDBF? Причем тут внезапно Artery? ТС использует STM32 RxTx(216 знак., 28.04.2024 20:57)
- А вот тут вы, батенька, неправы... Прерывание общее для TDBE/RDBF
(и ошибок, если включено). Соответственно, чтение регистра
состояния в прерывании обязательно, для правильной обработки. А при
чтении данных после чтения регистра состояния, все ошибки
сбрасываются аппаратно... Idler(171 знак., 28.04.2024 20:19)
- Я понимаю о чем ты и сам так не пишу. Но. HAL_UART_Transmit_IT()
работает совершенно спокойно для передачи по 1 байту и будет так
работать без всяких сбоев. Конечно перегружая проц лишним
оверхедом. Я наталкивался где-то на подобное извращение. - RxTx(28.04.2024 19:02)
- Ну дык у ТС об _IT. Лагунов вот и удивляется, нахрена по байту пихать. - Vit(28.04.2024 18:46)
- У ST правило именования всех функций (DMA, SPI, I2C, Timers и так
далее) : 1. Софтварный поллинг (функция не выйдет, пока не
отработает): Просто название функции. 2. Через прерывание: дописано
_IT. 3. Через DMA: дописано _DMA. - RxTx(28.04.2024 18:33)
- Ну я имел в виду, что если на передачу делать буференный вывод
через очередь freertos или кольцевой буфер, то надо сначала из
printf передавать в переписанный fputc(), а потом по 1 байту
вынимать из очереди и передавать в HAL_UART_Transmit_IT(). Или по
другому можно -- в отдельной задаче из очереди класть в буфер
передачи, а потом разом передавать в HAL_UART_Transmit_IT или в DMA
transmit - Mty1(28.04.2024 18:32)
- Там же ж где-то может быть HAL_UART_GetState(&huart_n); Vit(693 знак., 28.04.2024 17:59)
- DMA - RxTx(28.04.2024 17:40)
- Для передачи точно DMA удобнее. Для приёма - зависит от протокола и
нагрузки. Я чисто на прерываниях прием делал, два прерывания - одно
UART, прием/передача/ошибки, другое - таймер - временные параметры
протокола. Обеспечиваю предварительное занятие линии RS-485, так,
чтобы передача первого старта шла уже после некоторого времени в
активном состоянии драйвера - чтобы сбросить межкадровые помехи,
если были на "пустой" линии. Nikolay_Po(188 знак., 28.04.2024 17:53)
- Спасибо, Коль, за объяснение, всегда приятно тебя читать. Да, DMA
это достаточно несложно, автора видать отпугивает непонятность
реализации. А реализовать его проще всего "поженив" с программным
циркулярным буфером. Тогда "пишущий" в буфер указатель (или лучше
index) будет программный. "Заворачивается" он банальным AND, т.е.
&= . А читающий указатель (или index) выполняется на DMA с тем
нюансом что надо будет обслужить "заворот". - RxTx(28.04.2024 18:05)
- Вот, например: SciFi(3191 знак., 28.04.2024 18:38)
- Хорошо написано. На передачу, я, когда не было риска изменений данных на стороне источника, контроллеру ПДП, вообще передавал ссылку на данные. Не оформляя отдельного буфера передачи, но формируя очередь запросов с указателями на данные и размер. Для передачи кадра данных известного размера, ПДП подходит идеально. - Nikolay_Po(28.04.2024 22:04)
- Так-то всё красиво, да. Но зачем плодить указатели на структуры, я не понял. Все уарты и все каналы dma (которые есть в конкретном процессоре) определены там же, где USART_TypeDef и DMA_Channel_TypeDef. Если он не определён, не сработает инициализация, а если определён - зачем делать свой? Я всю сознательную жизнь просто дефайнил, типа #define PRINT_UART USART1 и т.д. - Idler(28.04.2024 21:17)
- Я видел раньше и когда писал, думал "Нет тут SciFi". Да, очень чистенький код. Идеально я бы сказал. - RxTx(28.04.2024 18:48)
- Да, DMA вариант мне все больше нравится. Тем более вывод у меня
будет через printf строками. Как раз задача для DMA. Можно даже с
Doube Buffer Mode попробовать поиграть. Немножко странно конечно у
меня будет - прием по IRQ а отправка в DMA :) - Mty1(28.04.2024 18:37)
- Как по мне, УАРТ не то место, где ДМА необходим. Понимаю, если надо принимать плотный поток от АЦП, или отправлять что-то много и быстро. Но УАРТ, по нынешним временам, не тот случай. ДМА может сократить кол-во срабатываний прерываний, тем сократив среднюю нагрузку по производительности, но производительности обычно и так навалом. Другое дело длительность прерывания. mr-x(323 знак., 29.04.2024 12:26)
- Почему "странно", это вполне нормально, если входной поток нужно на ходу разгребать. Ну, например, выделить из него команду, адрес и дальнейший поток писать куда надо. А передача - "fire & forget", пусть принимающий думает... - Idler(28.04.2024 21:25)
- В старых STM32 UART примитивный и в отличии даже от древних dsPIC30 начала 2000х не имеет FIFO буфера. Что приводит к тому что прерывания будут дубасить на каждый байт. Тогда даже медленный по нынышним временам 115200 это 115200/10 ( к 8 битам байта еще 1 стартовый и 1 стоповый бит) = 11 520 = 11,5 килогерц. И это только один канал. - RxTx(28.04.2024 18:47)
- Вот, например: SciFi(3191 знак., 28.04.2024 18:38)
- Спасибо, Коль, за объяснение, всегда приятно тебя читать. Да, DMA
это достаточно несложно, автора видать отпугивает непонятность
реализации. А реализовать его проще всего "поженив" с программным
циркулярным буфером. Тогда "пишущий" в буфер указатель (или лучше
index) будет программный. "Заворачивается" он банальным AND, т.е.
&= . А читающий указатель (или index) выполняется на DMA с тем
нюансом что надо будет обслужить "заворот". - RxTx(28.04.2024 18:05)
- Для передачи точно DMA удобнее. Для приёма - зависит от протокола и
нагрузки. Я чисто на прерываниях прием делал, два прерывания - одно
UART, прием/передача/ошибки, другое - таймер - временные параметры
протокола. Обеспечиваю предварительное занятие линии RS-485, так,
чтобы передача первого старта шла уже после некоторого времени в
активном состоянии драйвера - чтобы сбросить межкадровые помехи,
если были на "пустой" линии. Nikolay_Po(188 знак., 28.04.2024 17:53)
- Ты же в курсе, что можно переключить драйвер на LL? А это "на
регистрах" и есть. - RxTx(28.04.2024 17:39)
- А, спасибо. Надо попробовать. Видать пора на LL переезжать. - Mty1(28.04.2024 17:42)
- Делал обработчик в прерывании. На регистрах. Что-то конкретное
интересует? - Nikolay_Po(28.04.2024 17:35)
- Да, код обработчика если можно. Кстати обработку RTS/CTS нужно
руками делать по заполнению буфера, или железо само делает? - Mty1(28.04.2024 17:44)
- А код обработчика - у UART сразу забираю данные из регистров статуса и данных. ASAP. А потом конечный автомат из switch() и состояний протокола обмена. У таймера тоже switch() и конечный автомат. - Nikolay_Po(28.04.2024 22:37)
- RTS/CTS, если это не RS-232, а управление драйверами линии, то только по таймеру. Для управления драйвером непригодны. На высоких скоростях нет возможности включать драйвер заблаговременно, до стартового бита. Errata ещё, да в малых корпусах не выведено. В общем, у меня с RTS/CTS не срослось, ни разу, кроме atSAM какого-то, когда на 1.5Мбит/с непрерывный поток данных с/на ПК гонял. Тогда контроль потоком RTS/CTS пригодился и работал. - Nikolay_Po(28.04.2024 22:32)
- Да, код обработчика если можно. Кстати обработку RTS/CTS нужно
руками делать по заполнению буфера, или железо само делает? - Mty1(28.04.2024 17:44)
- Прочти этого Aвтора в интересующем разделе bnb62(1 знак., 01.05.2024 04:59, ссылка)