Ich habe ein Nucleo-401RE (STM32F401) Board. Ich versuche, einen Timer (TIM4) so einzurichten, dass er über 2 MHz (bei Bare-Metal-Code) funktioniert.
Gemäß den folgenden Timer-Einstellungen soll ich 10,5 MHz erhalten. Am Oszilloskop erhalte ich nur 2 MHz.
Habe ich die richtige Konfiguration vorgenommen? Gibt es einen Weg, um es schneller zu machen (ich habe die gleiche Hz, wenn ich das Timer-Perload-Register auf 3 setze)
#include "stm32f4xx.h"
#include "dbg_pin.h"
#define DBG_PIN_HIGH(p,x) (p->BSRR = (uint16_t)x)
#define DBG_PIN_LOW(p,x) (p->BSRR = (uint32_t) x << 16)
#define DBG_PIN_TOGL(p,x) ((p->ODR & x)? DBG_PIN_LOW(p,x) : DBG_PIN_HIGH(p,x))
TIM_HandleTypeDef hTimSlice;
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
return ;
}
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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
return ;
}
}
uint8_t timer_init()
{
__HAL_RCC_TIM4_CLK_ENABLE();
hTimSlice.Instance = TIM4;
hTimSlice.Init.Prescaler = 0;
hTimSlice.Init.Period = 7;
hTimSlice.Init.ClockDivision = 0;
hTimSlice.Init.CounterMode = TIM_COUNTERMODE_UP;
hTimSlice.Init.AutoReloadPreload= TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&hTimSlice) != HAL_OK){
return 1;
}
HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
return 0;
}
void TIM4_IRQHandler()
{
if(__HAL_TIM_GET_FLAG(&hTimSlice, TIM_FLAG_UPDATE) != RESET) {
if(__HAL_TIM_GET_IT_SOURCE(&hTimSlice, TIM_IT_UPDATE) !=RESET) {
__HAL_TIM_CLEAR_IT(&hTimSlice, TIM_IT_UPDATE);
}
}
DBG_PIN_TOGL(GPIOC, GPIO_PIN_8);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
setupDbgPin();
timer_init();
HAL_TIM_Base_Start_IT(&hTimSlice);
for(;;);
}
Danke.
Die ISR-Montageliste (unten). Gezählte Befehlsausführungszeit basierend auf Arm-M4-Befehlssatz und ungefähr (37) Zyklen gefunden. Beachten Sie, dass es sich nur um das Umschalten eines Pins handelt.
Bei 84 MHz sind (37) Befehle * 12 ns = 444 ns.
Und es ist wahr, Sie können keine Timer-Rate von >2 MHz (oder schlechter) erreichen. Ich denke, die Idee, einen Timer mit höherer Rate zu verwenden, besteht darin, ihn mit anderen Diensten wie DMA zu verwenden.
70 if(__HAL_TIM_GET_FLAG(&hTimSlice, TIM_FLAG_UPDATE) != RESET) {
TIM4_IRQHandler:
08000f80: ldr r3, [pc, #40] ; (0x8000fac <TIM4_IRQHandler+44>)
08000f82: ldr r3, [r3, #0]
08000f84: ldr r2, [r3, #16]
08000f86: lsls r0, r2, #31
08000f88: bpl.n 0x8000f96 <TIM4_IRQHandler+22>
71 if(__HAL_TIM_GET_IT_SOURCE(&hTimSlice, TIM_IT_UPDATE) !=RESET) {
08000f8a: ldr r2, [r3, #12]
08000f8c: lsls r1, r2, #31
72 __HAL_TIM_CLEAR_IT(&hTimSlice, TIM_IT_UPDATE);
08000f8e: itt mi
08000f90: mvnmi.w r2, #1
08000f94: strmi r2, [r3, #16]
75 DBG_TOGL(GPIO_PIN_8);
08000f96: ldr r3, [pc, #24] ; (0x8000fb0 <TIM4_IRQHandler+48>)
08000f98: ldr r2, [r3, #20]
08000f9a: lsls r2, r2, #23
08000f9c: ite mi
08000f9e: movmi.w r2, #16777216 ; 0x1000000
08000fa2: movpl.w r2, #256 ; 0x100
08000fa6: str r2, [r3, #24]
76 }
08000fa8: bx lr
08000faa: nop
08000fac: lsls r4, r3, #17
08000fae: movs r0, #0
08000fb0: lsrs r0, r0, #32
08000fb2: ands r2, r0
jsotola
bare-metal code
?alsalem
Misaz
alsalem