|
Странное поведение STM32F745 |
|
|
|
Jan 14 2016, 16:17
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
Доброго времени суток! Столкнулся с проблемой при использовании STM32F745. Элементарная программа: В main в бесконечном цикле происходит постоянный вызов процедуры, в которой следующее: 1. выставили лог. 1 на GPIO 2. пустой цикл задержки 3. сбросили пин GPIO (лог. 0) 4. пустой цикл задержки ... и далее повторение пунктов 1-4 4 раза. Все пустые циклы сделал ассемблерными вставками (чтобы наверняка, компилятор проглатывает как есть). На осциллографе 3 первых получившихся импульса и пауз между ними одинаковые, а четвертый импульс растянут раз в 5 больше. Эффект независим от длительности импульсов. При добавлении кол-ва импульсов этот эффект может проявиться где угодно в разных импульсах и паузах 1 и более раз. Тактирование PLL - 200 МГц от внешнего генератора 25 МГц. Пробовал и c HAL-ом и без него. Кроме GPIO и RCC (тактирование) ничего не включено. Все прерывания отключены. Питание норм. Что это может быть? Уже всю голову сломал и уже не я один. Приветствуются любые предложения. Спасибо!
|
|
|
|
|
Jan 14 2016, 16:55
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
Пишу в Keil-е. В ассемблерном листинге все ровно как и хотелось, компилятор оставляет всавки как есть. В отладке все красиво пробегает. Все по порядку, ни шагу в лево ни шагу вправо. На практике чудеса...
|
|
|
|
|
Jan 14 2016, 17:28
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
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 такие непонятные явления, очень странно...
Сообщение отредактировал IgorKossak - Jan 14 2016, 19:33
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Jan 15 2016, 07:07
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
Про SysTick и про DWT - это все понятно, можно, но не для моей реализации. Нужно решить именно эту задачу. Что такое конвейер тоже в курсе, работал. Добавленный акселерометр должен ускорять, а не тормозить процесс. Пробовал отключать и включать акселерометр, не помогает. Отключение ICash к изменению результата не приводит.
Даже если решить эту проблему другим образом, встретить в программе подряд идущих несколько циклов, не обязательно задержек, очень легко. И представьте, что МК, ни с того ни с сего, будет выполнять один из циклов в 5 раз дольше... Это нормально? Я понял бы если +- 20 - 50 тактов куда то уходило... Но столько...
Варианты задержек просьба не предлагать. Все способы реализаций известны. Нужно именно понять почему один из циклов растягивается в 5 раз? Причем с добавлением циклов растянутый может быть любой из них или даже не один.
Появилась новая интересная штука. Если перед циклом, который задерживается вставить NOP тогда все идет нормально. Иногда нужно вставить не один NOP. Похоже на проблему с выравниваниями. Но не факт. Но вот теперь вопрос, как этого избежать? ICache включаю! В отладке вижу, что включен. Не помогает. Может кто знает в Keil-е макрос, который производит выравнивание NOP-ми во флешке автоматически?
Кратно 32, 64 байта...
Сообщение отредактировал Денис555 - Jan 15 2016, 05:38
|
|
|
|
|
Jan 15 2016, 08:32
|
Гуру
     
Группа: Участник
Сообщений: 2 219
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143

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

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
Цитата(ViKo @ Jan 15 2016, 11:47)  У вас конвейер 7-ступенчатый!  Задумайтесь. Если программа куда-то перескакивает (в начало цикла), конвейер переписывается. Можно проверить. Понизить тактовую частоту, изменить латентность конвейера. Акселерометр != Акселератор.  Да да, очепятка, акселератор... А что Вы имеете ввиду под изменить латентность? Таковая частота понизится и должно быть все тоже самое, только растянется по времени... По поводу перезаписи конвейера: Если так случится, что к примеру ему пришлось переписАться, то была бы аддитивная задержка в начале одного цикла на несколько тактов, но не постоянно же...? Конвейер - 6 ступенчатый
|
|
|
|
|
Jan 15 2016, 10:15
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 29-09-06
Из: Самара
Пользователь №: 20 827

|
Цитата(ViKo @ Jan 15 2016, 13:17)  Доступ к флэш-памяти. Чем меньше тактовая частота, тем меньше тактов можно задать для доступа. Там табличка есть, в референс руководстве, в разделе Flash. Это да, сейчас wait state стоит 7 тактов (для моих 200 МГц). При уменьшении тактирования и соответственно wait state уменьшится, но и частота всех шин тоже. Но чем черт не шутит, попробую, хотя сомневаюсь. Спасибо!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|