Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странное поведение STM32F745
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Денис555
Доброго времени суток!
Столкнулся с проблемой при использовании STM32F745.
Элементарная программа:
В main в бесконечном цикле происходит постоянный вызов процедуры, в которой следующее:
1. выставили лог. 1 на GPIO
2. пустой цикл задержки
3. сбросили пин GPIO (лог. 0)
4. пустой цикл задержки
...
и далее повторение пунктов 1-4 4 раза.
Все пустые циклы сделал ассемблерными вставками (чтобы наверняка, компилятор проглатывает как есть).
На осциллографе 3 первых получившихся импульса и пауз между ними одинаковые, а четвертый импульс растянут раз в 5 больше. Эффект независим от длительности импульсов.
При добавлении кол-ва импульсов этот эффект может проявиться где угодно в разных импульсах и паузах 1 и более раз.
Тактирование PLL - 200 МГц от внешнего генератора 25 МГц. Пробовал и c HAL-ом и без него. Кроме GPIO и RCC (тактирование) ничего не включено. Все прерывания отключены. Питание норм.
Что это может быть? Уже всю голову сломал и уже не я один.
Приветствуются любые предложения.
Спасибо!
ViKo
Если в Кейле, то можно в отладчике пройтись по ассемблерным командам. Там и такты считаются, и время.
Если не в Кейле, то ассемблерный листинг все равно можно посмотреть.
Денис555
Пишу в Keil-е. В ассемблерном листинге все ровно как и хотелось, компилятор оставляет всавки как есть. В отладке все красиво пробегает. Все по порядку, ни шагу в лево ни шагу вправо.
На практике чудеса...
AlexandrY
Цитата(Денис555 @ Jan 14 2016, 18:17) *
Приветствуются любые предложения.


Есть предложение выложить проект сюда.
Денис555
CODE
/* Includes ------------------------------------------------------------------*/
#include "stm32f7xx_hal.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
void TDC12(void);
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

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();
/* Configure the system clock */
SystemClock_Config();

/* Initialize all configured peripherals */
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */

SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; //Disable IRQ SysTick
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //Disable SysTick
__disable_irq ();
while (1)
{
TDC12();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
HAL_PWREx_ActivateOverDrive();
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;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* USER CODE BEGIN 4 */
void TDC12(void)
{
register uint32_t adr __asm("r4");
register uint32_t portb __asm("r5");
register uint32_t portc __asm("r6");
register uint32_t portd __asm("r7");
register uint32_t porte __asm("r8");
register uint32_t win1 __asm("r9");
register uint32_t win2 __asm("r10");
register uint32_t win3 __asm("r11");
register uint32_t win4 __asm("r12");
adr=0;
portb=0x40020400;
portc=0x40020800;
portd=0x40020c00;
porte=0x40021000;
win1=100;
win2=100;
win3=100;
win4=100;
__asm {
MOV temp,#0x00000010
STR temp,[portc,#0x18]
MOV adr,#0x00000000
lab1:
ADDS adr,adr,#1
CMP adr,win1
BCC lab1 }

__asm {
MOV temp,#0x00100000
STR temp,[portc,#0x18]
MOV adr,#0x00000000
Lab2:
ADDS adr,adr,#1
CMP adr,win2
BCC lab2 }

__asm {
MOV temp,#0x00000010
STR temp,[portc,#0x18]
MOV adr,#0x00000000
Lab3:
ADDS adr,adr,#1
CMP adr,win3
BCC lab3 }

__asm {
MOV temp,#0x00100000
STR temp,[portc,#0x18]
MOV adr,#0x00000000
Lab4:
ADDS adr,adr,#1
CMP adr,win4
BCC lab4 }
}

/* USER CODE END 4 */
#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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif


Это с использованием HAL есть и без HAL-а, сейчас не под рукой, но результат одинаковый.
Процедуру урезал до 2-х импульсов, что бы не нагромождать.
Что бы на таком простом коде были у STM32F7 такие непонятные явления, очень странно...
ViKo
Думаю, надо присмотреться к кэшу. Шина Flash у STM32F745 64-битовая. Латентность большая.
alx125
Рискну предположить, что Вы ранее имели дело с микроконтроллерами без конвеера и кэш.
Там функцию точной задержки можно было написать простым циклом.
В ахитектуре ARM используется конвеер и значит многие вещи стали не детерминированными по времени!
Если Вам нужно точную задержку в ARM - необходимо использовать таймер+прерывание
arhiv6
Цитата(alx125 @ Jan 15 2016, 08:54) *
Если Вам нужно точную задержку в ARM - необходимо использовать таймер+прерывание

Даже если все перифирийные таймеры заняты, в самом ARM ядре есть системный таймер который для этого можно использовать. Вот пример.
Денис555
Про SysTick и про DWT - это все понятно, можно, но не для моей реализации.
Нужно решить именно эту задачу.
Что такое конвейер тоже в курсе, работал. Добавленный акселерометр должен ускорять, а не тормозить процесс.
Пробовал отключать и включать акселерометр, не помогает.
Отключение ICash к изменению результата не приводит.

Даже если решить эту проблему другим образом, встретить в программе подряд идущих несколько циклов, не обязательно задержек, очень легко.
И представьте, что МК, ни с того ни с сего, будет выполнять один из циклов в 5 раз дольше... Это нормально? Я понял бы если +- 20 - 50 тактов куда то уходило...
Но столько...

Варианты задержек просьба не предлагать. Все способы реализаций известны. Нужно именно понять почему один из циклов растягивается в 5 раз?
Причем с добавлением циклов растянутый может быть любой из них или даже не один.

Появилась новая интересная штука. Если перед циклом, который задерживается вставить NOP тогда все идет нормально. Иногда нужно вставить не один NOP.
Похоже на проблему с выравниваниями. Но не факт.
Но вот теперь вопрос, как этого избежать?
ICache включаю! В отладке вижу, что включен. Не помогает.
Может кто знает в Keil-е макрос, который производит выравнивание NOP-ми во флешке автоматически?

Кратно 32, 64 байта...
ViKo
У вас конвейер 7-ступенчатый! maniac.gif Задумайтесь. Если программа куда-то перескакивает (в начало цикла), конвейер переписывается.
Можно проверить. Понизить тактовую частоту, изменить латентность конвейера.
Акселерометр != Акселератор. rolleyes.gif
mantech
Цитата(ViKo @ Jan 15 2016, 10:47) *
У вас конвейер 7-ступенчатый! maniac.gif Задумайтесь. Если программа куда-то перескакивает (в начало цикла), конвейер переписывается.
Можно проверить. Понизить тактовую частоту, изменить латентность конвейера.
Акселерометр != Акселератор. rolleyes.gif


Когда-то тоже делал подобное, пробовал линейно сделать 10 или 20 переключений пина и только потом переходил снова к первому, при переходе, действительно возникала 3х кратная задержка, чем длиннее линейная составляющая - тем точнее длительность. Плюс еще накладывалось ожидание готовности периферийной шины, а она заметно медленнее, чем процессорная.
Проверьте...
Денис555
Цитата(ViKo @ Jan 15 2016, 11:47) *
У вас конвейер 7-ступенчатый! maniac.gif Задумайтесь. Если программа куда-то перескакивает (в начало цикла), конвейер переписывается.
Можно проверить. Понизить тактовую частоту, изменить латентность конвейера.
Акселерометр != Акселератор. rolleyes.gif

Да да, очепятка, акселератор... rolleyes.gif
А что Вы имеете ввиду под изменить латентность? Таковая частота понизится и должно быть все тоже самое, только растянется по времени...
По поводу перезаписи конвейера:
Если так случится, что к примеру ему пришлось переписАться, то была бы аддитивная задержка в начале одного цикла на несколько тактов, но не постоянно же...?
Конвейер - 6 ступенчатый rolleyes.gif
ViKo
Цитата(Денис555 @ Jan 15 2016, 11:57) *
Да да, очепятка, акселератор... rolleyes.gif
А что Вы имеете ввиду под изменить латентность? Таковая частота понизится и должно быть все тоже самое, только растянется по времени...

Доступ к флэш-памяти. Чем меньше тактовая частота, тем меньше тактов можно задать для доступа. Там табличка есть, в референс руководстве, в разделе Flash.
Денис555
Цитата(ViKo @ Jan 15 2016, 13:17) *
Доступ к флэш-памяти. Чем меньше тактовая частота, тем меньше тактов можно задать для доступа. Там табличка есть, в референс руководстве, в разделе Flash.

Это да, сейчас wait state стоит 7 тактов (для моих 200 МГц). При уменьшении тактирования и соответственно wait state уменьшится, но и частота всех шин тоже.
Но чем черт не шутит, попробую, хотя сомневаюсь. Спасибо!
ViKo
Сама латентность не уменьшится с понижением тактовой частоты, а будет столько, сколько зададите. sm.gif
scifi
Не проще ли запустить этот код из ITCM RAM? Оно там как раз для таких дел.
Денис555
Это хорошая идея. Спасибо! Буду рыть информацию на то, как это сделать в Keil-е. Где то слышал, что люди запускали всю программу из ОЗУ в IAR-е.
Денис555
Всем спасибо! Проблема решилась. Все импульсы стали ровные как только перевел выполнение программы с шины AXIM на шину ITCM. Разумеется с включеным ART-акселератором.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.