Thread: Advanced (I think) pointer questions.

  1. #1
    Registered User
    Join Date
    Dec 2012
    Posts
    15

    Advanced (I think) pointer questions.

    I am working with a STM32f1 micro. In the standard peripheral libraries, I noticed they use some very organized methods of accessing the many registers and peripherals. I do not understand a small portion of this.
    Code:
    typedef struct
    {
      __IO uint32_t ACR;
      __IO uint32_t KEYR;
      __IO uint32_t OPTKEYR;
      __IO uint32_t SR;
      __IO uint32_t CR;
      __IO uint32_t AR;
      __IO uint32_t RESERVED;
      __IO uint32_t OBR;
      __IO uint32_t WRPR;
    #ifdef STM32F10X_XL
      uint32_t RESERVED1[8]; 
      __IO uint32_t KEYR2;
      uint32_t RESERVED2;   
      __IO uint32_t SR2;
      __IO uint32_t CR2;
      __IO uint32_t AR2; 
    #endif /* STM32F10X_XL */  
    } FLASH_TypeDef;
    #define FLASH               ((FLASH_TypeDef *) FLASH_R_BASE) 
    /*******************  Bit definition for FLASH_CR register  ******************/
    #define  FLASH_ACR_LATENCY                   ((uint8_t)0x03)               /*!< LATENCY[2:0] bits (Latency) */
    #define  FLASH_CR_LATENCY_0                 ((uint8_t)0x00)               /*!< Bit 0 */
    #define  FLASH_CR_LATENCY_1                 ((uint8_t)0x01)               /*!< Bit 0 */
    #define  FLASH_CR_LATENCY_2                 ((uint8_t)0x02)               /*!< Bit 1 */
    #define  FLASH_CR_HLFCYA                    ((uint8_t)0x08)               /*!< Flash Half Cycle Access Enable */
    #define  FLASH_CR_PRFTBE                    ((uint8_t)0x10)               /*!< Prefetch Buffer Enable */
    #define  FLASH_CR_PRFTBS                    ((uint8_t)0x20)               /*!< Control Register Status */
    This code is used to access registers for micro operational control. I could write "FLASH -> CR &= FLASH_CR_LATENCY_0;" to set or clear bits. I understand how pointers are generally used to access memory bits, but I do not understand how this typedef is put before the asterisk in the FLASH define. Can anyone explain whats going on clearly? If I am not mistaken, the typedef structure is simply a means of using the correct size pointer to point the specific memory address, and nothing more. I really could replace the FLASH_TypeDef * with __IO uint32*, correct? By the way __IO is macro for volatile. Thanks much!

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    The relevant code is just a cast.

    It says "Convert whatever type the variable `FLASH_R_BASE' really is into a `FLASH_TypeDef *' for my use.".

    Soma

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,793
    if you run you compiler with flags that specify to generate of the code output after preprocessor, your fine looking line
    Code:
    FLASH -> CR &= FLASH_CR_LATENCY_0;
    will be changed into
    Code:
    ((FLASH_TypeDef *) FLASH_R_BASE) -> CR &=  ((uint8_t)0x00);
    So it is just accessing the member of the struct by pointer to this struct while pointer type is all wrong - so type cast is needed.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    David J. Wheeler

  4. #4
    Registered User
    Join Date
    Dec 2012
    Posts
    15
    vart, I understand that this change would be made. But if you took that change one step farther, what code would replace (FLASH_TypeDef *)? Phantomotap, I am confused by your response. The variable FLASH_R_BASE is simply a #define.
    Code:
    #define FLASH_R_BASE          (AHBPERIPH_BASE + 0x2000) /*!< Flash registers base address */
    It is simply a hex value address. Your response does not make sense to me.

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    1,654
    Quote Originally Posted by DanielB33 View Post
    The variable FLASH_R_BASE is simply a #define.
    So the code would cast the address (an integer) to be a pointer to the FLASH structure type:

    Code:
    ((FLASH_TypeDef *) (AHBPERIPH_BASE + 0x2000)) -> CR &=  ((uint8_t)0x00);
    


  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    It is simply a hex value address. Your response does not make sense to me.
    O_o

    I take it you haven't been working with embedded development for very long.

    1): The macro `HBPERIPH_BASE' is the base address of the define range for targeting.
    2): The `0x2000' is an offset from the base address to the necessary flash registers.
    3): The value `AHBPERIPH_BASE + 0x2000' is just a hex value address which your compiler treats as an integer type value.
    4): The statement `((FLASH_TypeDef *) (AHBPERIPH_BASE + 0x2000))' takes the integer type statement and casts the result into a pointer so that you can treat the calculated address as a pointer to a structure of type `FLASH_TypeDef'.

    So, you are correct, the define is just an integer type value representing an address.

    That is the problem.

    Code:
    (AHBPERIPH_BASE + 0x2000) -> CR &=  ((uint8_t)0x00);
    This is wrong. An integer value is not a structure so contains no members.

    The cast tells the compiler to treat the value as a pointer to a structure.

    Code:
    ((FLASH_TypeDef *) (AHBPERIPH_BASE + 0x2000)) -> CR &=  ((uint8_t)0x00);
    This is perfectly fine as `FLASH_TypeDef' is a structure with members.

    Soma

  7. #7
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    FLASH_TypeDef is just an alias for the structure.
    Code:
    // you can name the struct as you would if you were not typedef'ing it
    struct xyz {
       int a;
       int b;
    };
    // create the alias
    typedef struct xyz xyz_typedef;
    
    // declare some variables
    struct xyz a;
    xyz_typedef b;
    
    // a and b refer to the same type. you can say
    a = b; 
    // ==================
    // alternatively, you can combine the named structure and typedef
    typedef struct xyz {
       int a;
       int b;
    } xyz_typedef;
    
    
    struct xyz a;
    xyz_typedef b;
    
    // a and b refer to the same type. you can say
    a = b; 
    
    // ==================
    // now, if leave out the name of the structure, you just have the type 'xyz_typedef'
    
    // note struct is not named now
    typedef struct {
       int a;
       int b;
    } xyz_typedef;
    
    
    // struct xyz a; // this would give a compile error
    xyz_typedef a;
    xyz_typedef b;
    
    // a and b refer to the same type. you can say
    a = b;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointer Questions
    By tgrieger in forum C Programming
    Replies: 4
    Last Post: 04-09-2011, 10:14 PM
  2. Two Pointer Questions
    By chris.r in forum C Programming
    Replies: 13
    Last Post: 06-04-2010, 09:40 PM
  3. Advanced pointer use
    By mvanrijnbach in forum C Programming
    Replies: 9
    Last Post: 03-04-2010, 01:17 AM
  4. Pointer questions
    By 1rwhites in forum C Programming
    Replies: 1
    Last Post: 10-20-2005, 09:55 AM
  5. 2 Quick Pointer Questions:
    By Krak in forum C++ Programming
    Replies: 7
    Last Post: 01-24-2003, 09:41 PM