Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

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

Тема в разделе "Другие проекты", создана пользователем Perfer, 1 фев 2015.

  1. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    Пример работы ESP8266 с 2,2" дисплеем на чипе ili9341 по SPI без внешнего MCU
    Вращающийся 3D кубик (зеленая плата на заднем плане FT2232H Board используется для перепрошивки):

    Проект на GitHub: https://github.com/Perfer/esp8266_ili9341
    В проекте расчет sin(x)/cos(x) производиться cordic методом, подробнее про метод: http://bsvi.ru/cordic-dlya-chajnikov/
     
    aliaksei, Sermus и Victor нравится это.
  2. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Уважаемый Gerber, смотрю код hspi.c и вот чего не понимаю. Функция записи в SPI-буфер разве не может быть реализована вот так:
    memcpy((uint8_t*)SPI_FLASH_C0(HSPI), data, numberByte)? Ведь, насколько я понимаю, камень работает в little-endian?

    Я еще не знаю, есть ли в поставляемых библиотеках memcpy, но сути вопроса это не меняет, почему нельзя заменить процедуру тупым побайтным копированием?
     
  3. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    Есть мнение что работать не будет, по вот таким соображениям: если почитать содержимое http://bbs.espressif.com/download/file.php?id=109&sid=8dae87d845a00f473dba015b7265be2e, а именно spi_reg.xls то там вот что написано:
    а значит memcpy точно должна обеспечивать доступ к регистрам как к 32 битным ячейкам памяти, т.е. просто так адресоваться к одному байту регистра нельзя, по этому большой вопрос по реализации memcopy.
    Также я пробовал сделать прямое обращение к регистра HSPI как к однобайтным ячейкам памяти - ничего не вышло, записывался только первый байт, остальные не устанавливались
     
  4. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Спасибо за наводку, интересно. Ну хорошо, допустим, что оно действительно допускает установку слова одномоментно, и попытка установить отдельный байт, например, сбрасывает три оставшихся байта в рамках слова. Тем не менее, почему тогда не сделать так (код для количества байт, выровненного по границе 4, чтобы не заморачиваться с определением хвоста, для сути вопроса это небольшой урон):
    Код (Text):
    1. for (int wi = 0; wi < numBytes/4; wi++)
    2.     ((uint32_t*)SPI_FLASH_C0(HSPI)) [i]= ((uint32_t*)data) [i];
    Зачем здесь необходимы сложности с перепаковкой. Пытаюсь осознать чего я не понимаю.

    И второй вопрос. Если размер SPI-буфера 16 слов, почему у Вас размер промежуточного буфера 32 байта? Это с какой-то целью сделано?
     
  5. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    1. А если numBytes % 4 != 0 то тогда часть данных не отправится, правильно?
    2. Подождите: dword = 32 бита, word = 16 бит. Регистры HSPI у нас 32 битные поэтому 8 * 32 = 256 бит = 32 байта - кажется все корректно. Да и если посмотреть то MAX_SIZE_BUFFER нигде по делу не используется, а объявление локальной переменной (uint8_t dataBuffer[MAX_SIZE_BUFFER];) можно выкинуть
     
  6. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    1. Да, это так, но к сути вопроса это не имеет отношения, поэтому я не стал усложнять пример для учета хвоста, который на выровнен по границе 4.
    2. Почему слово - 16 бит? Для этой архитектуры слово 32-битное. В приведенной Вами же выше цитате, написано, что размер SPI-буфера 64 байта или 16 слов. Отсюда мой вопрос, почему у Вас в коде размер буфера 32 байта?
     
  7. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    1. Я сразу решил написать общий случай, а не дописывать потом обработку хвоста. За максимальной производительностью не гнался. Если вы проведете тесты и покажете что вами модифицированный код работает быстрее, то - wellcome, кидайте pull-request приму изменения
    2. Хмм.... настойчивость это хорошо. Читаем spi_register.h:
    Код (Text):
    1.  
    2. #define SPI_FLASH_C0(i)                             (REG_SPI_BASE(i) +0x40)
    3. #define SPI_FLASH_C1(i)                             (REG_SPI_BASE(i) +0x44)
    4. #define SPI_FLASH_C2(i)                             (REG_SPI_BASE(i) +0x48)
    5. #define SPI_FLASH_C3(i)                             (REG_SPI_BASE(i) +0x4C)
    6. #define SPI_FLASH_C4(i)                             (REG_SPI_BASE(i) +0x50)
    7. #define SPI_FLASH_C5(i)                             (REG_SPI_BASE(i) +0x54)
    8. #define SPI_FLASH_C6(i)                             (REG_SPI_BASE(i) +0x58)
    9. #define SPI_FLASH_C7(i)                             (REG_SPI_BASE(i) +0x5C)
    10.  
    Считаем:
    (REG_SPI_BASE(i) + 0x5C + 0x04) - ( REG_SPI_BASE(i) +0x40 ) + 0x01 = 0x20 = 32
    или я вас не правильно понял?
    PS вы сами себя запутали с размерами и понятием слова
    PSS прошу обратить внимание что MAX_SIZE_BUFFER на самом деле не нужен в текущей реализации
     
  8. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    А где путаница? Слова 4-ехбайтные, вопрос в их количестве. Опираясь на первую выдержку из документа, которую Вы привели, размер буфера - 64 байта, т.е. 16 слов по 4 байта, что явно написано в выдержке. Это и породило вопрос про размер буфера у Вас в hspi.c.
    И кстати, размер используется например так: tft_setPixel -> transmitData(uint8_t *data, uint8_t numByte, uint32_t numRepeat) -> hspi_Tx(uint8_t * data, uint8_t numberByte, uint32_t numberRepeat), а там уж по крайней мере стоит выход без передачи по превышению порога MAX_SIZE_BUFFER.

    Я понимаю, что наверняка в коде складываются условия, в которых эта проверка никогда не стреляет, но... Это только потому что трансфер, видимо, неоптимален. Ну, например, закрашивать прямоугольник можно было бы не двухбайтными посылками, а 64-хбайтными, что было бы эффективнее.
    Собственно, это утверждение и есть корень вопроса про размер spi-буфера.
     
  9. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Ладно, разговор, видимо, перейдет в стадию гадания на кофейной гуще на почве недосказанности и противоречивости в китайской документации. В одном месте действительно написано, что 16 слов, в другом - 8. Придет ко мне железка, посмотрю. Заодно и проверим теорию про скорость трансфера пачками большего размера.
     
  10. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    В hspi.c не просто так оставлен закомментированный код - разберитесь что он делает, помниться он был рабочим, ток что-то до определить придется.
    Про слова и их кол-во почитайте еще описание в ESP8266 HSPI透传协议(2中断线).doc лежит в архиве по ссылке выше (переводить лучше на английский). Если кратко, то получается не очевидное использование регистров spi_w8~spi_w15 в режиме spi-master
    Все уже проверенно, если честно :) Правда я за сверх производительностью не гнался.
    А так можно еще много чего с оптимизировать - только вопрос ЗАЧЕМ? :)
     
    Последнее редактирование: 12 фев 2015
  11. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Так закомментированный код работает или нет? Как зачем? Чтобы кубик на Вашем видео не моргал.
    А если серьезно, то нарисовать более или менее адекватный UI при малой скорости рисования просто нереально. У меня есть библиотека от Adafruit для ILI9341 для Ардуины, страсть какая медленная, но она мне функционально нравится. Я ее для Atmega ускорил на 1.5 порядка (не в полтора раза, а в 16) за счет переезда с bitbanding на аппаратный SPI. После этого даже на убогой восьмибитной атмельке стало возможно рисовать полноценный UI.
    Хочу портировать (на самом деле уже портировал, но не железки пока для проверки) эту библиотеку на ESP8266. И хочется, чтобы она сразу быстро работала.

    Еще из замечаний - ожидание конца передачи в hspi_Tx. Зачем? Лучше ведь перед передачей убедиться, что предыдущая передача закончилась. А в конце не ждать - отпустить процессор, пусть он в это же время готовит данные для следующей передачи, а не ждет конца текущей.
     
  12. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    А это привычка :) Согласен надо поправить
    Можно вообще от while уйти в сторону конструкций case/ifelse - получиться некий конечный автомат
    Я вот это портировал https://github.com/gmtii/ili9341-arduino
     
  13. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Эту я тоже видел, но мне там не хватает шрифтов. В общем, железка приедет - опробую то, что понаписал.
     
  14. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    8.396
    Симпатии:
    1.271
    У SPI на ESP8266 есть "FIFO":
    Код (Text):
    1.  
    2. 60000100: 00000000 00000000 0028b313 5fff0120  ........._(. .я_
    3. 60000110: 00000000 00000011 80003043 80000044  ........C0._D.._
    4. 60000120: 5c000000 70000000 00000000 0000001e  ...\...p........
    5. 60000130: 00000200 02000000 00000000 00000000  ................
    6. 60000140: a7d40e60 f481f81d 2c3034c3 be1b9b31  `.Ф.ш_фГ40,1>._
    7. 60000150: 2352dda8 04960cf7 4c422943 7d60ce8d  ЁЭR#ч.-.C)BL_О`}
    8. 60000160: 0b08d192 bf3651d2 2de1b158 45dae09d  'С..ТQ6їX+б-_аЪE
    9. 60000170: 0b31b142 61c64f30 e9415914 8afa1be5  B+1.0OЖa.YAйе.ъ_
    10. 60000180: 00000000 00000000 00000000 00000000  ................
    11. 60000190: 00000000 00000000 00000000 00000000  ................
    12. 600001a0: 00000000 00000000 00000000 00000000  ................
    13. 600001b0: 00000000 00000000 00000000 00000000  ................
    14. 600001c0: 00000000 00000000 00000000 00000000  ................
    15. 600001d0: 00000000 00000000 00000000 00000000  ................
    16. 600001e0: 00000000 00000000 00000000 00000000  ................
    17. 600001f0: 800a0050 800f0258 00000000 00000000  P.._X.._........
    18. 60000200: 00000000 0801799a 016ab000 5fff0120  ...._y...°j. .я_
    19. 60000210: 00000000 00000011 80000000 80000064  ..........._d.._
    20. 60000220: 5c7e3f1f 70000000 00000000 0000001e  .?~\...p........
    21. 60000230: 00000210 02000000 00000000 00000000  ................
    22. 60000240: 64786568 7e64706d 7463657e 6d61722f  hexdmpd~~ect/ram
    23. 60000250: 6e69622e 6c627e00 6d61726b 0000297e  .bin.~blkram~)..
    24. 60000260: 5d841651 49ddae04 ef2baf7f b2b07b5c  Q."].RЭI.Ї+п\{°_
    25. 60000270: 261fa13c 800b0c75 439152b1 bc1e7b8e  <Ў.&u.._+R'C_{._
    26. 60000280: 00000000 00000000 00000000 00000000  ................
    27. 60000290: 00000000 00000000 00000000 00000000  ................
    28. 600002a0: 00000000 00000000 00000000 00000000  ................
    29. 600002b0: 00000000 00000000 00000000 00000000  ................
    30. 600002c0: 00000000 00000000 00000000 00000000  ................
    31. 600002d0: 00000000 00000000 00000000 00000000  ................
    32. 600002e0: 00000000 00000000 00000000 00000000  ................
    33. 600002f0: 800a0050 800f0258 00000000 00000000  P.._X.._........
    34.  
    0x60000140 и 0x60000240...
     
    Последнее редактирование: 13 фев 2015
  15. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
  16. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    8.396
    Симпатии:
    1.271
    Это всё известно, но тут пытались спорить о размерах...
    Разработка ‘библиотеки’ малого webсервера на esp8266 для этих целей в основном и делалась - чтобы отлаживать на живую и смотреть "что тама". Для более глубоких исследований надо писать полный отладчик с break-points.
     
  17. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Просветите, пжлста, меня, убогого, а как из дампа видно, что это fifo для spi?
     
  18. Perfer

    Perfer Новичок

    Сообщения:
    27
    Симпатии:
    3
    Товарищ pvvx говорит не про факт наличия FIFO, а про его размер.
    Сегодня проверил что с значением MAX_SIZE_BUFFER = 64 тоже все работает и корректно отображается - правда кубик быстрее (с меньшим количеством рывков) крутиться не стал, а вот с оптимизацией функций setCol и setPos - стал. Обновления в репозитории
     
  19. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    8.396
    Симпатии:
    1.271
    Там отображается то, что читалось. А это не память, a область регистров.
    -------
    Перед вычислением включите CPU на 160MHz:
    REG_SET_BIT(0x3ff00014, BIT(0));
    os_update_cpu_frequency(160);
    По окончанию можно обратно на 80MHz:
    REG_CLR_BIT(0x3ff00014, BIT(0));
    os_update_cpu_frequency(80);
    Но SDK сама поправит через время на 80MHz...
    Это ускорит исполнение ваших расчетов, но не I/O...
    Бояться не стоит, так штатно поступает SDK при включении SSL и общий ток и нагрев сильно не растет (больше греет WiFi и I/O).
     
    Последнее редактирование: 14 фев 2015
    tonal, Sermus и Perfer нравится это.
  20. Sermus

    Sermus Читатель

    Сообщения:
    110
    Симпатии:
    15
    Я подозреваю, что он стал крутиться после ампутации магии с перекладыванием байтиков во writeDataToBuffer (зуб даю, она теперь выполняется в 5 раз быстрее), а не оптимизации setCol и setPos. Не понятно, как не посылка команд установки окна в случае, если перед этим было установлено то же самое окно, может помочь, если окно выставляется все время разное, т.е. фактически, "экономный код" не работает. Или я не прав?

    А быстрее крутиться из-за увеличения размера буфера он скорее всего не стал потому что:
    1) Есть лишний промежуточный буфер (который как раз размера MAX_BUFFER_SIZE). Почему бы не писать из пользовательского буфера сразу в SPI FIFO?
    2) Ждите окончания посылки не после начала передачи, а перед началом следующей
     

Поделиться этой страницей