Jump to content

    

jcxz

Свой
  • Content Count

    10012
  • Joined

  • Last visited

Community Reputation

0 Обычный

3 Followers

About jcxz

  • Rank
    Гуру
  • Birthday 12/01/1974

Контакты

  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

19101 profile views
  1. Для надёжности можете в периодическом прерывании, обнаружив изменение NDTR от предыдущего состояния, брать не всю величину изменения, а без последнего символа (брать NDTR+1). И только если между двумя периодическими ISR NDTR не изменился - принимать теперь уже NDTR как есть. Если период периодического прерывания == 1мсек, то за 1 мсек символ всяко должен слиться в ОЗУ.
  2. Мой драйвер UART для STM32F4 работает немного по-другому. Не в циклическом, а в режиме двойного буфера. У меня весь буфер состоит из N частей по UART_RDMA_CHUNK байт каждая. Я запускаю DMA для текущей части размером UART_RDMA_CHUNK, и также прописываю указатель на следующий кусочек UART_RDMA_CHUNK. В прерывании завершения предыдущего кусочка, спокойно перемещаю указатель записи и вычисляю оставшийся свободный размер и положение следующего сегмента UART_RDMA_CHUNK в буфере (и есть ли он). В это время поток продолжает приниматься. Поэтому ничего не может переполниться или перепрыгнуть. Переполнение буфера обнаруживается и обслуживается корректно (при необходимости запускаю DMA для очередного UART_RDMA_CHUNK не в основной буфер, а в отдельную "мусорку"). Не знаю. Не наблюдал такого. Мой драйвер работает с DMDIS=0 для приёмного потока. И при этом - всё ок. В проекте 3 UART. Все работают с DMA на приём и передачу (на передачу DMDIS=1). Все могут работать одновременно. Один из UART-ов работает на 1843200 бод (подключен ESP8266). Девайс работает давно уже (не первый год), каждый день по многу часов, иногда и сутки напролёт. Проблем не замечал. Хотя возможно, что они просто не проявляются. Так как NDTR обрабатывается и указатель по нему двигается в ISR, а символы из очереди читаются уже в задаче ОС (в ISR - нет). К тому моменту когда выполнение доходит до задачи, символы вполне могут успеть записаться в ОЗУ (из FIFO DMA).
  3. Спасибо! Будет время - почитаю. Пока забабахал макрос Ньютоном-Рафсоном: #define SQRT_ITER(x, y) (y * (1.5f - y * y * x)) #define SQRT(x) ((x) * \ SQRT_ITER((x) * .5, \ SQRT_ITER((x) * .5, \ SQRT_ITER((x) * .5, \ SQRT_ITER((x) * .5, \ SQRT_ITER((x) * .5, \ SQRT_ITER((x) * .5, (((x) - 1.) / 2 + 1)))))))) 6 итераций: на диапазоне x=0.6...1.4 получаю точность = 30+ бит. (меня вобщем-то только этот диапазон x-ов интересует, но если кто предложит метод вычисления начального приближения получше чем тут, то - спасибо заранее) Я это сразу проверил. Нет - IAR и для sqrt() и для sqrtf() генерит код run-time вычисления. Да вроде неплохо получилось. 30 бит мне хватит вполне. Громоздко как-то.....
  4. Подскажите средство (макрос?), если таковое имеется, для вычисления квадратного корня во время компиляции. Имеется: #define SOME_TRESHOLD 0.15 нужно, чтобы в выражение типа: if (x < (u32)(SQRT(1 - SOME_TRESHOLD) * (1u << 31))) {...} компилятор подставил готовую константу. Вместо вычисления её в run-time. PS: Если имеет значение - IAR. Но лучше компиляторо-независимо. PPS: Пока приходит в голову только: воротить в макросе Ньютона-Рафсона врукопашную. Но может есть путь попроще?
  5. Думаю - заключает следующий рекламный контракт с новым производителем чипов. И скоро мы услышим хвалебные оды в их честь. Как ранее уже слышали про Кинетис, Ренесас, ...
  6. Вспоминается тут мне один мой бывший коллега. Который несколько лет назад решил освоить ООП. И начал везде где ни попадя создавать классы. Со всякими наследованиями и перегрузками. Я потом заглянул в его код и......! о УЖАС!!! Там где раньше были вызовы типа: SetEvent(...), ResetEvent(), SetAlarm(...), ResetAlarm(...), SetState(), ResetState() и т.п. с говорящими названиями, когда глядя на такой код более/менее понимаешь, что там происходит. То теперь там значилось: некий_объектA_с_ничего_не_значащим_названием.Set(...); некий_объектB_с_ничего_не_значащим_названием.Set(...); некий_объектC_с_ничего_не_значащим_названием.Reset(...); ... и так несколько десятков set()/reset()/get() в одной функции, но для разных переменных разного типа. вобщем - код состоящий из огромного множества Set()/Reset()/Get() и т.п. методов с одинаковыми названиями, но внутри совершенно разных. А чтобы понять - что за Set() в данном месте, нужно каждый раз отматывать исходник к месту объявления каждого такого объекта, чтобы увидеть его тип. Таким образом - вместо улучшения читаемости (которое вроде должно давать применение ООП), получили прямо противоположный результат. Стало совершенно нечитаемо. Если раньше можно было просто поиском по имени функции, найти место её определения и посмотреть что она делает, то теперь поиск выдавал тучу одинаковых Set(). Всё как на вашей каринке - вместо столового прибора на столе: с ложкой, вилкой, ножом, тарелкой, получили вот такой ряд из одних вилок!
  7. Конечно. И предназначен для передачи не только собственно кадра данных (единый 24-битный кадр (точнее = 26-битный, если считать со старт- и стоп-битами)), но и точки точной синхронизации (по началу старт-бита) между двумя устройствами. Вот именно об этом я и пишу!
  8. Вы на ровном месте сделали сущестенный оверхед. Совершенно искусственно. Даже не заметив этого. Это собственно то, с чего я и написал Вам изначальное замечание. С которым Вы всё продолжаете спорить, говоря что "не спорите". И каждый раз, своими же примерами, доказываете мою правоту! PS: Да и не будет там перегрузки. Метод же виртуальный. Т.е. - указатель. Будет то, что сказал Arlleex. Я смотрю - тут как раз много любителей создания лошади из каждого атома. Жесть какая! Теперь ещё для инита порта, вместо простого BL, будет стоять кучка команд LDR с последующей BLX: чтение указателя на таблицу виртуальных методов, чтение указателя на конкретный виртуальный метод (Init()), а затем - BLX. И вся эта кухня - вместо простого BL! (которого может и не быть если компилятор заинлайнит его). Ну ладно ещё инит порта, но ведь и чтение/запись символов будет работать через такой-же бурелом!!! Каждый символ! А потом удивляемся, почему на казалось бы ещё вчера мощном CPU, сегодня наша программа еле ворочается. Вот это и есть - оверхед в полный рост!
  9. А какой тогда смысл в таком классе? Если следовать вашей логике, то тогда надо создать такой базовый класс для всех устройств ввода/вывода - UART, USB, SPI и т.п. А какой смысл в таком объединении и чем оно лучше простого UartWrite(), SpiWrite() если кроме имён методов оно ничего не объединяет. Это уже искусственное притягивание классов за уши туда, где они совсем не нужны. И бесполезное загромождение кода бессмысленными сущностями. Так "обязан" или "может"? По Вашим же постам: Если у вас в одном проекте нужна функция Close() для UART, а вдругом - не нужна, то даже там где она не нужна, всё равно нужно её реализовывать? Или нет? Это с чего они "платформонезависимы"??? Вы ведь мой пример выше читали, забыли? Там где размер символа UART = 24 бита. Сможете Вы на STM32 или на LPC такую длину символа установить? Вот опять оверхед! О котором я говорил. Вы похоже не замечаете просто этого.... Нафига мне создавать и передавать какую-то структуру с настройками в функцию инита порта, если у меня в данном проекте нужно для UART устанавливать только скорость (остальные все параметры = const). Только потому, что в каком-то N-ном проекте мне в UART требовалась не только скорость, но и ещё куча параметров? И потому теперь, во всех проектах вместо передачи бодового значения скорости по значению, мне нужно везде тащить этот интерфейс со структурой! Вот именно! А классо-поклонники я вижу просто не замечают этого.
  10. да. А какой тогда смысл? Если только одна функция будет похожая на другие подобные - инициализация, но и та внутри (и по аргументам) - вся другая. Какой тогда смысл в таком наследовании? Когда собственно и ничего не наследуется от родительского. Класс - он для объединения объектов, имеющих похожие свойства. Чем менее объекты имеют похожих свойств, тем такое объединение бессмысленнее и неэффективнее. Это просто уже - притягивание за уши классов туда, где они совсем не нужны. Только потому что модно/молодёжно. Считаю что объединять в какие-то логические единицы (в виде класса или ещё как) нужно на более высоком уровне. Например (как у меня) - драйвер отладочного потока. Он передаёт поток как правило через UART (иногда бывают другие каналы) и внутри может вызывать функции установки скорости UART, передачи/приёма символов и т.п. Которые - обычные функции. Т.е. - построение по типу: middleware / IO-уровень.
  11. Конечно. А почему "запутаетесь"? Ведь этот драйвер будет однозначно проще универсального, который должен быть рассчитан на все возможные случаи. А значит в универсальном запутаться проще. Вот у меня сейчас в проекте есть UART, который: 1) в который нужно писать данные из ISR; 2) это только запись в FIFO UART, а собственно сама передача физически должна начинаться от аппаратного сигнала таймера значительно позже записи (но с привязкой к таймеру с точностью до такта CPU); 3) момент начала старт-бита (на приёмной стороне) надо отследить максимально точно (желательно с точностью до такта CPU), а значит - захватить его по аппаратному таймеру; 4) размер "символов" этого UART = 24 бита. Вот и попробуйте такое засунуть в "универсальный драйвер".
  12. Можно взять что-то из XMC4xxx. Там это всё есть: разные сложные варианты синхронизации периферии между собой аппаратными сигналами.
  13. Так если источник перегрева - сам CPU, то зачем что-то отключать? Достаточно этот CPU перевести в режим малого потребления. И ждать пока не остынет.
  14. Вообще-то для этого необходимо, чтобы была возможность синхронизации с развёрткой экрана. Иначе никакой буфер в ОЗУ не поможет. Есть ли она в ILI9341? Не знаю... Не знаю - зашёл на али, набрал в поиске "spi lcd touch ili9341" вывалило кучу ссылок, типа: https://aliexpress.ru/item/1005001692474185.html https://aliexpress.ru/item/1005003120684423.html PS: Цены что-то на них сильно поднялись... негуманно как-то...
  15. Не понимаю - с чем Вы тогда спорите... То доказываете, что универсальный драйвер будет не менее оптимальным, чем специализированный, то вдруг "оверхед есть". Сами себе противоречите... Если какое-то решение требует больше ресурсов, чем другое, на выполнение аналогичной задачи, это означает, что оно менее оптимально. Всё! О чём тут спорить? Вопрос "зачем" - я не рассматривал. Каждый для себя сам определяет "зачем". Если Вас устраивает время старта устройства = ~1мин и требование везде впендюривать внешнюю SDRAM + внешнюю флешку для загрузки ПО - ставьте линух, на который Вы ссылаетесь. И эти его требования - это как раз следствие универсальности и возможности "работать на куче архитектур". Но тогда не удивляйтесь, что задачам требуются мегабайты стека (как Вы писали ранее) или что они сжирают батарейку за полдня. Или когда работа с теми же несколькими UART-ами стала сжирать значительное время CPU. Кем "общепринятые"? Вами? Так и говорите за себя. У других могут быть свои "общепринятые" методы. И вообще не понимаю - что такое "открыть, закрыть" и зачем это UART-у? Что там закрывать? Практический пример: Вот написали Вы эти свои методы, с семафорами и прочими блэкджеком и шлюхами плюшками, а в новом проекте вдруг потребовалось писать/читать этот UART из ISR! Что будете делать? С Вашим подходом времени тратиться будет больше. В общем случае. Потому как - требования у разных проектов разные, и просто невозможно предусмотреть всё необходимое заранее. Вы когда начинаете какой-то проект и пишете там какой-то драйвер, уже можете предусмотреть на много проектов (и лет) вперёд - какие все возможные свойства вам понадобятся от этого драйвера в этом и во всех будущих проектах??? Или какое свойство этого драйвера вдруг окажется несовместимым с какой-то из будущих потребностей? Подозреваю что нет. А значит - в новых проектах придётся этот драйвер перепиливать многократно. И опять встаёт та же проблема: что делать с предыдущими версиями универсального драйвера в старых проектах? Все переделывать??? Или развалить на кучу веток, которые через несколько модификаций станут совершенно независимыми. У меня складывается ощущение, что все ваши задачи - примерно одинаковые. Как и используемые МК. Потому Вы просто не можете представить себе всего многообразия различных требований предъявляемых в разных проектах к похожим интерфейсам. И потому ваше "универсальное решение" кажется вам оптимальным. Только что сами же говорили о "пустой трате времени". Опять сами себе противоречите. PS: Универсальность == неэффективность. Однозначно. Спорить тут не о чем.