Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 (изменено) · Жалоба Недавно появилась задача подключить небольшой объем оперативной памяти к микроконтроллеру STM32, чтобы буферизировать видеопоток. PSRAM64(H) - это псевдо статическая оперативная память, подключаемая по QuadSPI (можно конечно и по 1 или 2 проводному SPI, но не суть). В некоторых линейках STM32 если встроенный интерфейс QSPI с возможностью мапинга адресного пространства, правда только на чтение. Так же интерфейс QSPI в данных микроконтроллерах может работать в сдвоенном режиме, т.е. можно подключить сразу 2 флэшки с параллельной шиной в 8 бит и хранить пол байта на одном чипе, а вторые пол байта на втором. Но все это Вы можете изучить прочитав мануал, а в моем случае я решил подключить те же самые 2 чипа памяти в параллель по FSMC, просто из-за физического отсутствия интерфейса QSPI в выбранном контроллере STM32F407VETx. Реализация следующая: - Подключаем BANK1 FSMC в режиме LCD интерфейса - Ножка NE1 - будет использоваться как SCK; - Ножки NWE, NOE и A просто игнорируем и даже не инициализируем; - Любую ножку инициализируем на выход для выбора кристалла CS. И в программе просто обращаемся к фиксированной ячейке памяти по адресу 0x60000000 для записи или чтения данных из памяти. Та же самая ячейка памяти используется для посылки команд и выбора адреса ячейка памяти. С ней можно работать как напрямую, так и по DMA Пример работы с данной памятью Spoiler volatile void *const sram = (volatile void*)0x60000000; static DmaStream dma(DMA2_Stream0, DmaStream::Channel0); //--------------------------------------------------------------------------- uint32_t initPSRAM64() { initFsmc(); Timer::wait(2_mSec); select(); write(u8ToSingleRev(PSRAM64::ResetEnable)); unselect(); select(); write(u8ToSingleRev(PSRAM64::ResetMemory)); unselect(); select(); write(u8ToSingleRev(PSRAM64::ReadId)); write(uint64_t(0)); write(uint64_t(0)); write(uint64_t(0)); for (size_t i = 0; i < sizeof(id1); ++i) { uint64_t buf = read<uint64_t>(); ((uint8_t*)&id1)[i] = singleToU8Rev(buf, 0x02); ((uint8_t*)&id2)[i] = singleToU8Rev(buf, 0x20); } unselect(); if (id1.manufacturer != id2.manufacturer || id1.kgd != id2.kgd) return 0; if (id1.manufacturer != 0x0D || (id1.kgd != 0x55 && id1.kgd != 0x5D)) return 0; uint32_t size = 8*1024*1024; return size; } //--------------------------------------------------------------------------- constexpr uint64_t u8ToSingleRev(uint8_t value) { return (((value & 0x80) ?0x11ULL :0x00ULL) << 0) | (((value & 0x40) ?0x11ULL :0x00ULL) << 8) | (((value & 0x20) ?0x11ULL :0x00ULL) << 16) | (((value & 0x10) ?0x11ULL :0x00ULL) << 24) | (((value & 0x08) ?0x11ULL :0x00ULL) << 32) | (((value & 0x04) ?0x11ULL :0x00ULL) << 40) | (((value & 0x02) ?0x11ULL :0x00ULL) << 48) | (((value & 0x01) ?0x11ULL :0x00ULL) << 56); } //--------------------------------------------------------------------------- constexpr uint16_t u8ToQuadRev(uint8_t value) { return ((value & 0xF0) >> 0) | ((value & 0xF0) >> 4) | ((value & 0x0F) << 8) | ((value & 0x0F) << 12); } //--------------------------------------------------------------------------- constexpr uint8_t singleToU8Rev(uint64_t value, uint8_t mask) { return ((value & (uint64_t(mask) << 0)) ?0x80 :0) | ((value & (uint64_t(mask) << 8)) ?0x40 :0) | ((value & (uint64_t(mask) << 16)) ?0x20 :0) | ((value & (uint64_t(mask) << 24)) ?0x10 :0) | ((value & (uint64_t(mask) << 32)) ?0x08 :0) | ((value & (uint64_t(mask) << 40)) ?0x04 :0) | ((value & (uint64_t(mask) << 48)) ?0x02 :0) | ((value & (uint64_t(mask) << 56)) ?0x01 :0); } //--------------------------------------------------------------------------- inline void select() { FSMC_CS_Port.resPin(FSMC_CS_Pin); } //--------------------------------------------------------------------------- inline void unselect() { for (volatile int i = 0; i < 3; ++i); FSMC_CS_Port.setPin(FSMC_CS_Pin); } //--------------------------------------------------------------------------- template<typename T> inline void write(T data) { *(volatile T*)sram = data; } //--------------------------------------------------------------------------- template<typename T> inline T read() { return *(volatile T*)sram; } //--------------------------------------------------------------------------- void writeDMA(const void *data, size_t size) { dma.init(DmaStream::M2M, DmaStream::VeryHigh, DmaStream::Normal, DmaStream::PInc, DmaStream::MNoInc, DmaStream::P16, DmaStream::M16); dma.setMemoryFrom(data); dma.setMemoryTo0(sram); dma.setCount(size / 2); dma.transferCompleteClear(); dma.enable(); } //--------------------------------------------------------------------------- void readDMA(void *data, size_t size) { dma.init(DmaStream::M2M, DmaStream::VeryHigh, DmaStream::Normal, DmaStream::PNoInc, DmaStream::MInc, DmaStream::P16, DmaStream::M16); dma.setMemoryFrom(sram); dma.setMemoryTo0(data); dma.setCount(size / 2); dma.transferCompleteClear(); dma.enable(); } //--------------------------------------------------------------------------- inline void flushDMA() { while (!dma.transferCompleteIs()); } //--------------------------------------------------------------------------- В итоге мы получаем 16МБ оперативной памяти (правда без мапинга адресного пространства); Дешевая стоимость ~300р за пару на Алиэкспресс; Минимальное место на плате (2 по SO8); Минимальное количество занятых ножек (всего 10 ног); Скорость чтения/записи до 133 МБ в секунду. Из недостатков только отсутствие возможности подключения к адресному пространству, но при работе по QSPI на запись его тоже не будет. Изменено 3 сентября, 2023 пользователем haker_fox Длинный код нужно прятать под спойлер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба 42 минуты назад, Ivan. сказал: Из недостатков только отсутствие возможности подключения к адресному пространству, но при работе по QSPI на запись его тоже не будет. "Только"? Да ладно! А то, что стоит как чугунный мост (раз в 10 дороже SDRAM аналогичного объёма)? И работать будет так же раз в 10 медленнее (так как обычная внешняя ОЗУ, отображаемая на адресное пространство, в современных МК как правило может кешироваться, а ваша - нет). Так себе решение.... За эту цену можно было пару МК со встроенной быстрой ОЗУ купить. И места на плате заняло бы меньше и скорость была бы выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба SDRAM занимает много места и половину ног контроллера И какой это контроллер можно найти с 16 МБ за 500р? (~200р STM32F407 и ~300р PSRAM64) В третьих мне не нужно кешировать данные, мне нужно собирать поток данных с DCMI и класть его в буфер, а по событию выгружать на SD 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 3 сентября, 2023 Опубликовано 3 сентября, 2023 (изменено) · Жалоба Гусары, молчать! (Но подумали про allwinner t113-s). Вам кадр или несколько секунд видео? Если кадр это не 16 мегабайт. 512k вполне у stm32h7 есть. Изменено 3 сентября, 2023 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 62 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба On 9/3/2023 at 5:49 PM, Ivan. said: И какой это контроллер можно найти с 16 МБ за 500р? (~200р STM32F407 и ~300р PSRAM64) Где вы STM32F407 за 200 руб. берете ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба AliExpress Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба 4 минуты назад, GenaSPB сказал: Гусары, молчать! (Но подумали про allwinner t113-s). В том числе, но не только. Есть также старенькие Nuvoton-ы. В коих (если не путаю) = up to 64MB stacked RAM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба 5 минут назад, GenaSPB сказал: Но подумали про allwinner t113-s Да тут даже v3s будет более чем))) 3 минуты назад, Ivan. сказал: AliExpress Можно не в напряг на подделку нарваться... 8 минут назад, GenaSPB сказал: Вам кадр или несколько секунд видео? Мне тоже интересно, что за "видео" ТС решил крутить на СТМ 160МГц ))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба STM можно и в проме купить, а вот allwinner где брать? STM можно в любой момент на GD заменить пин2пин 13 минут назад, mantech сказал: Мне тоже интересно, что за "видео" ТС решил крутить на СТМ 160МГц ))) Видеофиксатор события возникновения пожара. мне не нужно раскодировать поток, мне нужно только зафиксировать. Требуется зафиксировать 10 секунд до возникновения пожара Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба 7 минут назад, Ivan. сказал: STM можно и в проме купить, а вот allwinner где брать? Алиэкспресс вроде еще не запрещен)) По крайне мере мои заказчики трудностей не испытывают (покупаем модули на v3s и Т113). 8 минут назад, Ivan. сказал: Требуется зафиксировать 10 секунд до возникновения пожара Ну для СТМ это уже "подвиг" с каким разрешением и сколь кадров будет за эти 10 сек? 10 минут назад, Ivan. сказал: в любой момент на GD заменить Вероятность, что GD тоже пропадет выше, чем у аллвиннера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба 14 минут назад, mantech сказал: Ну для СТМ это уже "подвиг" с каким разрешением и сколь кадров будет за эти 10 сек? И в чем же подвиг прокачать 30 кадров/с HD качества в JPEG-е? Камера уже шлет кадры в JPEG в среднем 50kB на кадр Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 3 сентября, 2023 Опубликовано 3 сентября, 2023 · Жалоба Основной задачей в данном проекте планируется FFT, а камера так, довесок, практически не занимающий ресурсов контроллера. Все на DMA Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 4 сентября, 2023 Опубликовано 4 сентября, 2023 (изменено) · Жалоба 14 часов назад, Ivan. сказал: HD качества в JPEG-е 14 часов назад, Ivan. сказал: в среднем 50kB на кадр Или у вас JPEG какой-то волшебный, детализации там никакой или все на одном фоне, или качество там будет, ммм...вообщем))) Ну вам виднее, если действительно 50к\кадр хватает, то СТМ с таким конечно справится... Изменено 4 сентября, 2023 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 21 сентября, 2023 Опубликовано 21 сентября, 2023 · Жалоба Пока проблем с захватом видео не возникло, нагрузка на процессор составляет около 5% (могу немного приврать, т.к. сейчас нет под рукой картинки с анализатора), это с учетом того, что в момент выгрузки в оперативку программа приостанавливается. Это я испытывал на разрешении 1600x1200, 15 кадров в секунду. Если перевести на прерывания - освободится еще уйма времени вплоть до <1% Структура следующая: - По DMA с DCMI поступают данные. DMA настроен с двойным буфером по 1КБ; - По заполнению одного из буфером происходит прерывание и начинается выгрузка во внешнюю оперативку (в данный момент по одному QUAD SPI, потом будет 2 QUAD SPI в параллель, а точнее по FMC с 8-битной шиной как было задумано); - В это время заполняется второй буфер; и так по циклу, пока не произойдет прерывание окончания кадра; - По окончанию приема кадра он фиксируется в псевдо файловой системе для дальнейшего анализа; - Далее по какому то условию любой кадр может быть заблокирован от удаления, чтобы он не затерся в циклическом буфере; Сжатие в MPEG или другие форматы не планируется. Видеофайл будет сохраняться в формате MJPEG. т.е. покадровое сжатие, что уже выполнено самой камерой. Кодирование/декодирование не нужно. Вы будете смеяться, но в данный проект на STM32F407 планируется впихнуть еще много чего, и видео захват - это мелочь. - Планируется поднять TCP и транслировать видеопоток; - По событию обнаружения пожара выгрузка видеофайла на SD карту в формате MJPEG; - Modbus; - HART; - Ну и непосредственно сам анализ пламени на основе FFT с 3(4) ИК/УФ сенсоров. Сейчас я игрался с камерой OV2640 и качество картинки с нее, мягко говоря, очень плохенькое. Заказал OV5640, посмотрим какая у нее будет картинка. У меня сейчас появилась другая проблема: Свою библиотеку работы с SD картой мне писать было не охота и я воспользовался CUBE-вским примером. Так вот создание файла размером в 100КБ у меня заняло около 114мс Размер кадра с OV2640 с разрешение 1600*1200 составляет около 120КБ, в разрешении 320*240 ~6КБ. Картинку с разрешение 320*240 удается передать на ПЛК по Modbus (RS-485 57600 baud) примерно за 2 секунды, что позволит оператору принять решение пожаротушения Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться