Хейсан
Сб, 04 августа 2018 г., 19:25
(Используя ядро Роджера)
Играя сегодня, я заметил что -то довольно интересное:
В SPI_TX Libmaple:
Играя сегодня, я заметил что -то довольно интересное:
В SPI_TX Libmaple:
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
regs->DR = *dp8++;
Стивестронг
Солнце 05 августа 2018 г., 6:36
Можете ли вы предоставить простой эскиз для тестирования?
Вы используете отдельные записи или буферированные (несколько) пишет?
Потому что использование буферированного записи SPI.Напишите (BUF, NR_BYTES) будет почти так же быстро, как и с DMA, для менее чем ~ 70 байтов даже быстрее, чем с DMA.
РЕДАКТИРОВАТЬ
Если вы обратитесь к этим строкам: https: // github.com/rogerclarkmelbourne/ ... #L107-L108
Это для буферированной записи, и они оптимизированы, чтобы не дождаться окончания последнего перенесенного байта.
Но ожидание последнего байта должно быть где -то там, и поэтому он переведен в SPI.CPP: https: // github.com/rogerclarkmelbourne/ ... #L357-L358.
Я действительно не вижу никаких проблем с этим.
Edit2
Я думаю, что вы смешали, один байт пишет с буферированной записи.
Ваш экстракт из SPI.C для одиночной записи: https: // github.com/rogerclarkmelbourne/ ... #L327-L328, Это вызывает (встроенную) функцию spi_tx_reg, не смешивать с spi_tx !!!
Вы используете отдельные записи или буферированные (несколько) пишет?
Потому что использование буферированного записи SPI.Напишите (BUF, NR_BYTES) будет почти так же быстро, как и с DMA, для менее чем ~ 70 байтов даже быстрее, чем с DMA.
РЕДАКТИРОВАТЬ
Если вы обратитесь к этим строкам: https: // github.com/rogerclarkmelbourne/ ... #L107-L108
Это для буферированной записи, и они оптимизированы, чтобы не дождаться окончания последнего перенесенного байта.
Но ожидание последнего байта должно быть где -то там, и поэтому он переведен в SPI.CPP: https: // github.com/rogerclarkmelbourne/ ... #L357-L358.
Я действительно не вижу никаких проблем с этим.
Edit2
Я думаю, что вы смешали, один байт пишет с буферированной записи.
Ваш экстракт из SPI.C для одиночной записи: https: // github.com/rogerclarkmelbourne/ ... #L327-L328, Это вызывает (встроенную) функцию spi_tx_reg, не смешивать с spi_tx !!!
Хейсан
Солнце 05 августа 2018 10:37
Я буду войти и уйти в течение дня. Если мне удастся сесть достаточно долго, я подготовлю отдельный эскиз.
Вот где код предназначен для использования (добавлено в ADAFRIT_ILI9341_STM.час):
Вот где код предназначен для использования (добавлено в ADAFRIT_ILI9341_STM.час):
#ifdef _ADAFRUIT_FB_H_
void drawFB(int x, int y, Adafruit_FB1BPP& fb, uint16_t pal[]) {
if(x < 0 || y < 0 || x + fb.fbwidth() > WIDTH || y + fb.fbheight() > HEIGHT) return;
setAddrWindow(x, y, x + fb.fbwidth() - 1, y + fb.fbheight() - 1);
int iy, ix;
uint16_t p;
int bp = 0;
uint8_t m = 1;
int ms = 0;
for(iy = 0; iy < fb.fbheight(); iy++) {
for(ix = 0; ix < fb.fbwidth(); ix++) {
mSPI.writeAsync(pal[(fb.buffer[bp++] & m)>>ms]);
}
m <<= 1;
ms++;
if(m) {
bp -= fb.fbwidth();
} else {
m = 1;
ms = 0;
}
}
mSPI.writeAsyncEnd();
cs_set();
}
#endif
Стивестронг
Солнце 05 августа 2018 11:08
Ваш код кажется разумным.
Я предполагаю, что Array Pal [] содержит значения Uint16, поэтому вы используете SPI в режиме 16 -битного режима, справа?
Вы можете немного ускорить код, если заявите функцию writeAsync () как «встроенный» в файле заголовка.
Я предполагаю, что Array Pal [] содержит значения Uint16, поэтому вы используете SPI в режиме 16 -битного режима, справа?
Вы можете немного ускорить код, если заявите функцию writeAsync () как «встроенный» в файле заголовка.
Хейсан
Солнце 05 августа 2018 11:25
[Стивестронг - Солнце 05 августа 2018 11:08] - Ваш код кажется разумным.Спасибо - я еще не начал оптимизировать это. Это был быстрый хак, чтобы попытаться узнать, почему SPI.write () был таким медленным.
Я предполагаю, что Array Pal [] содержит значения Uint16, поэтому вы используете SPI в режиме 16 -битного режима, справа?
Вы можете немного ускорить код, если заявите функцию writeAsync () как «встроенный» в файле заголовка.
Мне было интересно, есть ли особая причина, по которой обертка Spiclass была написана таким образом, вместо того, чтобы использовать примитивы Libmaple (которые уже асинхронны)? Должен ли я потратить некоторое время на подготовку изменения в Spiclass или просто добавить отдельный класс асинхронных функций?
Хейсан
Солнце 05 августа 2018 11:27
В качестве примечания, рендеринг 240x240 инструменты типа набора теперь в 2 раза быстрее, чем рисунок непосредственно в библиотеку ILI9341, и Flicker Free .
Стивестронг
Солнце 05 августа 2018 17:40
[Хейсан - Солнце 05 августа 2018 11:25] - Мне было интересно, есть ли особая причина, по которой обертка Spiclass была написана таким образом, вместо того, чтобы использовать примитивы Libmaple (которые уже асинхронны)? Должен ли я потратить некоторое время на подготовку изменения в Spiclass или просто добавить отдельный класс асинхронных функций?Функции SPI LIB совместимы с Arduino, и я бы не предложил их изменить.
Ваше решение-нестандартная настройка, которая помогает в конкретной ситуации.
Как вы сами сказали, ваше заявление будет на самом деле хорошим кандидатом на двойную буферизованную передачу DMA.
Хейсан
Солнце 05 августа 2018 г. 20:56
[Стивестронг - Солнце 05 августа 2018 г., 17:40] - Функции SPI LIB совместимы с Arduino, и я бы не предложил их изменить.Spiclass.write () не является стандартной функцией ARDUINO API - она имеет только Transfer (), которая по определению должно быть синхронным. Но я вижу, что изменение функции стандартного write () на самом деле не будет практичной - в различных библиотеках недостаточно дисциплины в вызове EndTransaction () - поэтому вывод данных не будет гарантировано при любых обстоятельствах.
Ваше решение-нестандартная настройка, которая помогает в конкретной ситуации.
Как вы сами сказали, ваше заявление будет на самом деле хорошим кандидатом на двойную буферизованную передачу DMA.
В качестве альтернативы, что было бы вашими мыслями о перемещении _currentsetting от частного к защищенному, так что полученные классы можно сделать с помощью асинхронных функций? Я хотел бы избежать дополнительного штрафа памяти двух буферов DMA (особенно, когда возможный прирост производительности настолько мал), но я также не хочу, чтобы пользователям понадобилось пользовательское ядро для создания приложения...
Спасибо,
Джастин
Хейсан
Ср 8 августа 2018 г., 21:21
Наконец -то поступил с этим еще немного, и я делаю некоторый прогресс.
Сначала примечание. Часы SPI 36 МГц - я.эн. 2 часа процессора за бит. SPI пишет ширину 16 бит. Таким образом, есть 32 часа процессора, чтобы сохранить буфер SPI полным. Если вы можете сделать это, то конечный результат будет быстрее и использовать меньше памяти, чем реализация DMA.
Проблема в том, что 32 часа не так много .
В качестве ссылки я использую:
Сначала примечание. Часы SPI 36 МГц - я.эн. 2 часа процессора за бит. SPI пишет ширину 16 бит. Таким образом, есть 32 часа процессора, чтобы сохранить буфер SPI полным. Если вы можете сделать это, то конечный результат будет быстрее и использовать меньше памяти, чем реализация DMA.
Проблема в том, что 32 часа не так много .
В качестве ссылки я использую:
tfto.fillRect(0,0,240,240,0);
Стивестронг
Чт 09 августа 2018 г. 5:05 утра
Использовать директиву компилятора «-O3».
Хейсан
Чт 9 августа 2018 г. 8:11
Спасибо «-O3», доставляет его до скорости DMA для всех случаев - за 10% вспышки.
Как ни странно, любые попытки местных оптимизаций, например:
Как ни странно, любые попытки местных оптимизаций, например:
void __attribute__((optimize("O3"))) drawFB(int x, int y, Adafruit_FB& fb, uint16_t pal[]) {
Хейсан
Пт 17 августа 2018 г., 19:24
Я играл с этим еще немного, и мне все еще интересно...
Много работы было проведено, чтобы добавить слой DMA, и библиотеки портов к использованию DMA. Но, насколько я вижу, в каждом случае результат на самом деле больше, более медленный код.
Единственный способ получить реальное преимущество от DMA - это использовать dmasendasync, но текущий API не работает из библиотек, особенно если автобус обменивается.
По крайней мере, штат должен быть опробован в начале транзакции и эндранзакции, чтобы убедиться, что оно вернулось к SPI_STATE_READY (ASYNC TRANSFOR. Или это может быть сделано более прозрачным для разработчиков приложений путем проверки состояния на всех точках входа API.
Мнения?
Много работы было проведено, чтобы добавить слой DMA, и библиотеки портов к использованию DMA. Но, насколько я вижу, в каждом случае результат на самом деле больше, более медленный код.
Единственный способ получить реальное преимущество от DMA - это использовать dmasendasync, но текущий API не работает из библиотек, особенно если автобус обменивается.
По крайней мере, штат должен быть опробован в начале транзакции и эндранзакции, чтобы убедиться, что оно вернулось к SPI_STATE_READY (ASYNC TRANSFOR. Или это может быть сделано более прозрачным для разработчиков приложений путем проверки состояния на всех точках входа API.
Мнения?