2019-04-23 11:31 AM
Hello,
Has anyone succeeded in getting the timer cookbook examples (specifically the TIM_ExtCLK_ETR)
working on the STM32F303RE? I've been beating my head against the wall for a while now and still haven't seen the light. I'm using the IAR Embedded workbench. I took the original project and did the following:
The project builds fine with no errors but it doesn't run correctly. I'm driving a 1KHs 0-4.5V square wave into PA1 on a Nucleo 64 board. I turned the compiler optimization option to none so I could debug. When debugging, I see that the program always hangs on the following line:
/* wait until the transfer complete*/
while ((DMA1->ISR & DMA_ISR_TCIF7) == RESET)
{
}
So, I assume there is a 302R8 vs 303RE difference in clocking, TIM, or DMA setup but I'm unaware what the key difference is. Below is the setup code from the AN4776 timer cookbook TIM_ExtCLK_ETR example:
Thanks for any pointers.
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* @brief Configure the TIM2 peripheral:
* + ETR MODE : - HSI : 8MHz
* - Divider : 4
* - Polarity : High
* - ETR pin : Channel 1
* + Internal source clock mode: - HSI : 8MHz
*
* Counter mode : UP Counter
* Clock Division : 1
* Period : 0xFFFFFFFF
* Prescaler : 0
* input Channel : Channel 2
* @param None
* @retval None
*/
static void TIM2_Config(void)
{
/* TIM2 clock enable */
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
/* Set the Timer prescaler to get 8MHz as counter clock */
Prescaler = (uint16_t) (SystemCoreClock / 8000000) - 1;
/* Reset the SMCR register */
TIM2->SMCR = RESET;
#ifdef USE_ETR
/* Configure the ETR Clock source:
+ Asychronous divider : 4
+ Polarity : Rising Edge
*/
TIM2->SMCR |= (TIM_ETRPRESCALER_DIV4 | TIM_ETRPOLARITY_NONINVERTED);
TIM2->SMCR |= TIM_SMCR_ECE;
/******** Configure the Internal Clock source ********************************/
#else /* Internal clock source*/
/* Disable slave mode to clock the prescaler directly with the internal clock
if the TIM_SMCR is in the reset value, we can delete the following instruction*/
TIM2->SMCR &= ~TIM_SMCR_SMS;
#endif /* USE_ETR*/
/* Configure the Time base:
+ Counter mode : UP Counter
+ Clock Division : 1
+ Period : 0xFFFFFFFF
+ Prescaler : 0
*/
/* Select the up counter mode */
TIM2->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
TIM2->CR1 |= TIM_COUNTERMODE_UP;
/* Set the clock division to 1 */
TIM2->CR1 &= ~TIM_CR1_CKD;
TIM2->CR1 |= TIM_CLOCKDIVISION_DIV1;
/* Set the Autoreload value */
TIM2->ARR = PERIOD ;
/* Set the Prescaler value */
TIM2->PSC = Prescaler;
/* Generate an update event to reload the Prescaler value immediatly */
TIM2->EGR = TIM_EGR_UG;
/* Configure the Timer Input Capture Channels:
+ Channel : Channel 2
*/
/* Connect the Timer input to IC2 */
TIM2->CCMR1 &= ~TIM_CCMR1_CC2S;
TIM2->CCMR1 |= TIM_CCMR1_CC2S_0;
}
/**
* @brief Configure the DMA1 peripheral:
* Data Transfer Direction : Peripheral to Memory
* Peripheral Increment : Disable
* Memory Increment : Enable
* Peripheral Data Size : Word
* Memory Data Size : Word
* Data Transfer Mode : Normal
* Priority Level : High
* Peripheral Address : TIM2_CCR2 register
* Memory Address : aBuffer
* The length of transfered data : BUFFER_SIZE
* @param None
* @retval None
*/
static void DMA1_Config(void)
{
/* Reset the DMA Channel 7 Control register*/
DMA1_Channel7->CCR = ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
DMA_CCR_DIR));
/* Configure the DMA1 Channel 7 */
/* Set the direction bits : Peripheral to Memory */
DMA1_Channel7->CCR |= DMA_PERIPH_TO_MEMORY;
/* Disable the Peripheral increment */
DMA1_Channel7->CCR |= DMA_PINC_DISABLE;
/* Enable the Memory increment */
DMA1_Channel7->CCR |= DMA_MINC_ENABLE;
/* Set the Peripheral Data size to Word*/
DMA1_Channel7->CCR |= DMA_PDATAALIGN_WORD;
/* Set the Memory Data size to Word*/
DMA1_Channel7->CCR |= DMA_MDATAALIGN_WORD;
/* Set the transfer mode to Normal*/
DMA1_Channel7->CCR |= DMA_NORMAL;
/* Set the Priority to High*/
DMA1_Channel7->CCR |= DMA_PRIORITY_HIGH;
/* Configure the source, destination address and the data length */
DMA1_Channel7->CNDTR = CAPTURE_BUFFER_SIZE;
/* Configure DMA Channel destination address */
DMA1_Channel7->CPAR = (uint32_t)&(TIM2->CCR2);
/* Configure DMA Channel source address */
DMA1_Channel7->CMAR = (uint32_t)aCaptureBuffer;
/* Enable the transfer Error interrupt */
DMA1_Channel7->CCR |= DMA_IT_TE;
}
/**
* @brief Starts the TIM2 Input Capture measurement on DMA mode :
* Channel : TIM_CHANNEL_2
* @param None
* @retval None
*/
static void TIM2_DMA1_Capture(void)
{
/* Enable the DMA1 */
DMA1_Channel7->CCR |= DMA_CCR_EN;
/* Enable the TIM Capture/Compare 2 DMA request */
TIM2->DIER |= TIM_DMA_CC2;
/*Enables the TIM Capture Compare Channel 2.*/
TIM2->CCER |= TIM_CCER_CC2E;
/*Enable the TIM2*/
TIM2->CR1 |= TIM_CR1_CEN;
/* wait until the transfer complete*/
while ((DMA1->ISR & DMA_ISR_TCIF7) == RESET)
{
}
}
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__DMA1_CLK_ENABLE();
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
}