STM32F746GDISCOVERY. Продолжение индустриального графического интерфейса

Эта отладочная плата была приобретена в направлении других горизонтов развития, однако, как и прежде, с чего-то нужно оживлять железо. Эти отладочные платы с мониторчиками и Toush Screen – прежде всего прекрасный набор кнопок (черная и голубая в набор не входят).

Чего не хватало в предыдущем проекте калькулятора? – В основном памяти для картинок. Здесь в полном распоряжении 16 Мбайт QSPI. Можно ни на чем не экономить.

При попытке использования более-менее свежего железа всегда возникают неожиданности.

Не смотря на то, что MXCube предлагает выбор версии IAR для генерации кода, 7-я версия выдала кучу ошибок, устранить которые я не смог.

8-я версия IAR выдала ошибки инициализации DMA2D в режиме DMA2D_M2M_BLEND, обругав 2 параметра. Поскольку эти параметры мне были особо не нужны, я их просто убил.

9-я версия IAR порадовала еще больше! Она запросто сказала, что в каталоге
C:\Program Files\IAR Systems\Embedded Workbench 9.0\arm\config\flashloader\ST нету файла
FlashSTM32F7xx_STM32F746G-DISCO.board и отказалась работать с проектом…

Ну так я скопировал туда этот и еще 2 файла из аналогичного каталога восьмой версии
FlashSTM32F7xx_QSPI_STM32F746G-DISCO.flash
FlashSTM32F7xx_QSPI_STM32F746G-DISCO.mac
И ведь все снова заработало!

STM32 Cube Programmer чистит и пишет external memory ничуть не хуже STM32 ST-LINK Utility. Нужно только добавить (выбрать) в External Loader N25Q128A-STM32F746G-DISCO.

В IAR есть кнопочки Download and Debug и Debug without Downloading

Так вот, если в программе оставить только функции инициализации и ничего значимого не делать, то при нажатии Download and Debug IAR отрабатывает Debug without Downloading. То есть загрузчик не отрабатывает и, соответственно, данные во flash память не грузятся! В примере грузятся, у Вас не грузятся. Можно хорошо скоротать несколько дней!

SDRAM

Несколько озадачило начало работы. Через программатор все работает и светится. Однако, если отключить питание и включить автономно на экране начинает все дрожать, а то появляется и совсем не пойми что. Если понажимать RESET, то вроде как все встает на свои места и начинает работать. Но со стороны комично. В STM32F429i_Discovery такого не было.

Серьезные пацаны подметили, что если включить правильное питание (жрет она 0,6 А), то не дрожит. Все, что нашел в интернете, так у кого-то были плохие конденсаторы возле SDRAM. Посмотрел через хорошую лупу – у меня точно не треснувшие!

Проблема все-таки в SDRAM. При инициализации дисплея, мы сразу привязываем его к определенным адресам буферов. А вот что на момент инициализации в этих адресах лежит не всегда понятно. При серьезном питании память, видимо, сбрасывается. При питании от USB компьютера не всегда.

//В примере STM32CubeExpansion_AN4749_F7_V1.0.0 
//main.c строка 152:

            /* Copy picture from QSPI to SDRAM */     
            memset((void*)SDRAM_DEVICE_ADDR, 0, 130560*sizeof(uint16_t));
memcpy((void*)SDRAM_DEVICE_ADDR,
(void*) &RGB565_480x272_SDRAM, 130560*sizeof(uint16_t));

//Это действо проводится до инициализации GUI.

Помогло! Нажимать смущенно черную кнопку после этого не нужно! Особенно я бы обратил внимание на pLayerCfg1.FBStartAdress. Поскольку уровень по цвету урезанный, то его использование не всегда очевидно, как и аппаратные телодвижения с ним разработчиков.

MPU (memory-protection-unit)

В LCD-TFT display controller (LTDC) on STM32 MCUs есть пример настройки MPU для нашей отладочной платы.

Данные в SDRAM там буферизованы для использования DMA2D,
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
поэтому после использования функций библиотеки stm32746g_discovery_lcd.c вперемешку с DMA2D нужно выдавать команду SCB_CleanDCache();

Рассуждения на эту тему можно почитать в обсуждении:
https://kincajou.livejournal.com/4160197.html

Переводы AN4838, AN4839:
http://microsin.net/programming/arm/an4838-managing-memory-protection-unit-stm32.html
http://microsin.net/programming/arm/an4839-level-1-cache-stm32f7.html

QSPI

В CubeMX лапки выставить как в проекте STM32F746GDISCOVERY по умолчанию.

Настройку параметров лучше подсмотреть в примере QSPI_perfs
…Repository\STM32Cube_FW_F7_V1.15.0\Projects\STM32746G-Discovery\Applications\QSPI\QSPI_perfs\EWARM
поскольку в последнем показывается крутость производительности.

Кто не любит EWARM, нашел случайно ссылку по работе с QSPI по VisualGDB
https://sysprogs.com/w/forums/topic/using-the-quadspi-on-stm32f7-discovery/

В примере разработчики пишут в QSPI данные в формате unsigned char. Если работать со словами данных – все тоже получается. (См. STM32CubeExpansion_AN4749_F7_V1.0.0). Однако при подготовке файлов для вывода на LCD через DMA2D в формате байтов а не слов, есть нюанс.

В примере QSPI_perfs добавлена куча настроек IAR

// C/C++ Compiler --> Preprosessor -->
Defined symbols (one per line)
USE_HAL_DRIVER
STM32F756xx
USE_STM32746G_DISCO
__DBG_ITM
ARM_MATH_CM7
// Linker --> Config
$PROJ_DIR$\stm32f746xx_QSPI_flash.icf 

Это линкер c секцией QSPI. Файл в текстовом формате. Можно посмотреть, можно и редактировать. Секцию .textqspi можно назвать по любому и без точки. Однако .text символизирует код и данные.

// Linker --> Input
__iar_sh_stdout_swo 
// Debugger --> Download
$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32F7xx_STM32F746G-DISCO.board 

Дальше начинается самое интересное…

В примере QSPI_perfs есть файл main_images.c.

В описании AN4760 (раздел. 5.1.1 Генерация содержимого буфера кадра из памяти QSPI): «Все изображения и значки, необходимые для приложения, должны храниться во внешней памяти QSPI. В проекте доступно шесть изображений и три иконки, все они включены в файл «main_images.c», где каждое из них определяется как константа в отдельном заголовочном файле.»

Вроде бы все понятно… В stm32f746xx_QSPI_flash.icf мы создаем (уже создан разработчиками STM) раздел для памяти QSPI и директивой #pragma location = «.textqspi» мы обозначаем, что эти константы в этот раздел грузим.

Удобная штука. Все, что в «main_images.c» прописано, начинает грузиться в QSPI. Можно использовать в отдельном проекте, ничего из периферии не описывая. (Такой проект у меня вложен в основной.) Если изменить имя файла, то грузиться не будет. При этом нужно использовать линкер stm32f746xx_QSPI_flash.icf и загрузчик FlashSTM32F7xx_STM32F746G-DISCO.board. Пустую функцию dummy_init в файле «main_images.c» я тоже нигде не нашел. Возможно это намек, что именно так грузить нужно не только данные, но и код.

В следующем разделе AN4760 (5.1.2 Отображение изображений непосредственно из памяти QSPI). На этот пример (AN4749 поставляется с программным пакетом X-CUBE-LPDEMO-F7) я уже ссылался. Точно так же описываются данные. Файла main_images.c уже нет, зато в файле «nenu.c» есть функции WM_HWIN Createloadpicturefrom(void) библиотеки emWin version 5.28, описания которых я тоже поверхностно не нашел.

То есть по файлу «main_images.c» все гуманно! Работает, но не понятно как. Если кто-нибудь проникся, найдите время, пожалуйста, ПОДЕЛИТЕСЬ!

В описании AN4760 есть еще интересный подраздел «Как осуществлять программирование QSPI Flash memory только один раз».
В оригинале QUADSPI AN4760 pg. 58
How to proceed to program QSPI Flash memory only once… for IAR EWARM

Долго пытался разобраться. Так и не понял…
В Гугле ничего не нашел. Задал вопрос на форуме STMicroelectronics. Получил следующий ответ:

clive1 (NFA Crew) (Community Member)
2 months ago
If they are not part of your application image, I’d suggest writing some code to combine them, providing a table the app can access, and output them as a .HEX file, with an address starting at 0x90000000
Write that image with the STM32 Cube Programmer, using the External Loader for the QSPI memory (N25Q128 as I recall), and don’t tell IAR about it. Have you application set up the QSPI memory, and then access your table/images from there using normal memory access, ie pointers, structures, etc.

Что, собственно, и реализовано в файле QSPI_Addr_Table.h с использованием препроцессора …#ifdef IMG_NO_DATA

Но мне кажется, что это не изящно. Если кто-нибудь разобрался, пожалуйста, ПОДЕЛИТЕСЬ!

Touch panel FT5336

К stm32746g_discovery_ts.c как-то сразу возникло много вопросов…

Например функция BSP_TS_GetState, которая возвращает в строке 357 в качестве статуса
ts_status = BSP_TS_Get_GestureId(TS_State);
GestureId ну просто не работает и возвращает всегда ноль. Это не мешает разработчикам, поскольку в дефайнах статус «ОК» тоже ноль.

Строка 415 BSP_TS_ITClear с комментарием /* Clear TS IT pending bits */

Смотрим ft5336.c строка 425 /* Nothing to be done here for FT5336*/

Запросто включают и выключают режим прерываний, который не выключается, а переключается из Interrupt polling mode в Interrupt trigger mode и обратно.

Понимание обработки событий после некоторой исследовательской части окончательно у меня так и не сложилось. В проекте закомментированы функции, отображающие на экране счетчики этих самых событий. Кому интересно, можно посмотреть.

Пришлось довольствоваться обработкой внешнего прерывания, описав

 /*Configure GPIO pin : TS_INT_Pin */
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; 

Работает как кнопка. Нажал – первое прерывание, отпустил – второе. Пока держишь TOUCH_EVENT_CONTACT. Если нажимать кнопки быстрее, чем считает TIM7, то «отжатие» теряется. Для этого пришлось добавить Flag_Lift_Up – обработку этого «отжатия».

Однако и тут промелькнула интересная деталь (хотя может быть я написал плохой обработчик). В моем алгоритме прерывания обрабатываются в зависимости от порядка их следования. При нажатии начинается опрос Touch panel пока мы не уберем руку. При «отжатии», опрос клавиш проходит только один цикл. При длительной работе калькулятора порядок этих событий иногда почему-то менялся. Это могло происходить либо из-за каких-то заморочек с volatile переменными, либо из-за каких-то помех по шине EXTI.

Так или иначе я добавил сброс флага EXTI по окончании прохода опроса кнопок при установленном флаге Flag_Lift_Up и убрал волонтльность последнего. Проблема, вроде, ушла.

В сам калькулятор добавлено:

Тригонометрия.
Если ничего не введено, то при нажатии pi это pi и выводится. Можно использовать, как операнд.  Если какие-то цифры введены, то они считаются градусами и переводятся в радианы. При этом устанавливается флаг. Если нажать еще раз, обратно в градусы. Флаг чистится. Чистится флаг еще по «С» и «СЕ».
Sin, Cos, Tan считаются из операнда в зависимости от флага в градусах или радианах. То есть если флаг не включен, то функция сама переводит градусы в радианы, но флаг не устанавливает. Если флаг установлен, то считает, что угол в радианах и тоже флаг не сбрасывает.

Вывод случайного числа от нуля до единицы с пятнадцатью знаками после запятой – rand.
Алгоритм генерации HAL_RNG_GenerateRandomNumber. Генерируются два целых 32-х разрядных числа. Переводятся в строки. Вторая приклеивается к первой. Старшие цифры обрезаются до 15. Дописывается 0. Распределение не смотрел.

Операторы div и mod выводят целую и дробную части числа со знаком в формате целых чисел.

Осторожней со степенной функцией… Все-таки STM32. ))))))))))

Проект в IAR v8.40.1.21539

Примечания и дополнения:
В настройках CubeMX (файл calculator_746G_DIS.ioc в архиве) нужно поменять в настройках FMC:
FMC_SDRAM_CAS_LATENCY_3

В IAR проекте правильно, а в настройках CubeMX забыл поправить.

С уважением Петр.

Реализуем коммерческие проекты.
Возможна работа по договору подряда.

t654rk@mail.ru

5 ответов к «STM32F746GDISCOVERY. Продолжение индустриального графического интерфейса»

  1. Здравствуйте. Откуда утверждение: «Особенно я бы обратил внимание на pLayerCfg1.FBStartAdress. Поскольку уровень по цвету урезанный…«? По ссылке с Вашего, же, ресурса: «LTDC может быть сконфигурирован с до восьми программируемых форматов входных цветов для каждого слоя». Ну и картиночка (рис. 18) там же.

  2. У STM пример есть с двумя слоями. Есть видео уроки от дядьки в кепке. Везде второй слой кастрированный. Все, что у меня получилось, кажется, 1RGB, вместо ARGB.
    Я в своей задаче исходил из того, что мне было нужно.
    В f429 есть отличия в регистрах DMA2D в первом и втором каналах. Может и f746 есть, я не смотрел особо.
    Хуже, что Touch Screen, прерывания фиг поймешь как работают и точно не работает заявленная обработка жестов.
    Мне второй уровень был нужен, чтобы просто временно накрыть первый, чтобы было не видно, как нажимаются кнопки, когда я имитирую жест.
    Еще разрешение прерывания по ватерлинии сбрасывается после каждого прерывания. Нужно устанавливать по новой.
    Наверно интересно поиграться, подсовывая разные буферы SDRAM по этому прерыванию в адрес дисплея. Вроде так должно работать кино.
    Все зависит от задачи.

  3. Спасибо. С двумя слоями я, все же, проведу эксперимент немного позже, ибо не оставляет в покое табл.11 из AN4861 согласно которой 32/32 с макс. частотой клока в 12Мгц все же возможна. Правда, сноска (3) ввела меня в ступор — я так и невкурил в смысл написанного: «LTDC fetches the front buffer from the external memory while the DMA2D transfers data from backbuffer to frontbuffer.»
    На скорую руку попробовал подсовывать буферы SDRAM, но по биту VSYNCS регистра LTDC_CDSR:

    while (!(LTDC->CDSR & LTDC_CDSR_VSYNCS));
    fr_buff_replace( 1 );

    void fr_buff_replace( uint8_t frbuff ) {
    LTDC_LayerCfgTypeDef pLayerCfg = {0};
    if( frbuff ) {
    pLayerCfg.FBStartAdress = 0xC007F800;
    }
    else {
    pLayerCfg.FBStartAdress = 0xC0000000;
    }
    if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) {
    Error_Handler();
    }
    }

    С наскока не получилось. Наверно, не правильно меняю адрес буфера в настройках LTDC.

  4. В документации на f429 (одна из статей в этой же рубрике) документ AN4861 мной переведен:
    Возможно это другой AN4861 ))) Я его скачивал года 3-4 назад, но там нет третьей сноски в таблице 11.
    Блин, точно поменялся… Ввалили серии H и L. Вэк живи, вэк учись! )))))))
    LCD-TFT display controller (LTDC) on STM32 MCUs (Rus)
    В конце документа они приводят пример «правильной» настройки LCD. Из чего я и исходил и в f429, и в f746.
    Я закончил этот проект около года назад, поэтому помню уже не все.
    Были какие-то проблемы и модификацией параметров дисплея на лету. По-моему они решены в библиотеке BSP.

    В f746 есть чего много из-за чего может не все получаться, например настройки MPU. Так, например, при чередовании DMA2D и этих самых функций из BSP, нужно чистить SCB_CleanDCache();

    Кроме того, во всяких шустрых проектах, я бы исходил из камеры. которую можно подключить к разъему на плате. По моему она не 32-битная.
    Так вот в этих «правильных» настройках используется уже цветовой режим 5R6G5B. Зато получается удобный для кэширования буфер 512К.

    Я точно все не пробовал

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.