Перейти к содержанию
    

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

2 minutes ago, aaarrr said:

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

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

 

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

I5bdQsU8.png

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, aaarrr said:

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я поделил 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 я могу быть уверен, а вот что происходит дальше по цепочке....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Прочитал отладчиком состояние регистра 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? Я не нашел ничего..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, Obam said:

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

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 мгц, проблем с буфером не возникает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

52 minutes ago, MementoMori said:

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 выдает правильные интервалы.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...