IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Embarqué Discussion :

Firmware STM32F4 (GPIO question n°2) [STM32]


Sujet :

Embarqué

  1. #1
    Membre actif
    Homme Profil pro
    Technicien Layout
    Inscrit en
    Août 2015
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Technicien Layout

    Informations forums :
    Inscription : Août 2015
    Messages : 275
    Points : 292
    Points
    292
    Par défaut Firmware STM32F4 (GPIO question n°2)
    Bonsoir je repars ds les conditions ternaires je me suis rendu fou avec la configuration des fonctions alternées, je pense retomber sur le résultat qu'il faut avoir dans le registre GPIOx_AFR:

    Bits 31:0 AFRLy: Alternate function selection for port x bit y (y = 0..7)
    These bits are written by software to configure alternate function I/Os
    AFRLy selection:
    0000: AF0
    0001: AF1
    0010: AF2
    0011: AF3
    0100: AF4
    0101: AF5
    0110: AF6
    0111: AF7
    1000: AF8
    1001: AF9
    1010: AF10
    1011: AF11
    1100: AF12
    1101: AF13
    1110: AF14
    1111: AF15
    Pour ma part je recherche a avoir la fonction alternée n°7 qui correspond a l'USART1 donc mon registre doit etre égal ==> 0b 0000 0111

    Voici un morceau de la fonction qui permet d'associer la pin TX a la fonction USART:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    /**
      * @brief  Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
      * @param  GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
      *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
      * @param  GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
      *         the configuration information for the specified GPIO peripheral.
      * @retval None
      */
    void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
    {
      uint32_t position;
      uint32_t ioposition = 0x00;
      uint32_t iocurrent = 0x00;
      uint32_t temp = 0x00;
     
      /* Check the parameters */
      assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
      assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
      assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
      assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
     
      /* Configure the port pins */
      for(position = 0; position < GPIO_NUMBER; position++)
      {
        /* Get the IO position */
        ioposition = ((uint32_t)0x01) << position;
        /* Get the current IO position */
        iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
     
        if(iocurrent == ioposition)
        {
          /*--------------------- GPIO Mode Configuration ------------------------*/
          /* In case of Alternate function mode selection */
          if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
          {
            /* Check the Alternate function parameter */
            assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
            /* Configure Alternate function mapped with the current IO */
            temp = GPIOx->AFR[position >> 3];
            temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
            temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
            GPIOx->AFR[position >> 3] = temp;
          }

    Ensuite je vais lister les éléments manquant pour réussir a calculer ces conditions:

    GPIO_NUMBER = 16 (pour la boucle for)
    GPIO_Init->Pin = ((uint16_t)0x0200) (Pin 9 selected)
    GPIO_Init->Alternate = ((uint8_t)0x07) (USART1 Alternate Function mapping)

    Allez au boulot!

    On passe les déclarations et assert_param qui sert juste a contrôler les paramètres rentrant, renvoi un 0 si ça correspond et un 1 si cela ne correspond pas, le 1 ayant pour conséquence de stopper le prg

    Attaquons nous a la boucle for, donc tant que "position" n'est pas supérieur a 16, "position" s'incrémente.

    Donc "position" vaut 1 puis 2 puis 3 etc...

    Donc la variable "ioposition" va également changer en fonction de "position" et cela va nous intéresser au moment ou "position" = 9 car a ce moment "ioposition" = 0b 0000 0010 0000 0000 ou 0x 0200 (retenez cette valeur)

    Passons a la ligne suivante, "iocurrent" prend la valeur d'un ET entre GPIO_Init->Pin & ioposition ==> 0b 0000 0010 0000 0000 & 0000 0010 0000 0000 ==> donc au moment ou position vaut 9 "iocurrent" = 0b 0000 0010 0000 0000.

    On continu, toujours au moment ou "position" = 9 on entre dans la condition ==> if(iocurrent == ioposition)

    Ensuite on entre également ds la condition ==> if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) car dans le fichier d'initialisation via la structure GPIO_InitTypeDef on a configuré le mode ==> GPIO_MODE_AF_PP ( avec AF = alternant function et PP = Push-Pull).

    Rentrons ds le vif du sujet (assert_param déjà expliqué passons a la suite):

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    temp = GPIOx->AFR[position >> 3];
    a l'issue de cette opération temp = 0b 0000 0001; (car 0000 1001 >> 3 = 0000 0001)

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
    a l'issue de cette opération temp = 0b 0000 0001.

    Si je détail:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    (position & (uint32_t)0x07)
    0000 1001 & 0000 0111 = 0b 0000 0001

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    ((uint32_t)(position & (uint32_t)0x07) * 4))
    0000 0001 * 0000 0100 = 0b 0000 0100

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    ((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4))
    décalage de 0b 0000 1111 << 0b 0000 0100 = 0b 1111 0000

    0b 0000 1111

    0b 0000 0001 & 0b 0000 1111 = 0b 0000 0001 ==> nouvelle valeur de temp

    Voila pour cette ligne, et première question pourquoi avoir fait cette ligne alors que temp vaut tjrs la mm valeur avt et après manipulation ?

    Passons a la seconde lignes avec un début de calcul idem:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
     ((uint32_t) position & (uint32_t)0x07)
    0000 1001 & 0000 0111 = 0b 0000 0001

    Sur cette ligne j'ai pu observé une différence d'associativité avec la ligne précédente les parenthèse ne sont pas placées au même endroit je ne pense pas qu'il y ait d'importance ds ce cas.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    (((uint32_t) position & (uint32_t)0x07) * 4))
    0000 0001 * 0000 0100 = 0b 0000 0100

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4))
    decalage de 0b 0000 0111 << 0b 0000 0100 = 0b 0011 1000

    0b 0000 0001 | 0b 0011 1000 = 0b 0011 1001

    Dernière ligne:

    Pour cette ligne je n'en suis pas sur mais je pense que cela se produit comme ça car on retombe sur la valeur souhaitée car si on décale temp de 3 on obtient

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    GPIOx->AFR[position >> 3] = temp;
    0b 0011 1001 >> 3 = 0b 0000 0111 t c'est la valeur qu'il faut pour que AF = 7 (voir le début du post).

    Bon ben me suis bien cassé la tète et pour ce qui auront la foi de lire jusqu'au bout ce post merci pour votre aide!
    L’art est une activité humaine, le produit de cette activité ou l'idée que l'on s'en fait s'adressant délibérément aux sens, aux émotions, aux intuitions et à l'intellect. www.elise-galerie.com

  2. #2
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Salut Julien,
    Qu'est ce que tu ne comprends pas exactement ?

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* 1 */ temp = GPIOx->AFR[position >> 3];
    /* 2 */ temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
    /* 3 */ temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
    /* 4 */ GPIOx->AFR[position >> 3] = temp;

    En fait c'est la manière la plus propre pour mettre à 1 le ou les bits concernés sans toucher au reste de la configuration
    le & permet de lire les bits avec un masque adapté
    le | permet de mettre à 1 uniquement les bits concernés au travers d'un masque

    C'est le détail que tu veux comprendre ?
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  3. #3
    Membre actif
    Homme Profil pro
    Technicien Layout
    Inscrit en
    Août 2015
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Technicien Layout

    Informations forums :
    Inscription : Août 2015
    Messages : 275
    Points : 292
    Points
    292
    Par défaut
    Salut Vincent,

    ce que j'ai cru comprendre depuis les quelques semaines ou je décortique le programme c'est que l'on utilise l'opérateur binaire & pour forcer a 0 les bits qui nous intéressent ou on utilise l'opérateur binaire | pour mettre a 1 les bits qui nous intéressent.

    Du coup quand je vois l'affectation &=~ je comprends que l'on mets a 0 les bits que l'on veut ré-initialiser et quand je vois l'affectation |= on mets a 1 les bits en fonction de nos besoins de modification du registre.

    • Masking
    Bit-or: num | mask 0b0001 | 0b1000 → 0b1001
    Bit-and: num & mask 0b1001 & 0b1000 → 0b1000


    Par contre dans la configuration des fonctions alternées il y a quelque chose que je n'ai pas compris notamment sur la dernière ligne.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* 1 */ temp = GPIOx->AFR[position >> 3]; // temp = 0b 0000 0001 (voir calcul ds précédent post)
    /* 2 */ temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; // temp = 0b 0000 0001 (voir calcul ds précédent post)
    /* 3 */ temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));  // temp = 0b 0011 1001 (voir calcul ds précédent post)
    /* 4 */ GPIOx->AFR[position >> 3] = temp;  // le pb pour moi est sur cette ligne puisque je la lis comme ça GPIOx->AFR[1001 >> 3] prends la valeur (=) temp soit "0011 1001" et 1001 correspond a la fonction AF9
    L’art est une activité humaine, le produit de cette activité ou l'idée que l'on s'en fait s'adressant délibérément aux sens, aux émotions, aux intuitions et à l'intellect. www.elise-galerie.com

  4. #4
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Citation Envoyé par julien terrier Voir le message
    ce que j'ai cru comprendre depuis les quelques semaines ou je décortique le programme c'est que l'on utilise l'opérateur binaire & pour forcer a 0 les bits qui nous intéressent ou on utilise l'opérateur binaire | pour mettre a 1 les bits qui nous intéressent.
    Du coup quand je vois l'affectation &=~ je comprends que l'on mets a 0 les bits que l'on veut ré-initialiser et quand je vois l'affectation |= on mets a 1 les bits en fonction de nos besoins de modification du registre.

    • Masking
    Bit-or: num | mask 0b0001 | 0b1000 → 0b1001
    Bit-and: num & mask 0b1001 & 0b1000 → 0b1000
    Oui c'est bien ça, j'ajouterai aussi que & permet de lire certain bit, par exemple si je veux lire les 4 bits de poids forts de la valeur 0b 1101 0101
    tmp = valeur & mask
    tmp = 0b 1101 0101 & 0b 1111 0000
    tmp = 0b 1101 0000 // 4 bits de poids fort extrait de la valeur initiale 0b 1101 0101

    Bon, ok je vois ! Tu veux le détail de ce qui se passe
    Par contre il y a un truc qui ne me va pas dans ton calcul (le premier message) et dès le premier calcul en plus (c'est sûrement pour ça que tu tournes en rond )

    Citation Envoyé par julien terrier Voir le message
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    temp = GPIOx->AFR[position >> 3];

    a l'issue de cette opération temp = 0b 0000 0001; (car 0000 1001 >> 3 = 0000 0001)
    En fait non, ça ne veut pas dire que temp vaut 1.
    Ça veut dire que
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    temp = GPIOx->AFR[0b000 0001]; // temp vaut la valeur contenue, dans le tableau GPIOx->AFR[1] (à l'index 1)
    // En faite GPIOx->AFR[ ] est un tableau dont tu as calculé l'index en faisant position >> 3 mais en réalité tu ne sais pas pour autant ce qu'il y a à cette adresse

    Je ne sais pas si j'ai été clair mais dit autrement c'est comme ci je disais que :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char tab[] = "Julien"
    char tmp;
     
    tmp = tab[0]; // tmp vaut 0 .... mais en faite non pas du tout, tmp vaut 'J'

    Il faut savoir comment est fait GPIOx->AFR[ ] et savoir ce qu'il y a dedans pour comprendre ce que vaut tmp.
    A+
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  5. #5
    Membre actif
    Homme Profil pro
    Technicien Layout
    Inscrit en
    Août 2015
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Technicien Layout

    Informations forums :
    Inscription : Août 2015
    Messages : 275
    Points : 292
    Points
    292
    Par défaut
    Bonsoir Vincent,

    merci pour cette précision, effectivement je n'ai pas inclus que l'on pointé le tableau AFR[]. Suite a ta demande voici la déclaration du tableau AFR[] avec GPIO_TypeDef qui est un typdef sur la structure qui le contient.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
     __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */

    Donc on a un tableau de 2 nombres entier positif (unsigned long) et ce tableau prendra un espace de 8 octets contigu dans la mémoire ( j'ai bien révisé mes cours ).

    Cela doit correspondre au deux registres des fonctions alternées ==> GPIOx_AFRH et GPIOx_AFRL si on pointe AFR[0] on accède au registre Low tandis que si on pointe AFR[1] on accède au registre High donc dans mon cas on accède au registre High ce qui me va puisque l'on parle de la pin 9 du port A et selon le manuel de référence pour les pins 8 a 15 il faut modifier le registre de fonction alternée High.

    Et donc les octets 5,6,7 et 8 qui sont alloués pour le tableau prendront la valeurs temp, on est d'accord ?

    Je rectifie également le calcul de l'avant dernière ligne:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));// a l'issue temp = 0b 0000 0000 0000 0000 0000 0000 0111 0000

    Ce qui correspond au bit 4,5 et 6 du registre GPIOx_AFRH ( voir le fichier attaché) est que ce passe t-il quand on initialise ces bits a 1 bingo on active la fonction alternée 7 sur la pin 9 !

    Alors la c'est du grand art, merci pour ton aide grâce a toi je progresse je progresse.
    Images attachées Images attachées  
    L’art est une activité humaine, le produit de cette activité ou l'idée que l'on s'en fait s'adressant délibérément aux sens, aux émotions, aux intuitions et à l'intellect. www.elise-galerie.com

  6. #6
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Nous sommes tous les deux d'accord !
    Et voilà CQFD !

    Pas de quoi l'ami ! Par contre si un jour il y a une malheureuse question, sur le forum, concernant un micro ST.... tu as intérêt de m'aider
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [STM32] Firmware STM32F4 (GPIO question n°1)
    Par julien terrier dans le forum Embarqué
    Réponses: 32
    Dernier message: 30/09/2015, 17h32
  2. [STM32] Firmware STM32F4 (UART question n°2)
    Par julien terrier dans le forum Embarqué
    Réponses: 12
    Dernier message: 10/09/2015, 21h14
  3. [STM32] Firmware STM32F4 (UART)
    Par julien terrier dans le forum Embarqué
    Réponses: 21
    Dernier message: 29/08/2015, 20h03
  4. Question de faisabilité
    Par lisarasu dans le forum CORBA
    Réponses: 3
    Dernier message: 14/05/2002, 11h26
  5. [HyperFile] 2 questions de débutant
    Par khan dans le forum HyperFileSQL
    Réponses: 2
    Dernier message: 29/04/2002, 23h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo