C语言 为计算机和STM32中的变量给予特定地址

wh6knrhe  于 2023-02-07  发布在  其他
关注(0)|答案(1)|浏览(193)

我一直在使用STM32 hal驱动程序,我注意到当它们要为寄存器赋值时,它们会使用如下代码:

#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!

所以我试着用C在电脑上测试,但我有点困惑,下面的程序是我写的:

#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)

这程序将崩溃在inst->myTypeValue = 0x10; .否则它将显示这地址已经被分配给它.例如这是这输出:

#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

现在我有一些问题,stm32库工作是因为地址是寄存器而不是SRAM吗?因为我记得当我在FMC上使用SDRAM时,我可以在地址0xC0000000处做同样的事情,它工作得很好。
如果赋值是错误的,为什么编译器在第二个例子上工作,并且只在我试图使用结构体内部的变量时崩溃?为什么不在赋值inst = startaddress;时崩溃?

a8jjtwal

a8jjtwal1#

STM32中的这些地址是定义的,它们引用存储器Map的硬件寄存器。
您的代码是不同的。要与STM代码等效,它必须是:

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

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

stm32库工作是因为地址是寄存器而不是SRAM吗?
是的。您在STM CMSIS头文件中看到的那些地址(不是库!!!!)是由制造商定义的,并且与硬件相关。
因为我记得当我在FMC上使用SDRAM时,我可以在地址0xC 0000000处做同样的事情,它工作得很完美。
这是因为由灵活内存控制器管理的内存库之一在此地址暴露给内核。芯片制造商也定义了这些地址。
如果赋值错误,为什么编译器在第二个示例中工作,并且只在我尝试使用结构体内部的变量时崩溃?为什么不在赋值inst = startaddress时崩溃;它自己?
因为你定义了一个指针,并给它赋值,这是可以的。但是这个指针包含了一个无效的引用,当你试图解引用它时-系统失败了。
我认为你需要重读一下你最喜欢的C书中的指针章节,因为你对指针的理解相当有限。如果你想用裸机编程uC,这是相当重要的知识

相关问题