cancel
Showing results for 
Search instead for 
Did you mean: 

Simultaneous EXTI and timer interrupt configuration

avidroneg
Associate III

On the STM32F303K8, is it possible to configure e.g. PA8 to both receive an EXTI interrupt on falling edge and act as the TIM1CH1 input to trigger source TI1FP1, in turn serving as a timer gate for gated mode?

I cannot find a way to express this through MX, which usually means it isn't possible at all, but perhaps it could be done through explicit HAL calls.

6 REPLIES 6
mƎALLEm
ST Employee

Hello,

That's not possible as it depends on the IO config especially GPIOx_MODER:

mALLEm_0-1762273582905.png

For the timer you need to set the alternate function mode (10b), while for EXTI you need to set it as input mode (00b). So you can't do that simultaneously.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

That's exactly what I was looking for - thank you very much.

> for EXTI you need to set it as input mode

@mƎALLEm Do you have a source for that?

The EXTI part of the manual doesn't mention this, or I'm missing it.

 

This is certainly possible on the STM32F4 series without input mode (any mode except analog works). I suspect it's possible here as well, but not clickable in CubeMX. Don't have an F3 board to try it on.

TDK_0-1762274551705.png

 

If you feel a post has answered your question, please click "Accept as Solution".

That's interesting. I could try it locally. My guess is that it would involve:

  1. Allowing the MX configuration for TIM1 as generated:
TIM_HandleTypeDef htim1;
// ...
static void MX_TIM1_Init(void);
// ...
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_TIM1;
  PeriphClkInit.Tim1ClockSelection = RCC_TIM1CLK_HCLK;
// ...

/**
  * @brief TIM1 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

// ...

/**
  * @brief TIM_Base MSP Initialization
  * This function configures the hardware resources used in this example
  * @PAram htim_base: TIM_Base handle pointer
  * @retval None
  */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(htim_base->Instance==TIM1)
  {
    /* USER CODE BEGIN TIM1_MspInit 0 */

    /* USER CODE END TIM1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM1 GPIO Configuration
    PA8     ------> TIM1_CH1
    */
    GPIO_InitStruct.Pin = nBUTTON_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(nBUTTON_GPIO_Port, &GPIO_InitStruct);

    /* TIM1 interrupt Init */
    HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
    /* USER CODE BEGIN TIM1_MspInit 1 */

    /* USER CODE END TIM1_MspInit 1 */
  }

2. Calling my own EXTI configuration as MX would have:

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  // ...
  GPIO_InitStruct.Pin = nBUTTON_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(nBUTTON_GPIO_Port, &GPIO_InitStruct);

// ...
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */

  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(nBUTTON_Pin);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

 

...But that doesn't look safe. One HAL_GPIO_Init call specifies Alternate and one doesn't.

waclawek.jan
Super User

Of course that's possible.

This is one of the things which is notoriously impossible to do in Cube/CubeMX only because Cube is designed so. AFAIK there is a particular order of Cube function calls which results in this working, reported at this forum by users several times in the past, but I don't use Cube (and the usual caveat, Cube does change, so anything not designed in may stop working if you recompile it after a Cube update).

The best way is not to use Cube if Cube does not support everything you need.

JW

Try GPIO_MODE_IT_FALLING | GPIO_MODE_AF_OD in a single call. I think that works.

If that doesn't work, you'll have to edit registers.

If you feel a post has answered your question, please click "Accept as Solution".