• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Esp8266->spi->tft (ili9341) без внешнего mcu

Sermus

New member
Это ускорит исполнение ваших расчетов, но не I/O...
Подождите, серьезно? Вы говорите, что можно удвоить частоту ядра и ничем за это не заплатить? А чего его тогда не заставить все время работать на 160? Где подвох? А что за волшебные битики выставляются?
 

pvvx

Активный участник сообщества
Подождите, серьезно? Вы говорите, что можно удвоить частоту ядра и ничем за это не заплатить? А чего его тогда не заставить все время работать на 160? Где подвох? А что за волшебные битики выставляются?
Я всегда, в своих проектах, гоняю модули на 160MHz. Включаю 160MHz в первых командах инициализации и постоянно, когда открыты соединения по TCP. Не выключаю никогда (но периодически отключает SDK в процедуре, вызывающейся периодически через несколько секунд и опрашивающей массу условий - вроде названа и выводит в отладку "periodic_call").
Плата в том, что немного больше греется и немного больше жрет. Но она компенсируется увеличением производительности с лихвой (трансфер WEB сервера поднимется почти в 2 раза, иногда и более - зависит от асинхронностей обработки пакетов WiFi).
Это битик переключает делитель на CPU и далее вызов процедуры, указывающей остальным процедурам BIOS и SDK, что частота на CPU переключена и мы не в "режиме экономии". На остальную периферию CPU это не влияет - у них свои делители.
SDK создана для опроса одного датчика и Iot - им и не требуется производительность от CPU, а наоборот. Но менее 80MHz не поставить, по массе причин.
 
Последнее редактирование:

Sermus

New member
Интересно, спасибо за информацию.
Прескейлер для SPI в этом случае, естественно, придется тоже увеличить в два раза.
А 160 - это максимум, на который способен кристалл?
 

pvvx

Активный участник сообщества
Прескейлер для SPI в этом случае, естественно, придется тоже увеличить в два раза.
На остальную периферию CPU это не влияет - у них свои делители.
А 160 - это максимум, на который способен кристалл?
160 номинал.
 

Sermus

New member
Т.е. если в момент, когда частота ядра 80, SPI-делитель сконфигурировать так, чтобы SPI тактировался на 10 (т.е. делитель 8), а потом выставить частоту ядра 160, то частота SPI все равно останется 10? Я так параноидально переспрашиваю, потому что мне это кажется странным. Точнее интуитивно некорректным кажется утверждение "на периферию это не влияет". Одно дело периферия, частота которой явно не конфигурируется, понятно, что ответственность по поддержанию ее работоспособности не лежит на плечах программиста, ведь он даже не знает как тактовая частота ядра влияет на такую периферию. Другое дело периферия, такт которой явно задается программистом как частота ядра, поделенная на заданный программистом коэффициент. В этой ситуации как реализовать парадигму "IO не зависит от частоты ядра"? Автоматически менять делитель?
 

Andy Korg

Moderator
Команда форума
В этой ситуации как реализовать парадигму "IO не зависит от частоты ядра"? Автоматически менять делитель?
Для переферии свои шины со своими источниками тактов, если мне склероз не изменяет (вроде как шина AHB)
 

Sermus

New member
На самом деле единственный практический вопрос - что фиксируется в момент выставления делителя частоты - делитель или посчитанная на его основе частота.
Если первое, то прыжок к частоте 160 ядра приведет к увеличению частоты SPI. Если второе - то ничего не произойдет.
 

Andy Korg

Moderator
Команда форума
что фиксируется в момент выставления делителя частоты - делитель или посчитанная на его основе частота.
Не важно, т.к. CPU тактируется от своего источника, а SPI от своего. И они никак не связаны. Или я чего-то не допонял.
 

Sermus

New member
Не понятно в таком случае вот что: почему бы не дать тогда просто выставить частоту SPI напрямую? Он-то ведь выставляется делителем относительно частоты ядра. Зачем такие экзорцизы, если тактовые генераторы независимы? Зачем связывать их тогда фиктивным делителем?
 

Sermus

New member
Не ядра, а частоты тактового генератора 80МГц.
Ну это сути-то вопроса не меняет, если тактовые генераторы независимы, зачем программный API устроен так, чтобы задавать соотношение между ними. Почему бы не дать возможность просто задавать частоту такта для SPI?
 

Andy Korg

Moderator
Команда форума
Почему бы не дать возможность просто задавать частоту такта для SPI?
Оно и независимо.
Выглядит это так

тактовый генератор (80 МГц) -->> делитель для SPI -- >> блок SPI
|
+---->> делитель для CPU --->> CPU
Подробнее можно прочитать тута
 

Sermus

New member
Я когда я выставляю частоту ядра 160, я что делаю - конфигурирую тактовый генератор или выставляю делитель для ядра в 0.5?

Если второе, тогда все понятно.
 

pvvx

Активный участник сообщества
Я когда я выставляю частоту ядра 160, я что делаю - конфигурирую тактовый генератор или выставляю делитель для ядра в 0.5?

Если второе, тогда все понятно.
REG_SET_BIT(0x3ff00014, BIT(0)); // меняет мультиплексор - переключает только шину тактирования ядра CPU к внутреннему делителю от общей PLL на выход 160MHz или 80MHz
os_update_cpu_frequency(160); // = ets_update_cpu_frequency(x) и запоминает значение x в памяти 0x3fffc704, чтобы отдать его по ets_get_cpu_frequency() и является чисто информационной, т.к. регистр переключения частоты шин CPU в 0x3ff00014 не читается (аппаратно не сделано его отображение - только установка/запись).
Все остальное у данного чипа работает со своими делителями от общей PLL.
I/O порты тактируются с периодом в 75ns (быстрее их не переключить), а SPI от своей тактовой, как и всё остальное.
 
Последнее редактирование:

Sermus

New member
Пришли железки. Получил первый рабочий вариант своей библиотеки для ILI9341. Удалось достичь примерно чуть более чем двухкратного увеличения pixel rate по сравнению с кодом уважаемого perfer. В основном за счет аппаратного управления CS (на выводе MTDO) и чуть более заточенной организации функций (минимальный набор параметров во всех функциях, однократное конфигурирование SPI только на передачу).
Заметил, что у трансфера по SPI есть какая-то странная дыра после передачи (ну или перед, не принципиально).
Вот код, который стреляет двухбайтными 0xFFFF в SPI:
Код:
    *spi_fifo = 0xFFFF;
    uint32_t bitcount = 2 * 8 - 1;
    WRITE_PERI_REG(SPI_FLASH_USER1(HSPI), (bitcount & SPI_USR_OUT_BITLEN) << SPI_USR_OUT_BITLEN_S);
    for (int i = 0; i < 100; i++)
    {
        SET_PERI_REG_MASK(SPI_FLASH_CMD(HSPI), SPI_FLASH_USR);
    }
На выводах получаем вот что:

Интересно, чем обусловлены паузы между передачами, которые съедают 30% пропускной способности?
 

Perfer

New member
Уважаемый Sermus, поздравляю Вас с получением "железок", а также с Вашим даром находить упущения в коде и исправлять их!
Расскажите нам всем, как вы смогли догадаться до аппаратного управления CS? Это немыслимо великолепный ход!
Меня, да я думаю и не только меня, захватывают Ваши достижения в части эффективнейшего использования памяти контроллера и непрерывного требования от последнего передачи Ваших данных по SPI. Это немыслимо круто!
Овации в честь Sermus :D
 

Sermus

New member
Ну как догадался? Мозгом подумал.
Очень жаль, что Вы восприняли мой пост как уничижение Ваших достижений, он таким ни в коей мере не был. Я крайне благодарен Вам за этот код, потому что он послужил хорошей стартовой площадкой для моих экспериментов.
Уж очень толстый сарказм, лучше б помогли.
 

Perfer

New member
А если без тролинга:
1) попробуйте не долбить HSPI постоянным выставлением бита на передачу и ждать окончания отправки содержимого буфера, хоть в начале хоть в конце.
2) проведите измерения на передачи двух двухбайтных сообщений, так будет чуть понятнее
3) если вам так нужна сверх производительность может стоит взглянуть на дизасемблировааный код?! Как это сделать я не знаю, думаю pvvx может подсказать
 
Сверху Снизу