STM32F411: effacement d'une interruption externe drapeau-elle vraiment nécessaire?

J'ai acheté un STM32F411 nucleo conseil et maintenant je suis en train d'essayer de comprendre les divers morceaux de HAL. En commençant avec des interruptions externes semblait être une bonne idée, parce que le conseil d'administration dispose d'un bouton poussoir qui est connecté à PC13. J'ai donc créé une simple bascule-la fréquence de blinky. Le code ci-dessous est un peu simplifié:

#define LED_PIN GPIO_PIN_5
#define BTN_PIN GPIO_PIN_13

static uint32_t blink_period = 250;

int main(void)
{
  HAL_Init();
  SystemClock_Config();

  __GPIOA_CLK_ENABLE();
  GPIO_InitTypeDef pinConfig;
  pinConfig.Pin = (LED_PIN);
  pinConfig.Pull = GPIO_NOPULL;
  pinConfig.Mode = GPIO_MODE_OUTPUT_PP;
  pinConfig.Speed = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOA, &pinConfig);

  __GPIOC_CLK_ENABLE();
  pinConfig.Pin = (BTN_PIN);
  pinConfig.Pull = GPIO_NOPULL;
  pinConfig.Mode = GPIO_MODE_IT_FALLING;
  pinConfig.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOC, &pinConfig);
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x0F, 0x00);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

  while (1)
  {
    HAL_GPIO_TogglePin(GPIOA, LED_PIN);
    HAL_Delay(blink_period);
  }
}

void EXTI15_10_IRQHandler(void)
{
  HAL_GPIO_EXTI_IRQHandler(BTN_PIN);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == BTN_PIN)
  {
    if (blink_period == 500)
    {
      blink_period = 250;
    }
    else
    {
      blink_period = 500;
    }
  }
}

Lorsque j'appuie sur le bouton, une interruption est générée et le blinky les changements de fréquence de 1 à 2 Hz (ou vice-versa). Cela fonctionne comme prévu, mais pourquoi? J'ai oublié d'effacer l'attente de l'interruption du drapeau, de sorte que le rapport de recherche internationale devrait être appelé à plusieurs reprises. La fiche technique indique clairement que

Lorsque l'arête sélectionnée se produit sur l'interruption externe de la ligne, une demande d'interruption est générée. Dans l'attente de bits correspondant à la ligne d'interruption est également définie. Cette demande est
réinitialisation par l'écriture d'un " 1 " dans l'attente de vous inscrire.

Lecture un peu plus loin révèle que c'est un peu différent pour les événements:

Lorsque l'arête sélectionnée se produit sur la ligne de l'événement, un événement impulsion est générée. Dans l'attente de bits correspondant à la ligne de l'événement n'est pas définie.

Cependant, je ne suis pas le réglage de la goupille de bouton mode pour toute la GPIO_MODE_EVT_... modes, donc je ne suis pas en utilisant le mécanisme d'événements (pour être honnête je ne sais pas encore ce que c'est - je pense que je ne suis pas à l'utiliser. Tous les conseils sont les bienvenus).

Donc quelque part que je devrais appeler void HAL_NVIC_ClearPendingIRQ (IRQn_Type IRQn), ne devrais-je pas? Il semble que la désactivation de l'indicateur par le logiciel n'est pas nécessaire, parce que le rapport de recherche internationale n'est pas appelé plus d'une fois par flanc descendant. J'ai ajouté un point d'arrêt dans HAL_GPIO_EXTI_Callback pour vérifier cela.

Modifier

Comme mentionné dans les commentaires, l'indicateur de compensation de code de la SAINT de la mise en œuvre de la GPIO gestionnaire d'interruption:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

Ce gestionnaire doit être appelé par les ISR (ce qui est fait dans mon code) et il efface l'attente de drapeau correspondant à la GPIO_Pin argument. Donc, je dois écrire un rapport de recherche internationale qui trie, qui les drapeaux sont en jeu, et d'appeler HAL_GPIO_EXTI_IRQHandler pour chaque, ce qui à son tour appelle mon HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin), de nouveau avec la broche comme un argument. Pour chaque interruption externe, le numéro de broche serait vérifiée certains ~3 fois (dans le rapport de recherche internationale, dans le gestionnaire et dans le rappel)!

Si c'est la solution, je veux que mon problème de dos.

Je suis à peu près certain que ce n'est pas cochée dans HAL_GPIO_EXTI_IRQHandler() - vous n'avez pas de nous montrer la source de cette fonction particulière... Et - comme d'habitude - ce type de problèmes sont évités par PAS à l'aide de cette pseudo-bibliothèque de SAINT - il ne résout rien, vous donner plus de problèmes à penser. Et il est donc extrêmement misérable, que je ne peux pas regarder ce code...
Oh - votre variable blink_period devrait vraiment être déclaré volatile.
en effet, le traitement des interruptions externes est assez compliqué et je pense que je ne veux même pas essayer les pilotes pour les plus complexes des périphériques. HAL_GPIO_EXTI_IRQHandler() est fourni par ST - j'ai eu un coup d'oeil, et en effet, il en efface l'indicateur en question. Donc, existe-il des solutions de rechange pour le Cube?
Rien de ce que je connais (Il y libopenCM3 - je n'ai pas l'utiliser, donc je ne sais pas ce que ça vaut. Les périphériques sont assez simples, donc personnellement je viens d'utiliser mon propre code, à l'aide de SPL (Cube prédécesseur) par exemple quand je ne comprends pas quelque chose, ou quand quelque chose ne fonctionne pas comme il devrait. Si vous le souhaitez, vous pouvez vérifier STM32F4 exemple de projet à partir de mon site web - vous avez GPIO de la configuration et de l'horloge (ccs) de la configuration à l'aide de registres, de sorte que vous voyez comment ce regard. L'exemple n'est pas pour nucleo, mais il faudra travailler lorsque vous modifiez les paramètres dans la configuration.h fichier.
vous n'êtes probablement pas encore regarder, mais pour les autres prestations, le STM32Cube paquet a un tas d'exemples qui utilisent le pilote de HAL. Voir st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897 ou st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897/...

OriginalL'auteur Christoph | 2014-11-23