Jump to content

    

Не могу подружить SDRAM и LTDC

2 minutes ago, aaarrr said:

Можно вывести на пин частоту после делителя

А что вы хотите вывести? Тактирование FMC? Самое близкое к нему, что выводится на MCO, это PLLCLK. После него до FMC всего два делителя. Логика понятна, но у меня есть функция HAL_Delay - она выдает правильные задержки, пропорциональные SYSCLK. Так что тут все ровно.

 

ЕДинственное - что  - посмотрите на тактирование  

I5bdQsU8.png

 

Я не могу сделать по человечески - поделить HSE на 25 и дальше плясать от 1 МГЦ - у меня в этом случае почему-то не заводится пиксельклок, хотя куб показывает допустимые значения.

Share this post


Link to post
Share on other sites
2 minutes ago, aaarrr said:

На MCO2 можно SYSCLK вывести.

Куб ругается, если она меньше 25 МГЦ.

 

У меня идея..... сейчас приду...

Share this post


Link to post
Share on other sites

Я поделил SYSCLK на 512, должен был получить HLCK 0.39 МГЦ

PPX0WuPs.png

 

 

Но на SD_CLK получил такую осциллограмму

BxJFuQQA.png

 

Этим осциллографом, в силу его примитивности, я ловлю максимум 100 кГц. Более высокие частоты у меня просто сглаживаются в линию на уровне 2-2.5 вольт.

 

Но, судя по картинке, его пропускной способности хватает, и сигнал именно 15 кГц, Это показывает  счетчик, и измерение ручками по 10 импульсам.

 

Частота клока на SDRAM - 15,6 КГц.

То есть, когда я ее не делю - она по факту 8 МГц.  (У меня уже мозги плывут, вчера до 3 ночи сидел, и сегодня весь день. Не исключаю, что мог элементарно ошибиться)

А должна быть равна HCLK/2, так ведь? 

 

 

Что посоветуете сделать, чтобы понять, кто своровал мегагерцы?

Повторюсь, программный код до включения деления на 512 выдавал правильные задержки через функцию HAL_Delay. То есть в SYSCLK и в HCLK я могу быть уверен, а вот что происходит дальше по цепочке....

Share this post


Link to post
Share on other sites

Тихо сам с собою...

Прочитал отладчиком состояние регистра FMC SDCR1 - получил 2, что соответствует HCLK/2. А вот в SDCR2 - 0 - отключено.

У меня задействован SDRAM_bank2, то есть SDCKE1 и SDNE1. То есть у меня тактирование отключено? А откуда тогда клок на SDRAM?

 

Сначала я решил что в коде от куба ошибка - SDCLockPeriod для банка 2 в нем неправильно настраивается.

 

В даташите написано

SDCLK[1:0]: SDRAM clock configuration
These bits define the SDRAM clock period for both SDRAM banks and allow disabling the clock
before changing the frequency. In this case the SDRAM must be re-initialized.

Это как понимать? То есть SDCLK для банка 2 устанавливать не нужно - он один общий и читается из регистра настройки первого банка что ли?

Судя по коду так и есть

else /* FMC_Bank2_SDRAM */                      
  {
    tmpr1 = Device->SDCR[FMC_SDRAM_BANK1];
    
    /* Clear SDCLK, RBURST, and RPIPE bits */
    tmpr1 &= ((uint32_t)~(FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
    
    tmpr1 |= (uint32_t)(Init->SDClockPeriod      |\
                        Init->ReadBurst          |\
                        Init->ReadPipeDelay);
    
    tmpr2 = Device->SDCR[FMC_SDRAM_BANK2];
    
    /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
    tmpr2 &= ((uint32_t)~(FMC_SDCR1_NC  | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
                          FMC_SDCR1_NB  | FMC_SDCR1_CAS | FMC_SDCR1_WP   | \
                          FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));

     tmpr2 |= (uint32_t)(Init->ColumnBitsNumber   |\
                        Init->RowBitsNumber      |\
                        Init->MemoryDataWidth    |\
                        Init->InternalBankNumber |\
                        Init->CASLatency         |\
                        Init->WriteProtection    
                        );                                                                         

    Device->SDCR[FMC_SDRAM_BANK1] = tmpr1;
    Device->SDCR[FMC_SDRAM_BANK2] = tmpr2;
  }

 

Да и попытка при отладке в Кейле изменить SDCLK банка в регистре FMC SDCR2 ни к чему не приводит...

 

Я перенастроил SDRAM на банк 1, проверил клок - он все также при делении на 512 равен 15 кГц.

 

 

 

А что еще тогда в FMC отвечает за тактирование SDRAM? Я не нашел ничего..

Share this post


Link to post
Share on other sites

Стадия RTFM в полный рост настала, кмк, уже когда до 3 ночи возился ;-)

Share this post


Link to post
Share on other sites
Just now, Obam said:

Стадия RTFM в полный рост настала, кмк, уже когда до 3 ночи возился ;-)

Когда начинаешь понимать, где загвоздка, RTFM - весьма приятное занятие. Но вчера бы мне это не помогло.

 

Share this post


Link to post
Share on other sites

Проверяйте тактирование с самого начала. Только не по картинкам, а по коду.

Share this post


Link to post
Share on other sites

Начну для начала с картинки для наглядности

hc9T6H7g.png

 

Вот как это выглядит в коде

 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 = 25;
  RCC_OscInitStruct.PLL.PLLN = 400;
  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_6) != HAL_OK)
  {
    Error_Handler();
  }

 

 

Хочу я к примеру, понять - соответствует ли HCLK истинному. От него тактируется FMC и core.  Поскольку HAL_Delay(1000) дает правильную задержку в 1 секунду, считаю, что ядро тактируется правильно.  Смущает только то, что если настроить HCLK на 100 МГц, то библиотека не пересчитывает это и имею задержку в 2 секунды.

От 200 МГц core тактируется правильно. Но вот SDRAM_CLK, который настроен на половину HCLK, получается меньше 10 МГц.

Захожу с другой стороны. Настраиваю таймер TIM4. Он тактируется от APB1, 100МГц.

Настраиваю его переполнение на 100 мсек

 

 htim4.Instance = TIM4;
  htim4.Init.Prescaler = 10000;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 1000;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

Я правильно указал Prescaler и Period?    Тогда должно быть 100000000/10000/1000 = 10 переполнений в секунду.

А по факту - переполнение ровно за 5 секунд.

Как бы APB1 не имеет никакого отношения к FMC, но сам факт неправильной работы таймера беспокоит.

В чем подвох?

Чем еще можно проверить HCLK?

Share this post


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

Вот как это выглядит в коде

Это не код, а заполнение портянок HAL'а. Почему бы не попробовать сделать то же самое руками, самым простым способом:

//**************************************
//*    CLK
//*
//*  SYSCLK = 200MHz (over-drive)
//*  AHB = 200MHz, APB2 = 100MHz, APB1 = 50MHz
//*

#define HSE_CLK_MHZ		25

static void clk_setup(void)
{
	/* Enable ART accelerator, Prefetch Buffer and set Flash Latency */
	FLASH->ACR = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_7WS;

	/* Enable HSE */
	RCC->CR |= RCC_CR_HSEON;
	while(!(RCC->CR & RCC_CR_HSERDY));

	/* SYSCLK = HSE
	 * AHB  = SYSCLK
	 * APB1 = AHB / 4
	 * APB2 = AHB / 2
	 * RTC  = HSE / HSE_CLK_MHZ = 1MHz
	 * MCO2 = SYSCLK / 4
	 */
	RCC->CFGR = RCC_CFGR_MCO2PRE_2 | RCC_CFGR_MCO2PRE_1 |
			HSE_CLK_MHZ << RCC_CFGR_RTCPRE_Pos | RCC_CFGR_PPRE2_DIV2 |
			RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_HSE;

	/* PLLM = HSE / HSE_CLK_MHZ = 1MHz
	 * PLLN = 400
	 * PLLP = 2 (SYSCLK = 400 / 2 = 200MHz)
	 * PLL source = HSE
	 * PLLQ = 8 (PLL48 = 400 / 8 = 50MHz)
	 */
	RCC->PLLCFGR = 8 << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLSRC_HSE |
			400 << RCC_PLLCFGR_PLLN_Pos | HSE_CLK_MHZ;

	/* Enable PLL */
	RCC->CR |= RCC_CR_PLLON;

	/* Enable over-drive */
	PWR->CR1 |= PWR_CR1_ODEN;
	while(!(PWR->CSR1 & PWR_CSR1_ODRDY));

	PWR->CR1 |= PWR_CR1_ODSWEN;
	while(!(PWR->CSR1 & PWR_CSR1_ODSWRDY));

	/* Wait till PLL is ready */
	while(!(RCC->CR & RCC_CR_PLLRDY));

	/* Select PLL as MCO2 and system clock source */
	RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_MCO2_Msk | RCC_CFGR_SW_Msk)) |
			RCC_CFGR_MCO2_1 | RCC_CFGR_MCO2_0 | RCC_CFGR_SW_PLL;

	/* Wait till PLL is used as system clock source */
	while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}

 

Share this post


Link to post
Share on other sites

Мысли... процессор уже давно вышел, ошибки в кубовской настойке тактирования для него маловероятны.  Топикствртеру предлагаю контролировать правильность настройки ввводом в компорт текста.

Edited by GenaSPB

Share this post


Link to post
Share on other sites
1 hour ago, GenaSPB said:

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

Не совсем понял, о чем вы...

 

1 hour ago, GenaSPB said:

Мысли... процессор уже давно вышел, ошибки в кубовской настойке тактирования для него маловероятны.  

Ну тот факт, что если поставить делитель HSE на величину,равную частоте кварца, то какими бы ни были остальные множители, ltdc clock перестает работать (то ли не генерируется, то ли частота не подходящая)уже говорит о том что ошибки есть. Лично я в прошлом году нашел ошибку в одной из версий, благодаря которой не настраивались cs на qspi, написал в ST, думал, что я дурак, а они ответили, мол, ошибка, исправим

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

 

Лично мне кажется подозрительно странным соотношение должной частоты клока (100 мгц) и реальной (8 мгц). Это как 200 и 16 и напоминает ситуацию, когда срабатывает CSS. Вернусь домой и если код, предложенный выше, не сработает, то попробую посмотреть на прерывания от css.

Еще есть мысль - оказывается tim11 можно подключить к HSE в режиме input capture. То есть хотя бы это звено проверить.

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

По факту же, на дискавери, на настройках, предлагаемых кубом, та же самая проблема. Там скорость SDRAM еще меньше. Но на разрешении 480х272 и пиксельклоке 9.6 мгц, проблем с буфером не возникает.

Share this post


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

И я потратил уйму времени, пытаясь найти разницу между двумя проектами.

Есть простое решение, нужно снять дамп регистров периферии после всех операций инициализации. Для этого пригодится макрос преобразования имени переменной в строку. Просто печать в отладку, с сохранением в файл, и уже потом проверка. 

Решение не годится для поиска различий в реализации алгоритмов, но позволяет выявить место косяка, что значительно сокращает время на решение проблемы.

Share this post


Link to post
Share on other sites
5 hours ago, aaarrr said:

Это не код, а заполнение портянок HAL'а. Почему бы не попробовать сделать то же самое руками, самым простым способом:

Не знаю даже что и сказать.

Ваш код виснет на последней строке приведенного ниже фрагмента

/* Enable HSE */
	RCC->CR |= RCC_CR_HSEON;
	while(!(RCC->CR & RCC_CR_HSERDY));

Наверное все-таки мое предположение верно - не работает HSE, система переключается на HSI 16 МГц- как раз получающиеся частоты этому и соответствуют:

1. SDRAM - HCLK/2 =16/2=8 МГц

2. В 12,5 раз медленнее работает таймер

3. Systick выдает правильные интервалы.

 

Осталось проверить, так ли это...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this