![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
MementoMori
Свой-
Постов
1 340 -
Зарегистрирован
-
Посещение
Весь контент MementoMori
-
Не могу подружить SDRAM и LTDC
MementoMori ответил MementoMori тема в ARM
Господа, может я пытаюсь совместить несовместимое? У меня дисплей 1024х600. Цвет RGB888. Размер кадра получается 1 843 200 байт 1 слой, планируется использовать DMA2D (контроллер STM32F746BG) Память SDRAM 32 бит. Пиксельклок дисплея - не менее 40 МГц (реально он стабильно но с мерцанием работает на 30 МГц) но не более 65 МГц Согласно Аппноуту максимальный пиксельклок для этих параметров 52 МГц. Я пока экспериментирую с RGB565 и без DMA2D - то есть 83 МГц Способна ли эта связка, исходя из указанных параметров работать или нет? У меня пока результаты неутешительны Стабильную картинку удалось получить только на пиксельклоке 30 МГц и объеме кадра 200х200 пикселей. С внутренней SRAM таких проблем нет. А вот со SDRAM или встроенной FLASH - картинка дергается и изображение корежит. Тактирование вот такое -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Господа это абсурд!!!!! Картинка перестала дрожать лишь тогда, когда я уменьшил пиксельклок до 30 МГц, а размер окна до 200х200 пикселей, формат цвета RGB565. Правда даже в этом случае есть какой-от глюк, цвет 0xF800 дает розовый квадрат, хотя по идее это чистый красный. Так.... скажите мне, какова пропускная способность памяти SDRAM 32 бит на частоте 108 МГц? Можно ли как-то практически средствами контроллера измерить ее? Ну не может такого быть чтобы SDRAM+LTDC не мог потянуть кадр больше 80 кб... -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
При указании в качестве адреса буфера FLASH памяти тоже дрожание. Какой бы я адрес ни указал. -
Не могу подружить SDRAM и LTDC
MementoMori ответил MementoMori тема в ARM
Хех... подружить-то я подружил, но они живут как кошка с собакой. Подробности здесь -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Вникаю в предмет... Скажите, а MPU может помочь? Я сделал как в одной статье Правда там почему-то адрес SRAM (хотя статья про настройку SDRAM), но я попробовал поменять адрес на 0x20010000 - не помогло. Что-то не так или это тупиковый путь? -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Опять таки, простите мне мою необразованность - но разве верхушка стека не в старших адресах располагается? Вот как выглядит красный прямоугольник на экране, если расположить буфер по адресу 0x2000FF00 А вот, как его корежит, если в качестве адреса буфера указать 0xD0000000, то есть SDRAM (это картинка, в динамике изображение дрожит и шумит) -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
ЕСТЬ НЕБОЛЬШОЙ РЕЗУЛЬТАТ!!!! Выяснено, что если располагать буфер в SRAM по адресу 0x2000FF00, то дрожание полностью прекращается. На единицу меньше - появляются глюки. Я любитель и в некоторых аспектах матчасти разбираюсь плохо. Еще один минус моего любительства - слепая вера чужому коду, который, если его выложили, очевидно рабочий. Вот где в этом чужом коде была собака зарыта volatile uint32_t RGB565[5000] = {0x00000000}; uint32_t i; HAL_LTDC_SetAddress(&hltdc,(uint32_t) &RGB565,0); for(i=2000;i<4500;i++) { *(__IO uint16_t*) (hltdc.LayerCfg[0].FBStartAdress + (i*2)) = 0x00ff; } while (1); Только сейчас я понимаю его несуразность - объявить переменную, которой компилятор присвоит некий адрес и разместить начало буфера по этому же адресу. Хотя и в младших адресах и в старших могут быть еще переменные. Просветите невежду, может быть так, что в процессе создания и уничтожения локальных переменных образующиеся пустые места не остаются без внимания системы и происходит "уплотнение" памяти? ПОнятно теперь, почему начало буфера плавало. Но..... проблемы то со SDRAM это не решает. Ладно, пытаясь разместить код в SRAM, я рисковал разворошить осиное гнездо. Но по адресу 0xD0000000 должно быть спокойно. Продолжаю копать... -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Запустил тест на 100 циклов. Ни одной ошибки SDRAM. 10 раз сработало прерывание ошибки LTDC. Всего 10 раз. Да черт возьми, что ж там с чтением адреса? Может быть контроллер дефективным? Неохота его перепаивать. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Не знаю. По идее, если где-то поставить точку останова, процессор останавливается. Пробовал, к положительному результату со стороны дисплея это не приводит. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Хорошее уточнение. Вы правы - дергается то вся картинка. Если бы были пропуски, то дергались бы фрагменты в случайных местах и случайной длины. А это может быть следствием того, что кто-то еще занимает шину? Это плохо? Вот здесь товарищ эррату цитировал Но я так понял, это только для статической памяти и FMC. А у меня проблема даже с встроенной SRAM.... -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
10 циклов. Ошибок нет. P.S. В целом то ситуация полезная. Мои знания STM32 весьма поверхностны. Ища ошибку я хоть и не досконально, но весьма детально разобрался в некоторых ключевых моментах. Если бы все было как с платой дискавери (на которой я за полчаса не то что дисплей настроил - проект TouchGFX запустил), я бы некоторых вещей не узнал. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Вот так? srand(1); for (uwIndex = 0; uwIndex < 4194304; uwIndex++){ *(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*uwIndex) = rand(); } srand(1); for (uwIndex = 0; uwIndex < 4194304; uwIndex++){ if (*(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*(uwIndex)) !=rand()) err=1; } -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Уменьшил тайминги дисплея, перекроил его под формат 400х200 пикселей. То есть дал контроллеру LTDC время отдохнуть. Подождать, пока придут данные и не сталкиваться с ситуацией когда буфер FIFO пуст - все равно шум. Да и, как я уже сказал - не ловятся больше прерывания ошибки шины и пустого буфера. Вот жеж черт, ведь где-то в одном каком-то месте кроется ошибка.... неделю бьюсь.. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Простите, не совсем понял о чем речь. Просто изменить srand() на srand(0xFFFFFFFF)? "rand() - srand(N) " - это операция вычитания или указание диапазона? К слову - вариант, который я назвал джедайским, все же дает весьма разноцветную картинку. Полоски неподвижны. Это видеоэффект. Я полагаю это те редкие моменты, когда чтение идет без сбоев. У меня на плате дискавери SDRAM отображается в виде шумной, но статичной картинки. Впрочем, поясните мне то, что я спросил про srand - проверю. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Вот видео. https://cloud.mail.ru/public/kNQS/4SvaLUzJ6 Зеленое - это фон LTDC - как видите, контуры его ровные, неподвижные - то есть с сигналом от LTDC к дисплею и с самим дисплеем все нормально, никаких наводок - пиксель к пикселю. Большое прямоугольное окно - первый слой, он черпает данные из SRAM - внизу синяя линия (то что я записал), вверху какой-то мусор. Это проекция всей SRAM в дисплей. Маленькое квадратное окошко - второй слой, он спроецирован в SDRAM. Белая полоса внизу - то что я записал. Остальное - мусор. Это проекция фрагмента SDRAM во второй слой. Если вы обратите внимание - мерцание не хаотичное, а сформированная шумная картинка дрожит целиком. Не надо быть таким перфекционистом. Я понимаю, если бы я ловил мерцающий раз в час пиксель. Даже когда я заполнял одинаковыми байтами, картинка на экране оставляла желать лучшего, зато тест теми же байтами не дал ни одной ошибки. Слишком большие отличия в результате тестов, чтобы говорить о дефекте SDRAM. Картинка шума не меняется, текстура ее постоянна, дрожат линии, из которых она состоит. Может память так глючить, чтобы выдавать правильные данные, но с меняющейся задержкой? Ну как если бы вы на ходу CAS меняли с 3 до 40-50? Нет. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Вот вам джедайский тест test_iteration=0; srand(); for (j=0;j<10;j++) { test_iteration++; for (uwIndex = 0; uwIndex < 4194304; uwIndex++) { TEST_BYTE=rand(); *(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*uwIndex) = TEST_BYTE; if (*(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*(uwIndex)) !=TEST_BYTE) err=1; } } Пройден 20 раз - без ошибок Господа, гляньте одним глазком, вдруг чего в глаза бросится... Я вот к примеру заметил, что дисплей вообще перестает работать, если я делитель RCC_OscInitStruct.PLL.PLLM с 4 меняю на 8. У меня кварц 8 МГц, то есть дальше я пляшу от 1 МГц. Сменив делитель на 8 и умножив все остальное на 2 для компенсации, я получаю те же частоты и на дисплее и на шинах, однако дисплей вообще гаснет. Может кто заметит какую-нибудь аналогичную тонкость, которую я не учел. Да, и проект для КалоКуба я тоже выкладываю, для наглядности. Ссылка в самом низу. ПРОШУ ПРОЩЕНИЯ У МОДЕРАТОРА, РАНЬШЕ Я ПОЛЬЗОВАЛСЯ ТЭГОМ codebox, чтобы свернуть код, теперь тэг не работает. /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #define SDRAM_TIMEOUT ((uint16_t)0xFFFF) #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) #define SDRAM_BANK_ADDR ((uint32_t)0xD0000000) #define BUFFER_SIZE ((uint32_t)0x5) #define WRITE_READ_ADDR ((uint32_t)0x0800) #define REFRESH_COUNT ((uint32_t)1542) /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ DMA2D_HandleTypeDef hdma2d; LTDC_HandleTypeDef hltdc; SDRAM_HandleTypeDef hsdram1; /* USER CODE BEGIN PV */ uint32_t aTxBuffer[BUFFER_SIZE]; uint32_t aRxBuffer[BUFFER_SIZE]; FMC_SDRAM_CommandTypeDef command; __IO uint16_t uwWriteReadStatus = 0; uint32_t uwIndex = 0; uint16_t n=10; uint32_t ADDRESS; uint32_t TEST_BYTE; uint32_t test_iteration; uint32_t j; char err =0; //volatile uint32_t RGB565[5000] = {0x00000000}; uint32_t i; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_LTDC_Init(void); static void MX_FMC_Init(void); static void MX_DMA2D_Init(void); /* USER CODE BEGIN PFP */ static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command) { __IO uint32_t tmpmrd =0; /* Step 1: Configure a clock configuration enable command */ Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; Command->AutoRefreshNumber = 1; Command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, Command, 0x1000); /* Step 2: Insert 100 us minimum delay */ /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */ HAL_Delay(1); /* Step 3: Configure a PALL (precharge all) command */ Command->CommandMode = FMC_SDRAM_CMD_PALL; Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; Command->AutoRefreshNumber = 1; Command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, Command, 0x1000); /* Step 4 : Configure a Auto-Refresh command */ Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; Command->AutoRefreshNumber = 8; Command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, Command, 0x1000); /* Step 5: Program the external memory mode register */ tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD | SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE; Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; Command->AutoRefreshNumber = 1; Command->ModeRegisterDefinition = tmpmrd; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, Command, 0x1000); /* Step 6: Set the refresh rate counter */ /* (15.62 us x Freq) - 20 */ /* Set the device refresh counter */ HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); } static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset) { uint16_t tmpIndex = 0; /* Put in global buffer different values */ for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ ) { pBuffer[tmpIndex] = tmpIndex + uwOffset; } } /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_LTDC_Init(); MX_FMC_Init(); MX_DMA2D_Init(); /* USER CODE BEGIN 2 */ SDRAM_Initialization_Sequence(&hsdram1, &command); /* HAL_LTDC_SetAddress(&hltdc,(uint32_t) &RGB565,0); for(i=2000;i<4500;i++) { *(__IO uint16_t*) (hltdc.LayerCfg[0].FBStartAdress + (i*2)) = 0x00ff; } while(1); */ HAL_GPIO_WritePin(TFT_PWM_GPIO_Port, TFT_PWM_Pin, GPIO_PIN_SET); Fill_Buffer(aTxBuffer,BUFFER_SIZE,n); n=n<<1; test_iteration=0; srand(); for (j=0;j<10;j++) { test_iteration++; for (uwIndex = 0; uwIndex < 4194304; uwIndex++){ TEST_BYTE=rand(); *(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*uwIndex) = TEST_BYTE; if (*(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*(uwIndex)) !=TEST_BYTE) err=1; } } while(1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLN = 216; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Activate the Over-Drive mode */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) { Error_Handler(); } PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; PeriphClkInitStruct.PLLSAI.PLLSAIN = 100; PeriphClkInitStruct.PLLSAI.PLLSAIR = 2; PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2; PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV2; PeriphClkInitStruct.PLLSAIDivQ = 1; PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } } /** * @brief DMA2D Initialization Function * @param None * @retval None */ static void MX_DMA2D_Init(void) { /* USER CODE BEGIN DMA2D_Init 0 */ /* USER CODE END DMA2D_Init 0 */ /* USER CODE BEGIN DMA2D_Init 1 */ /* USER CODE END DMA2D_Init 1 */ hdma2d.Instance = DMA2D; hdma2d.Init.Mode = DMA2D_M2M; hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888; hdma2d.Init.OutputOffset = 0; hdma2d.LayerCfg[1].InputOffset = 0; hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB888; hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; hdma2d.LayerCfg[1].InputAlpha = 0; if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) { Error_Handler(); } if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN DMA2D_Init 2 */ /* USER CODE END DMA2D_Init 2 */ } /** * @brief LTDC Initialization Function * @param None * @retval None */ static void MX_LTDC_Init(void) { /* USER CODE BEGIN LTDC_Init 0 */ /* USER CODE END LTDC_Init 0 */ LTDC_LayerCfgTypeDef pLayerCfg = {0}; /* USER CODE BEGIN LTDC_Init 1 */ /* USER CODE END LTDC_Init 1 */ hltdc.Instance = LTDC; hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC; hltdc.Init.HorizontalSync = 139; hltdc.Init.VerticalSync = 19; hltdc.Init.AccumulatedHBP = 146; hltdc.Init.AccumulatedVBP = 21; hltdc.Init.AccumulatedActiveW = 1170; hltdc.Init.AccumulatedActiveH = 621; hltdc.Init.TotalWidth = 1330; hltdc.Init.TotalHeigh = 633; hltdc.Init.Backcolor.Blue = 0; hltdc.Init.Backcolor.Green = 255; hltdc.Init.Backcolor.Red = 0; if (HAL_LTDC_Init(&hltdc) != HAL_OK) { Error_Handler(); } pLayerCfg.WindowX0 = 100; pLayerCfg.WindowX1 = 924; pLayerCfg.WindowY0 = 100; pLayerCfg.WindowY1 = 500; pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; pLayerCfg.Alpha = 255; pLayerCfg.Alpha0 = 0; pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; pLayerCfg.FBStartAdress = 0xD0000000; pLayerCfg.ImageWidth = 924; pLayerCfg.ImageHeight = 500; pLayerCfg.Backcolor.Blue = 0; pLayerCfg.Backcolor.Green = 255; pLayerCfg.Backcolor.Red = 0; if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN LTDC_Init 2 */ /* USER CODE END LTDC_Init 2 */ } /* FMC initialization function */ static void MX_FMC_Init(void) { /* USER CODE BEGIN FMC_Init 0 */ /* USER CODE END FMC_Init 0 */ FMC_SDRAM_TimingTypeDef SdramTiming = {0}; /* USER CODE BEGIN FMC_Init 1 */ /* USER CODE END FMC_Init 1 */ /** Perform the SDRAM1 memory initialization sequence */ hsdram1.Instance = FMC_SDRAM_DEVICE; /* hsdram1.Init */ hsdram1.Init.SDBank = FMC_SDRAM_BANK2; hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8; hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12; hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32; hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3; hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE; hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0; /* SdramTiming */ SdramTiming.LoadToActiveDelay = 2; SdramTiming.ExitSelfRefreshDelay = 7; SdramTiming.SelfRefreshTime = 4; SdramTiming.RowCycleDelay = 7; SdramTiming.WriteRecoveryTime = 3; SdramTiming.RPDelay = 2; SdramTiming.RCDDelay = 2; if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) { Error_Handler( ); } /* USER CODE BEGIN FMC_Init 2 */ /* USER CODE END FMC_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOJ_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOK_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GL_RST_GPIO_Port, GL_RST_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LTDC_DITHB_GPIO_Port, LTDC_DITHB_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOG, LTDC_UD_Pin|LTDC_LR_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LTDC_MODE_GPIO_Port, LTDC_MODE_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(TFT_PWM_GPIO_Port, TFT_PWM_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : GL_RST_Pin */ GPIO_InitStruct.Pin = GL_RST_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GL_RST_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LTDC_DITHB_Pin */ GPIO_InitStruct.Pin = LTDC_DITHB_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LTDC_DITHB_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : LTDC_UD_Pin LTDC_LR_Pin LTDC_MODE_Pin */ GPIO_InitStruct.Pin = LTDC_UD_Pin|LTDC_LR_Pin|LTDC_MODE_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); /*Configure GPIO pin : TFT_PWM_Pin */ GPIO_InitStruct.Pin = TFT_PWM_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(TFT_PWM_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ проект для КалоКуба RUTFT.ioc -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Ниче не понимаю.... Прогнал всю SDRAM. Вот так for (uwIndex = 0; uwIndex < 4194304; uwIndex++){ *(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*uwIndex) = 0xAAAAAAAA; } for (uwIndex = 4194304; uwIndex>0; uwIndex--){ if (*(__IO uint32_t*)(SDRAM_BANK_ADDR + 4*(uwIndex-1)) !=0xAAAAAAAA) err=1; } Никаких ошибок. А LTDC не может все это дело нормально прочитать. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
GenaSPB советовал снизить пиксельклок. Мотивируя это тем, что может не хватать пропускной способности. Пытаясь посчитать, какова же она может и должна быть, я наткнулся на интересную картинку. Все уже посчитано до нас У меня 1 слой, память 32 бит, режим включил 16 бит. То есть в этих условиях LTDC способен отработать 78 МГц пиксельклока. Я снизил пиксельклок до 30 МГЦ (удивительно, но дисплей работает, хотя заявлен минимум 40). Тем не менее, строки все равно дрожат. Но прерывания ошибки LTDC не ловятся. Точнее они ловятся однократно, спустя какое-то время после запуска. Что интересно, они дрожат меньше на 63 МГц. Копаю дальше.... -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
STM32F746BGT6 -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Спасибо, интересная мысль про фифо. Но это об fmc, а у меня проблема даже при работе со sram. А кстати, за сколько тактов происходит чтение и запись вo внутреннюю sram? A у sdram в связке с stm какая пропускная способность на частоте 108 мгц? Вытянет ли она пиксельклок в 40-50 мгц? Мне ниже 40 никак нельзя снижать. А в идеале бы 50, потому что на 40 экран уже мерцает. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Хмм... а кто-нибудь, знает, какова скорость ram в stm32f7 ? Я пиксельклок снизил до 40 мгц - это нижний предел. Все равно дрожит. К слову, на плате дискавери я ограничил частоту тактирования sdram насколько позволила система тактирования - порядка 2 мгц , думал, она захлебнется и возникнет такой же эффект. Но ничего не произошло, дисплей работает.... -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Я так и знал, что проблема не в SDRAM или SRAM. Иначе в памяти был бы хаос. А у меня не хаос, а рассинхрон чтения. И проблема не в дисплее, полярности клоков, частоте. Иначе глючила бы вся картинка, а у меня глючит только слой, с которым работаю. Догадался я заглянуть, что творится в прерываниях. И ловятся у меня оба прерывания ошибок - FUIF (Генерируется, когда пиксель запрашивается а FIFO пуст) и TERRIF (Генерируется при возникновении ошибки шины). В чем может быть причина? Куда копать дальше? Я пока работаю не со SDRAM, a с RAM, которая, как таковая, настроек не требует. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Попробую, когда домой приду. Для пробы я вчера DE режим отключал -толку не было. От скуки попробую еще на дисплее Dithering отключить, это единственная нога, которой я еще не дергал. А с тактированием на моем скриншоте все нормально? Может конфликт какой... сравнил с тактированием DISCO, на котрой все работает - идентично, единственное - у меня кварц 8 мгц, у них 25. Но по мануалу, для седьмой серии достаточно и 4 мгц. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Не думаю. Проверил в отладке. Мой код, переделанный под RAM, размещает начало буфера по адресу 0x20002300. Объем памяти в моем контроллере 320 кб. Это 160 кпикселей. При длине строки в 1024 пикселя это 156 строк, то есть четверть экрана. Собственно примерно четверть экрана мусор и занимает Я подправил код, теперь, начиная с адреса 0х20003300 он шлет не 2000 слов, а около 614 тыс.(это весь экран). В резулььате экран закрашивается синим ровно на столько, но сколько хватает RAM, то есть на четверь (остальное черное, без.мусора) И в этой синеве никакой жизни процессора не наблюдается. Наблюдается только дрожание начала первой линии прямоугольника и конца последней его линии. Да и предыдущая картинка, что на видео - там не видно, но когда вживую смотришь - там нет хаотичной трансформации мусора, как а экране отключенного от антенны телевизора. Ощущение, что строки одной и той же картинки просто съезжают на несколько пикселей. Я пошел дальше - добавил еще один слой, в виде квадрата 200х200, расположил его в центре экрана. Получилась картинка в картинке и еще раз в картинке. Границы рамок слоев четкие. Я ведь правильно понимаю, что контроллер ltdc отправляет на дисплей уже совмещенную картинку? Он не может выборочно обновлять определенную область в дислпплее? Он просто тупо копирует свой буфер в буфер контррллер. Тогда это точно не наводки на линиях от проца к дисплею и не в контроллере дисплея. Идет какой-то рассинхрон чтения Тогда что? Я грешил на трассировку сдрам, но, как видите, при чтении из RAM та же картина. Да и когда я работал со сдрам - я получал чистые, стабильные по текстуре прямоугольники, у них только смещались концы начальных и конечных линий. проблемы возникают при предаче данных внутри контроллера. Там максимум 67.5 мгц. И, повторюсь, рамка вокруг слоя не дрожит. Будь пиксельклок чрезмерен, то страдало бы все изображение. Я все же попробовал уменьшить - нк помогло. -
Странное поведение дисплея
MementoMori ответил MementoMori тема в В помощь начинающему
Отключил SDRAM совсем, поотключал периферию - дрейф данных остается все равно...