Jump to content

    

AlanDrakes

Участник
  • Content Count

    168
  • Joined

  • Last visited

Community Reputation

0 Обычный

About AlanDrakes

  • Rank
    Частый гость
  • Birthday 01/31/1988

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

1757 profile views
  1. Если в заголовке нет ошибки, и на контроллер требуется отправлять команды со стороны ПК, то... интерфейс SWO однонаправленный. Контроллер может в него только выводить данные. Как-то задумывался над подобной ситуацией, но в итоге пришёл к стандарту для себя - развожу на плате ttl uart и не заморачиваюсь.
  2. Смысла делать "медленную" смену картинок осциллографу нет. Там наоборот, чем быстрее, тем лучше. Хорошие осциллографы выдают 60+FPS + отображают "интересные" кадры, которые были пойманы между отрисовками экрана. Вероятно, сложно описал мысль, но... Грубо говоря, имеем развёртку в 1мс на кадр (10 клеток по 100ns). При 60FPS между кадрами будет (1000 / 60 ) = 16,6мс, округлим до 16. В момент времени T=0 [0..1мс] - (первый экран) срабатывает триггер, данные отправляются в память. После этого ничего интересного НЕ происходит на протяжении... допустим, 8мс. В момент T=8.186мс снова срабатывает триггер. Захваченый буфер так же отрисовывается (старый может стать "призраком", потеряв часть яркости). Далее, допустим, в момент T=14.2мс приходит третий импульс, заставляющий сработать триггер. Естественно, отрисовываем и его. Получаем наложение трёх сигналов на ОДНОМ кадре. Современные осциллографы позволяют рисовать по 50+ слоёв и имеют производительность в 60k+ WFS (WaveForms per Second - волновых форм в секунду). Это возможно. Но перед новой отрисовкой потребуется восстановить исходное состояние картинки ДО вывода новой осциллограммы. Иначе экран плавно превратится в сюрреалистичный тест контроллера экрана, а не с осциллограф. Собственно, по этой причине я и указывал на желательное наличие в контроллере дисплея понятия слоёв, которые можно использовать для отрисовки кадра и команды типа Layer_Clear(LayerNumber). Очевидно, 16 бит, так как это самый большой кристалл в линейке. Как определить? Простой способ - скачать STM32CubeF3 и в нём настроить периферию. Как минимум, хорошо визуализирует используемые пины. Код от него использовать - не рекомендую. А вот в Datasheet'е всё очень странно. Упоминание о контроллере памяти есть, но списка пинов - нет. Не путайте мух и котлеты - битность АЦП (12) и его возможное разрешение (4096 значений). И мне интересно, что значит "12 точек по стояку"?. 12 пикселей в высоту? Мало. 12 пикселей в ширину? Не имеет смысла. Если берёте экран на 480 пикселей - так используйте хотя бы 480 пикселей для буфера захвата. Нормальные приборы используют 4к точек. В высоком разрешении (12 бит) каждый отсчёт будет занимать 2 байта (12 / 8 = 1.5, округляем вверх до целого = 2). Значит нужно 8кБ памяти только под буфер выборок. Хорошие приборы так же используют OverSampling - когда один пиксел (столбец) может скрывать под собой несколько отсчётов. > для 100кГц и 30 кадров в секунду для двух периодов исследуемого сигнала и миллион выборок в секунду. Входящий сигнал? Ну да, в этом случае, два периода сигнала займут всего-лишь: 2 (периода) * (1(с) / 100000(гц)) = > 2 * (1 / 100000) => 2 * (0,00001) = 0,00002с (если я не ошибся с количеством нулей) 30FPS = 1 / 30 = 0.033с = 33мс 0,033 - 0,00002 = 0,032997с... ничегонеделанья и один снимок на два периода сигнала. Ну, допустим... Хотя это и КРАЙНЕ странно. Приведённый выше контроллер умеет только линию в 1px. Я на это и намекаю. SPI не предназначен для такого потока данных. Во всяком случае, постоянное дёрганье пина RS (D/C) - рискуете не попасть в тайминги и дисплей воспримет данные как команду, или команду как данные. Плохо поддерживают, потому что широкому кругу заказчиков такой функционал ни к чему. Да даже работу со слоями никто не делает на уровне контроллера экрана (практически никто). Плюс, это усложнение кода, плюс дополнительная SRAM (именно статическая память, не динамическая) на каждый слой. Для STM32F767 - можно попробовать... скажем... 480*800 / 2 = 192000 байт (187.5кБ из 368кБ) - хороший такой буфер памяти. Чип гонится до 216МГц (штатно) и даже выше (я случайно разогнал его до 250МГц несколько раз). FMC контроллер работает на частоте ядра, но на такой скорости уже могут возникать проблемы из-за проводов, а так же требуются такты задержки для того, чтобы порты успевали зарядить дорожки до нужного напряжения. А там ёмкость небольшая, но на таких частотах = существенная нагрузка на чип. Тайминги FMC на моей плате были... -/-/0/5/-/2, где "-" - значение не используется в данном режиме, 0~5 задержки в тактах, необходимые для корректной работы. Соответственно, на 200МГц получаем задержку шины в 7(!) тактов. 1 такт на 200МГц = 5нс, 7 тактов = 35нс. Шина - 8 бит (потому что ILI9431 LCD Shield для Ардуины). Соответственно, скорость обмена в моём проекте была ~28,5МБ/с, и 384000 байт можно протолкнуть через шину за 13,47мс. Через параллельную шину. Ядру контроллера при этом желательно оставаться в состоянии сна, ибо у него приоритет выше, чем у DMA блока и если ядро будет работать с той же областью памяти, что и DMA, последний будет стоять в ожидании. Кстати, лол, 74FPS. На SPI... эм... грубо говоря, делим на 16 (если SPI скоростной) или на 32. Соответственно, 480*800 на последовательной шине с горем пополам выдаст 2-4FPS с полным обновлением экрана. Посмотрите в сторону более скоростных кристаллов, либо кристаллов со встроенным ускорителем и интерфейсом LVDS для таких размеров экрана. Тот же Fnirsi 1013D построене на Allwinner F1C100s.
  3. Как более простой вариант - можете ещё присмотреться к Wiznet W5500. Чип со стэком TCP-IP. Подключается по SPI к контроллеру, умеет до 8 сокетов (tcp/udp/ip/raw(1)). Для простых применений - более чем достаточно. В случае с tcp/udp, даже не требуется глубокого понимания принципов работы сети. Указываете IP/Mask/GW чипу, указываете к кому подключаться (IP/Port/Porocol) и всё. Хотя DNS запросы придётся обрабатывать самостоятельно (либо работать на уровре IP адресов).
  4. Пол часа пытался найти что-то такое в гугле, пытаясь сформулировать запрос >_< Ну да, с ним будет быстрее. Но потребуется внешний ROM для хранения фоновой картинки и каждый раз её перечитывать, а потом отрисовывать осциллограмму... ну не знаю. Здесь интереснее бы смотрелся контроллер с поддержкой слоёв: Задний слой с общими элементами типа фона кнопок, полей измерений и шкал, второй слой с графиком, и третий с надписями. Для осциллографа - прямо минимум необходимого. Опять же, можно попробовать посчитать скорость работы с точками путём пихания данных в регистры... применительно к RA8875 это... 0x91~0x94 (Start line), 0x95-0x98 (End line), Color (0x63-0x65), 0x90 (Draw!) (while (0x90 == draw) {} ). Чёт тоже много действий. Было бы интереснее, если бы описали команду через запись одного регистра набором данных. Например, 0x90 => Draw (0x20), StartX1, StartX2, StartY1, StartY2 ... Color1, Color2. Опять же, для осциллографа... (снова применительно к теме) требуется отрисовка линий по массиву точек. А вот заливка прямоугольников будет экономить время. Особенно больших.
  5. Можно, но у ТС вопрос с другого форума Радиокот с "умным" управлением дисплеем, как видеокартой. Мол, нужно отправить в дисплей команды типа "Рисуй массив точек", или что-то подобное. Плюс, в режиме SPI даже рисование пикселей с помощью таких команд - довольно затратная штука. Опять же, для тех чипов, с которыми я работал, последовательность команд будет выглядеть: SetWindow () 0x2A + (Left >> 8) + (Left & 0xFF) + (Right >> 8) + (Right & 0xFF) + 0x2B + (Top >> 8) + (Top & 0xFF) + (Bottom >> 8) + (Bottom & 0xFF) + 0x2C + (RGB >> 8) + (RGB & 0xFF) 13 байт + дёрганье ножкой RS (D/C). При скорости SPI в 20МГц получим (20 / 8) = 2.5МБ/с (8 бит при SCK = 20МГц). Будем считать, что точки расположены как попало, потому сэкономить на отправке которких команд не выйдет, а пин RS (D/C) для нас бесплатен и его переключение не занимает времени. (По факту - требуется дождаться окончания транзакции, убедиться в этом, и только потом менять его состояние. В противном случае... у меня были интересные странности в поведении дисплея). Значит, 13 байт при максимальной скорости в 2500000 байт/с отправятся за 5,2мкс. Допустим, у нас порядка 2048 точек. ~10,65мс. Нужно не забыть стереть предыдущие пиксели перед этим (+10,65мс) = 21,3мс. Окей, на 50Гц обновления тянет. А теперь нужно отрисовать интерфейс (с результатами измерений!). Пикселами будет КРАЙНЕ медленно - лучше рисовать как раз блоками. То же SetWindow с размерами окна, и пилить туда текст потоком пикселей. Допустим, нужно отрисовать порядка 10 блоков измерений, размерами... хотя бы 12*64. 12 пикселей - высота и какой-нибудь узкий шрифт. 12 * 64 = 768 * 2 (rgb) = 1536 + 11 (SetWindow) = 1547 байт. Делим на 2.5МБ/с = 0,62мс на блок. * 10 блоков = 6.2мс. Так как перерисовка блока выполняется начисто (с фоном) - старые пиксели затираются автоматически. Складываем 21,3 + 6,2 = 27,5мс ~36FPS, что ещё терпимо. В результате, SPI интерфейс не особо скоростной :( FSMC контроллер при тактовой в 20МГц сможет залить весь экран (320*240) * 2 (rgb565) за ~7,7мс (разве что для этого требуется частота ядра около 80+МГц). Где-то я делал тесты по скорости вывода картинки в экран. И вроди бы использовал при этом максимально возможные частоты передачи... и получал на том же экране частоту обновления до 40Гц (с перерисовкой и почти без разрывов), тупо дёргая DMA2D по таймеру. Ядро при этом занималось своими делами.
  6. FSMC - "Гибкий контроллер статической памяти". И он фактически позволяет передавать данные по параллельному интерфейсу (i8080 и аналогичным в режиме "LCD/PSRAM"). Он позволяет передавать данные быстро. Грубая оценка - 4 такта процессора на 1/2/3 байта (в зависимости от ширины шины). А передача команды/данных осушествляется записью байта в разные адреса в памяти (не в RAM, а в адресном пространстве, которое отображено на память) в случае моего проекта это блок 0xC00xxxxx, а FSMC сам разбирается с таймингами пинов и установкой уровня на пине RS (данные/команда). SPI интерфейс с другой стороны, это последовательная шина. У него ВСЕГДА шинита в 1 бит, плюс делитель периферии... итого скорость вывода байта в периферию около 32 тактов ЦП на 1 байт. Плюс, дополнительно нужно кодом программы управлять пином RS самостоятельно, выбирая, когда отправляется команда, а когда данные. По поводу "векторного" управления - сильно не все LCD контроллеры позволяют отправлять команды отрисовки примитивов. Тот же широко распространённый ILI9431/ILI9325/ILI9488/RENESAS_R61580/ST7735 (список того, с чем я работал), умеют только доступ к памяти. Всё. Даже заливку прямоугольника не позволяют выполнить своими силами. ИМХО: У себя максимально использую буферы экрана - это позволяет устранить мерцание при отрисовке. Хотя память кушает хорошо. Экран 320*240 требовал для себя 38400 байт (да, именно половину от своего разрешения). В этот буфер выполняется отрисовка интерфейса, данных и прочего, после чего его обрабатывает "ускоритель" DMA2D, который распаковывает пиксели из формата L4L4 в RGB565, которые затем отправляет через FMC в дисплей. LCD_BUF[320*240/2]; PX[4bit] -> DMA2D ----unpack------LUT-----> RGB[16bit] ---> FMC ---2x8bit--> LCD
  7. VSCode + PlatformIO + ESP-IDF. Стрит-флеш! На слабой машине МЕДЛЕННО. VSCode запускается шустро. Потом секунд 40 PlatformIO вспоминает, что он тут делает (перечитывает долбаную конфигурацию и пытается вспомнить что можно делать). После этого вроди бы можно работать. Компиляция проекта - через встроенные скрипты. Выбросить часть библиотек невозомжно. В частности, проект компилирует ВСЁ из штатных библиотек IDF и только на этапе сборки линкует необходимое. Как от этого избавиться - непонятно. Лично у меня если очистить проект, или добавить файлы в него (*.c / *.h) - выполняется чистовая пересборка где-то на 4 минуты. Чистовая занимает секунд 20 (редактирование "своих" файлов (в /src)).
  8. В их же даташитах указано, что объём DDR2 на f1c200s - 32MB, а на f1c200s - 64MB.
  9. У меня инициализируется так: Все выводы в консоль можно закомментировать, как и проверку if (RTC_OK), которая при первом запуске устанавливает начальное время часов. delay_us - задержки в микросекундах. Часы обычно запускаются (на не самом хорошем кварце) за 1-3 секунды.
  10. addrSysMem = (uint32_t)&SysMem; Эта инструкция получит АДРЕС переменной. Если: const uint32_t SysMem = 0x24000084; то (uint32_t)&SysMem = 0x08xxxxxx - скорее всего окажется во Flash памяти. Значит (0x08xxxxxx + 0x000xxxxx) - указатель будет пытаться писать во Flash. Ата-та так делать! Если же uint32_t SysMem = 0x24000084; то (uint32_t)&SysMem = 0x200xxxxx - скорее всего окажется во RAM памяти. Значит (0x200xxxxx + 0x000xxxxx) = Мы снова в RAM. Тут ошибки не будет скорее всего. Может Вы хотели написать так: addrSysMem = (uint32_t)SysMem; В сообщении выше я ошибся, обнулив не те биты. Попробовал прокомментировать это же в коде. void SetCalcAddrVarF(uint32_t addr, float var) { adrrMem = addr & 0xFFFFF; // 0x000xxxxx addrSysMem = (uint32_t)&SysMem; // Pointer to SysMem *(__IO float*)(addrSysMem + adrrMem) = var // Write at (pointer to SysMem + 0x000xxxxx) }
  11. Недостаточно данных. Чему равен addrSysMem? Чему может быть равен addr? По логике, addr будет сбрасывать последние 20 бит, значит (для STM32) скорее всего получится 0x200xxxxx -> 0x20000000. Итоговый адрес выходит (addrSysMem + 0x20000000) = float. Не уверен, что так можно.
  12. Вроди бы, UART0 нельзя использовать напрямую, т.к. он отладочный. Но можно выводить сообщения через ESP_LOGx Требуется #include "esp_log.h" ESP_LOGI("TEXT", "TEXT"); выведет "информационное" сообщение. ESP_LOGE("TEXT", "TEXT"); выведет "ошибку" и так далее. Таки ещё раз рекомендую добавить в бесконечный цикл вызов переключения контекста "vTaskDelay(1);" Без него внутренняя ОС так и будет падать в перезагрузку. Если вам нужен отдельный UART, который работает только в момент выполнения основной программы - то используйте другие пины. Либо переназначайте текущие (если это поддерживается). Документация от производителя: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/uart.html
  13. Это случается из-за работающего WDT - таймер сторожевой собаки. Так как while(1) {} является бесконечным циклом ожидания, а встроенная RTOS в SDK переключает задачи только явными вызовами системных функций, сброса таймера не происходит и он перезапускает кристалл. Попробуйте сделать так: while (1) { vTaskDelay(1000 / portTICK_PERIOD_MS); }; Фактически, основная задача будет спать и постоянно переключать контекст выполнения с себя на фоновые задачи. В том числе, сброс WDT. ------------------------------------------------------------------------------------------------------ Ещё проверьте, что запись идёт в правильный адрес памяти - 0x1000 в вашем случае. Можно руками прошить итоговый файл. Пример: esptool.py.exe --port COM7 --baud 512000 write_flash --flash_size=detect 0x1000 .\Downloads\esp32-idf3-20210202-v1.14.bin Отсюда: https://www.esp32.com/viewtopic.php?f=12&t=9941&sid=eb816a68997eb0864719cef143cac436&start=10
  14. Нахожу очень много вариаций этого кода: https://community.arm.com/support-forums/f/embedded-forum/4749/error-hard-fault-handler Собственно, нужен сам обработчик, который выведет сообщения, например, в консоль в виде дампа части стэка (весь восстановить сложновато, но и это уже что-то), и остановит выполнение. Все используют printf(), или его аналоги. Собственно, код: BusFault_Handler - может быть как сам BusFault, так и остальные обработчики. Он НЕ должен изменять значение стэка. Я переписал под минималистические функции DumpXXX, которые почти не обрабатывают данные. Текст - просто выводит строку, HexDWord - выводит 32 бита HEX-кодом. Это единственное моё изменение.
  15. Вам нужна спецификация, часть Е1: PartE1_SDIO_Simplified_Specification_Ver3.00.pdf Конкретно пункт 17.3 - конфигурация общей шины. В общем случае каждая карта может подключаться ко всем пинам шины, кроме пина тактирования. Такт должен быть мультиплексирован между картами. Переключение устройств (карт) возможно в том случае, когда выбраная (в текущий момент) карта не управляет шиной SD (SD Bus), например когда нет состояния занятости на линии. Не выбранное устройство может подать хосту прерывание в любой момент (даже без подачи сигнала тактирования). Выход карты #INT асинхронный. Как понимаю, когда передача завершена, и карта не трогает шину DAT[3:0], можно переключить тактирование на другую карту, выждать некоторое время (8+ тактов?) и работать уже с ней. Дожидаться освобождения шины обязательно, иначе будет интересная ситуация, когда одна карта держит шину, допустим в состоянии 0b0011, хост отправляет, например, 0b1100, а выбранная в этот момент карта будет читать 0b0000 ("проволочное И"):