什么是((端口*)0x41004400UL)的意思是在这里吗? [英] What does ((Port *)0x41004400UL) mean here?

查看:991
本文介绍了什么是((端口*)0x41004400UL)的意思是在这里吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个开发板,上有一个32位基于ARM microntroller(即板是Atmel SAM D21J18A)。我仍然在学习阶段,我有很多去,但我真的到嵌入式系统中。

I'm working on a developing board that has a 32-bit ARM based microntroller on it (namely the board is Atmel SAM D21J18A). I'm still at the learning phase and I have a lot to go, but I'm really into embedded systems.

我在C.一些背景然而,这显然是不够的。我一直在寻找在$ C $由Atmel实例项目的CS,我并没有真正得到它的某些部分。这里是其中的一个:

I have some background in C. However, it's obviously not enough. I was looking at the codes of an example project by Atmel, and I didn't really get some parts of it. Here is one of them:

    #define PORT              ((Port     *)0x41004400UL) /**< \brief (PORT) APB Base Address */

端口被定义为:

    typedef struct {
        PortGroup             Group[2];    /**< \brief Offset: 0x00 PortGroup groups [GROUPS] */
    } Port;

和端口组的定义是:

typedef struct {
    __IO PORT_DIR_Type             DIR;         /**< \brief Offset: 0x00 (R/W 32) Data Direction */
    __IO PORT_DIRCLR_Type          DIRCLR;      /**< \brief Offset: 0x04 (R/W 32) Data Direction Clear */
    __IO PORT_DIRSET_Type          DIRSET;      /**< \brief Offset: 0x08 (R/W 32) Data Direction Set */
    __IO PORT_DIRTGL_Type          DIRTGL;      /**< \brief Offset: 0x0C (R/W 32) Data Direction Toggle */
    __IO PORT_OUT_Type             OUT;         /**< \brief Offset: 0x10 (R/W 32) Data Output Value */
    __IO PORT_OUTCLR_Type          OUTCLR;      /**< \brief Offset: 0x14 (R/W 32) Data Output Value Clear */
    __IO PORT_OUTSET_Type          OUTSET;      /**< \brief Offset: 0x18 (R/W 32) Data Output Value Set */
    __IO PORT_OUTTGL_Type          OUTTGL;      /**< \brief Offset: 0x1C (R/W 32) Data Output Value Toggle */
    __I  PORT_IN_Type              IN;          /**< \brief Offset: 0x20 (R/  32) Data Input Value */
    __IO PORT_CTRL_Type            CTRL;        /**< \brief Offset: 0x24 (R/W 32) Control */
    __O  PORT_WRCONFIG_Type        WRCONFIG;    /**< \brief Offset: 0x28 ( /W 32) Write Configuration */
    RoReg8                         Reserved1[0x4];
    __IO PORT_PMUX_Type            PMUX[16];    /**< \brief Offset: 0x30 (R/W  8) Peripheral Multiplexing n */
    __IO PORT_PINCFG_Type          PINCFG[32];  /**< \brief Offset: 0x40 (R/W  8) Pin Configuration n */
    RoReg8                         Reserved2[0x20];
} PortGroup;

所以在这里,我们正在寻找在地址0x41004400UL,得到的数据在那里,然后发生了什么?

So here, we are looking at the address 0x41004400UL, get the data in there, and then what happens?

我抬头一看这个,但找不到任何有用的东西。如果您有任何建议(教程,书籍等),请让我听到。

I looked up for this but couldn't find anything useful. If you have any suggestions (tutorials, books etc.), please let me hear.

推荐答案

一般来说,你可以访问硬件寄存器用C以这种方式:

Generally you can access a hardware register in C in this manner:

#define PORT  (*(volatile uint8_t*)0x1234)


  • 0×1234 是寄存器地址

  • uint8_t有是寄存器的类型,在这种情况下,1个字节大。

  • 挥发性是必需的,这样编译器知道它不能优化这样一个变量,但每次读或写在code规定的变量必须实际上是完成。

  • (挥发性uint8_t有*)注塑整数文字所需类型的地址。

  • 最左边的 * 然后采取地址的内容,使宏可用于就像PORT是一个普通的变量。

    • 0x1234 is the register address
    • uint8_t is the type of the register, in this case 1 byte large.
    • volatile is required so that the compiler knows it cannot optimize such a variable, but that each read or write to the variable stated in the code must actually be done.
    • (volatile uint8_t*) casts the integer literal to an address of the desired type.
    • The left-most * then take the contents of that address, so that the macro can be used just as if PORT was a regular variable.
    • 请注意,这不分配任何东西!它只是假定有一个硬件寄存器present在给定的地址,可以通过指定的类型进行访问( uint8_t有)。

      Note that this does not allocate anything! It just assumes that there is a hardware register present at the given address, which can be accessed by the type specified (uint8_t).

      使用,还可以有其他的C数据类型直接对应硬件寄存器的方法相同。例如,通过使用一个方便的结构,可以映射特定的硬件外设的整个寄存器区域。例如code然而有点危险和可疑的,因为它必须采取的东西像对齐/结构填充和走样帐户。

      Using the same method you can also have other C data types to correspond directly hardware registers. For example by using a handy struct, you can map the whole register area of a particular hardware peripheral. Such code is however a bit dangerous and questionable, since it must take things like alignment/struct padding and aliasing in account.

      至于在你的榜样具体code,它是一个典型的可怕的寄存器映射为一个特定的硬件外设(看起来像一个普通的通用I / O口)在某微控制器。一个这样的野兽一般具有每个编译器支持MCU。

      As for the specific code in your example, it is a typical awful register map for a particular hardware peripheral (looks like a plain general-purpose I/O port) on a certain microcontroller. One such beast is typically provided with each compiler supporting the MCU.

      这样的寄存器映射黯然总是写在可怕的,完全不可移植的方法。例如,两个下划线 __ 是C.禁标识符无论是编译器和程序员被允许这样的声明标识符(7.1.3)。

      Such register maps are sadly always written in awful, completely non-portable ways. For example, two underscores __ is a forbidden identifier in C. Neither the compiler nor the programmer is allowed to declare such identifiers (7.1.3).

      什么是真正奇怪的是,他们已经省略了挥发性关键字。这意味着,你这里有这些情形之一:

      What's really strange is that they have omitted the volatile keyword. This means that you have one of these scenarios here:


      • volatile关键字隐藏在下方端口定义。最有可能的是这种情况,或者

      • 寄存器映射充满了致命的错误,或者

      • 编译器就是这样一个可怕的一块垃圾,它并没有在所有优化变量。这将使问题与挥发性走开。

      • The volatile keyword is hidden beneath the Port definition. Most likely this is the case, or
      • The register map is full of fatal bugs, or
      • The compiler is such an awful piece of crap that it doesn't optimize variables at all. Which would make the issues with volatile go away.

      我将进一步展开调查。

      至于结构填充和混叠,编译器厂商可能已经隐含地假定只有他们的编译器将被使用。他们在为您提供一个便携式寄存器映射,这样就可以切换竞争对手的编译器相同的MCU没有兴趣。

      As for struct padding and aliasing, the compiler vendor has likely implicitly assumed that only their compiler is to be used. They have no interest in providing you with a portable register map, so that you can switch the the competitor's compiler for the same MCU.

      这篇关于什么是((端口*)0x41004400UL)的意思是在这里吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆