0

i have been working with STM32 hal drivers and i noticed when they want to give a value to a register , they use some code like this :

#define     __IO    volatile

typedef struct
{
  __IO uint32_t CR1;    /*!< USART Control register 1,                 Address offset: 0x00 */
  __IO uint32_t CR2;    /*!< USART Control register 2,                 Address offset: 0x04 */
  __IO uint32_t CR3;    /*!< USART Control register 3,                 Address offset: 0x08 */
  __IO uint32_t BRR;    /*!< USART Baud rate register,                 Address offset: 0x0C */
  __IO uint32_t GTPR;   /*!< USART Guard time and prescaler register,  Address offset: 0x10 */
  __IO uint32_t RTOR;   /*!< USART Receiver Time Out register,         Address offset: 0x14 */
  __IO uint32_t RQR;    /*!< USART Request register,                   Address offset: 0x18 */
  __IO uint32_t ISR;    /*!< USART Interrupt and status register,      Address offset: 0x1C */
  __IO uint32_t ICR;    /*!< USART Interrupt flag Clear register,      Address offset: 0x20 */
  __IO uint32_t RDR;    /*!< USART Receive Data register,              Address offset: 0x24 */
  __IO uint32_t TDR;    /*!< USART Transmit Data register,             Address offset: 0x28 */
  __IO uint32_t PRESC;  /*!< USART clock Prescaler register,           Address offset: 0x2C */
} USART_TypeDef;

#define D2_APB1PERIPH_BASE    (0x40000000UL)
#define UART4_BASE            (D2_APB1PERIPH_BASE + 0x4C00UL)
#define UART4                 ((USART_TypeDef *) UART4_BASE)

UART4->CR = whatever!

so i tried to test on computer with C but i got a little confused , the program below is the one i wrote :

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define startaddress ((mytype*) (0x6d9ff93b))
    typedef struct
    {
        volatile uint32_t myTypeValue;
    }mytype;
    
    int main()
    {
        mytype* inst;
        inst = startaddress;
        inst->myTypeValue = 0x10;
        printf("address is : %x \n",inst);
        return 0;
    }
output : 
Process finished with exit code -1073741819 (0xC0000005)

the program will crash at inst->myTypeValue = 0x10; . otherwise it will show the address which has been assign to it . for example this is the output :

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define startaddress ((mytype*) (0x6d9ff93b))
    typedef struct
    {
        volatile uint32_t myTypeValue;
    }mytype;
    
    int main()
    {
        mytype* inst;
        inst = startaddress;
  // inst->myTypeValue = 0x10;
        printf("address is : %x \n",inst);
        return 0;
    }

output : 
address is : 6d9ff93b

Process finished with exit code 0

now i have some question , dose the stm32 library works because the address is a register and not the SRAM ? because i remember when i use SDRAM on FMC i can do the same at address 0xC0000000 and it works perfectly.

if the assignment is wrong why does the compiler works on second example and only crashes when i am trying to use the variable inside the struct ? why not crash at the assignment inst = startaddress; it self ?

3
  • 1
    You cannot do this on just any “computer with C”. When you use a general-purpose multi-user system, the operating system and programming environment arrange all the memory addresses for you. If you try to fix an address where you will put an object, you are likely to crash because you are accessing unmapped memory or to disrupt data needed for your program to run correctly. Using fixed addresses is for special hardware purposes, and the addresses used must be coordinated with the hardware and software on the system. Commented Feb 3, 2023 at 21:11
  • 1
    On a computer you have a Memory Management Unit which only allows your program to use addresses that are allocated to it by the operating system. Commented Feb 3, 2023 at 21:12
  • 1
    Re “why not crash at the assignment inst = startaddress; it self ?”: Because setting a pointer to point to some arbitrary place is generally harmless (albeit not defined by the C standard), just the same as it is not a problem if you write down some stranger’s address on a piece of paper. It is only when you try to go into the stranger’s house that you meet objections. Commented Feb 3, 2023 at 21:13

1 Answer 1

2

Those addresses in STM32 are defined and they reference memory-mapped hardware registers.

Your code is different. To be equivalent to the STM one it has to be:

    #define inst ((mytype*) (0x6d9ff93b))
    typedef struct
    {
        volatile uint32_t myTypeValue;
    }mytype;
    
    int main()
    {

          inst -> mytepevalue = 10;
          .....

dose the stm32 library works because the address is a register and not the SRAM ?

Yes. Those addresses you see in the STM CMSIS headers (not the library!!!!) are defined by the manufacturer and are hardware related.

because i remember when i use SDRAM on FMC i can do the same at address 0xC0000000 and it works perfectly.

It is because one of banks of memory managed by the Flexible Memory Controller is exposed to the core at this address. The chip manufacturer also defines those addresses.

if the assignment is wrong why does the compiler works on second example and only crashes when i am trying to use the variable inside the struct ? why not crash at the assignment inst = startaddress; it self ?

Because you define a pointer and assign it with value and it is OK. But this pointer contains an invalid reference and when you try to dereference it - the system fails.

I think you need to reread the pointers chapter in your favourite C book as your understanding of pointers is rather limited. It is quite important knowledge if you want to bare-metal program uCs

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.