Jump to content

    
MementoMori

TouchGFX и 32 битная SDRAM

Recommended Posts

Господа, продолжаю бороться со связкой STM32F746+SDRAM MT48LC4M32B2P-6A  +TouchGFX.

C созданием и компиляцией проекта проблем нет. Но при работе есть артефакты.

Вот такие вертикальные полосы сбоку от элементов

renditionDownload?rendition=ORIGINAL_Jpg

 

Избавиться от них удалось лишь тогда, когда я инициализировал память не в 32, а в 16-битном режиме.

И это, если честно, вызвало удивление. С одной стороны, SDRAM проецируется в единое адресное пространство и TouchGFX работает с ней, даже не зная, что это SDRAM. Для системы - что 16 бит, что 32 - без разницы. То есть проблема должна быть с аппаратной частью SDRAM. но с другой стороны - я неоднократно тестировал SDRAM - ошибок нет. А вот в работе с TouchGFX появляются артефакты.

Что интересно, похожие вертикальные белые полосы, но не с краю, а внутри картинок появились когда я случайно в одном месте, где инициализируется SDRAM, указал CAS Latency=2, а в другом - 3.  То есть в принципе аппаратная проблема может иметь место.

 

Смех в том, что когда я еще прорабатывал архитектуру и думал, стоит ли заморачиваться с 32 бит, один товарищ здесь на форуме написал, что у него с 16 бит были артефакты, которые исчезли, когда он поставил 32 бит.

Может есть какие тонкости  в работе с 32 битной SDRAM?

Кто-нибудь сталкивался с подобной проблемой?

 

Вот так я ее инициализирую

Spoiler

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 */
  __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(&hsdram1, &Command, SDRAM_TIMEOUT);

    /* 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(&hsdram1, &Command, SDRAM_TIMEOUT);

    /* Step 4: Configure an 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(&hsdram1, &Command, SDRAM_TIMEOUT);

    /* Step 5: Program the external memory mode register */
    tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | \
             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(&hsdram1, &Command, SDRAM_TIMEOUT);

    /* Step 6: Set the refresh rate counter */
    /* Set the device refresh rate */
    HAL_SDRAM_ProgramRefreshRate(&hsdram1, REFRESH_COUNT);
    
    //Deactivate speculative/cache access to first FMC Bank to save FMC bandwidth
    FMC_Bank1->BTCR[0] = 0x000030D2;
  /* USER CODE END FMC_Init 2 */
}

 

Share this post


Link to post
Share on other sites

если на аппаратные проблемы думать, то тогда напишите, какая длина трасс? какой разброс длин? пробовали паттерны какие-то выводить - может у вас проблема по конкретным линиям данных?

Share this post


Link to post
Share on other sites
6 hours ago, Aaron said:

если на аппаратные проблемы думать, то тогда напишите, какая длина трасс? какой разброс длин? пробовали паттерны какие-то выводить - может у вас проблема по конкретным линиям данных?

Тестировал заполнением псевдослучайной последовательностью.

Мне кажется, если бы проблемы были в том, о чем вы говорите, то есть косяки на конкретных линиях данных, то артефакты были бы привязаны не к месту, а к цвету. И не были бы постоянны. А тут есть элементы интерфейса, которые не подвержены этой проблеме. То есть по проблема возникает при каком-то определенном "спецэффекте" графического движка. Но непонятно, как на это влияет разрядность, если графический движок про память вообще ничего не знает. 

Кстати, еще одна проблема - на круге полосы видите? Так  вот эта проблема решается двумя действиями - переключением цвета в формат rgb565 и пресловутым включением памяти в 16 битный режим.

Share this post


Link to post
Share on other sites
27 minutes ago, golf2109 said:

у меня вот так прекрасно работает

  SdramTiming.RowCycleDelay = 6;
  SdramTiming.WriteRecoveryTime = 2;

Работает sdram как таковая? Или в связке с touchgfx? Если второе, то какая у вас глубина цвета?

Попробовал на дискавери - там конечно же только 16 битный режим памяти, но артефактов нет даже при rgb888.  А на моей плате, если включаешь 16 бит, то исчезают только те полосы, что сбоку картинок, полосатость же круга остается, чтоб ее убрать, нужно включать  rgb565. Проц и память те же, только в bga. Но с другой стороны, экран меньше. Вот и ищи, блин, отличия...

Может, dma2d чудит?

Share this post


Link to post
Share on other sites
12 hours ago, MementoMori said:

Что интересно, похожие вертикальные белые полосы, но не с краю, а внутри картинок появились когда я случайно в одном месте, где инициализируется SDRAM, указал CAS Latency=2, а в другом - 3.  То есть в принципе аппаратная проблема может иметь место. 

Коллега, и всё же предлагаю отмести железобетонно аппаратные проблемы.

Quote

Мне кажется, если бы проблемы были в том, о чем вы говорите, то есть косяки на конкретных линиях данных, то артефакты были бы привязаны не к месту, а к цвету.

Я вижу, что на приведённой картинке линии имеют разный цвет ;)

Как предположение (надо смотреть код touchGFX) - у вас обмен с SDRAM проводится в виде транзакций. Одна строчка изображения - одна транзакция. В промежутках между транзакциями шина может не использоваться. При проблемах в топологии из-за нарушения целостности сигналов могут быть всякие чудеса. Например, при появлении данных на линии первые биты могут портиться, и потом при окончании транзакции последние биты портиться. Может, у вас на линии идёт какая-то наводка извне? При этом, если данные передавать непрерывно, то проблема может не проявляться визуально.

Share this post


Link to post
Share on other sites

Хорошо, вечером приведу длины проводников.

Вообще, я все тестировал в гиперлинксе, глазковая диаграмма более чем хороша, перекрестные помехи имели место лишь где-то на линиях дисплея, но не превышали 200 мВ.

Share this post


Link to post
Share on other sites
Quote

вас обмен с SDRAM проводится в виде транзакций. Одна строчка изображения - одна транзакция. В промежутках между транзакциями шина может не использоваться. 

А нельзя ли поподробнее насчет транзакций? Это нечто конкретное и специфичское или вы под этим понимаете обычную операцию чтения записи?

Я к чему спрашиваю - тестирование у меня ошибок не выявило. Но вы говорите, при непрерывном чтении ошибеа может и не проявиться.

У меня  есть мысль -написать свою собственную функцию вывода картинки на экран, чтобы она создавала условия для возникновения ошибки, о которой вы говорите, те условия, которые, предположительно, создает код touchgfx. Если это получится, то значит с touchgfx обвинения снимаются.

Так вот как это сделать?

Share this post


Link to post
Share on other sites
2 часа назад, MementoMori сказал:

Работает sdram как таковая? Или в связке с touchgfx? Если второе, то какая у вас глубина цвета?

Попробовал на дискавери - там конечно же только 16 битный режим памяти, но артефактов нет даже при rgb888.  А на моей плате, если включаешь 16 бит, то исчезают только те полосы, что сбоку картинок, полосатость же круга остается, чтоб ее убрать, нужно включать  rgb565. Проц и память те же, только в bga. Но с другой стороны, экран меньше. Вот и ищи, блин, отличия...

Может, dma2d чудит?

работает в связке с touchgfx rgb888, 800х480 память в TSSOP 84

проверьте clk дисплея на предмет помех вплоть до перерезания и подключения

отдельным проводом

 

Edited by golf2109

Share this post


Link to post
Share on other sites
52 minutes ago, golf2109 said:

работает в связке с touchgfx rgb888, 800х480 память в TSSOP 84

Попутный вопрос - а каков пиксельклок у вас? У разработчика touchgfx написано, что более 30 мгц - проблема. У меня как раз на 30 мгц дисплей перестает заводиться.

 

52 minutes ago, golf2109 said:

проверьте clk дисплея на предмет помех

Если с клоком самого дисплея проблема, тогда точно к картинке привязки не будет.

Но попробую проверить.

Share this post


Link to post
Share on other sites

Оно конечно малопонятно, но так, для информации - подсвечены те линии, которые в 16 битном режиме не задействованы, то есть те, которые в 32 битном режиме могут создавать проблемы.

Клок - это идущая отдельно от остальных линия, в левых отделах схемы.  По картинке неясно, но клок идет в отдельном слое, окружен землей.

DgbA1uA5.png?download=1

Share this post


Link to post
Share on other sites
4 hours ago, golf2109 said:

проверьте clk дисплея на предмет помех вплоть до перерезания и подключения

отдельным проводом

Вы, батенька, садист)))

Но я последовал Вашему совету - не помогло.

Share this post


Link to post
Share on other sites

Наполовину проблему решил!!!

Дело было в MPU_Config()

Оказывается куб сгенерировал автоматом настройки только для QSPI, то есть для адреса 0x90000000.

Я настроил согласно AN4861, поменяв только адреса и размеры буферов - изображения всех виджетов пришли в норму - проблемы были со многими, на картинке я привел лишь сектор, он теперь без полосок. Но полосы в начале и в конце некоторых виджетов и в текстовых элементах все равно остались.

Посмотрите как я настроил - может у меня все еще что-то не так?

Для справки - у меня SDRAM по адресу 0xD0000000, буферизация двойная, второй буфер по адресу 0x90200000 (размер буфера 0x1C2000).

 

 

void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();
  /** Initializes and configures the Region and the memory to be protected 
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0xD0000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /** Initializes and configures the Region and the memory to be protected 
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;
  MPU_InitStruct.BaseAddress = 0xD0000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_2MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /** Initializes and configures the Region and the memory to be protected 
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER2;
  MPU_InitStruct.BaseAddress = 0xD0200000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_2MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /** Initializes and configures the Region and the memory to be protected 
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER3;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /** Initializes and configures the Region and the memory to be protected 
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER4;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

 

Share this post


Link to post
Share on other sites

Вот таким тестом долго гонял вчера память

Quote

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;    
}

Ошибок нет.

Может есть какой-нибудь более агрессивный тест?

Share this post


Link to post
Share on other sites

Делал даже так, чтобы каждый при каждом чтении приходилось обращаться в две соседние ячейки, а потом клеить ответ

 

result_byte=*(__IO uint32_t*)(0xD0000000 + 4*uwIndex+1);  - адрес увеличивал на единичку, то есть читались биты 8-31, затем в следующей ячейке 0-7  

ошибок нет.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.