0

私は、32ビットARMベースのmicrontrollerを搭載した開発ボードに取り組んでいます(つまり、ボードはAtmel SAM D21J18Aです)。私はまだ学習段階にあり、やるべきことはたくさんありますが、組み込みシステムにはまっています。

C のバックグラウンドがありますが、明らかに十分ではありません。私は Atmel によるサンプル プロジェクトのコードを見ていましたが、実際にはその一部を取得できませんでした。ここにそれらの1つがあります:

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

ポートは次のように定義されます。

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

PortGroup は次のように定義されます。

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 を見て、そこにデータを取得すると、何が起こるでしょうか?

これを調べましたが、有用なものが見つかりませんでした。何か提案 (チュートリアル、書籍など) があれば、お知らせください。

4

2 に答える 2

2

一部の宣言しか提示しないため、何も起こりません。質問が実際に何であるかは完全にはわかりませんが、そのコードを簡単に説明するには:

  • 0x41004400UL明らかに、ポートが開始する (I/O レジスタのセット) I/O 空間 (通常のメモリではない) のアドレスです。

  • このポートは、単一レジスタの同様の配置を持つ 2 つのグループで構成されます

  • structPortGroupは、ハードウェア上に存在するレイアウトでこれらのレジスタを正確にモデル化します

レジスタの意味を知るには、ハードウェアのドキュメントを参照してください。

于 2015-07-07T08:07:30.053 に答える
0

通常、C のハードウェア レジスタには次の方法でアクセスできます。

#define PORT  (*(volatile uint8_t*)0x1234)
  • 0x1234レジスタアドレスです
  • uint8_tレジスタのタイプで、この場合は 1 バイトです。
  • volatileコンパイラがそのような変数を最適化できないことを知るために必要ですが、コードに記述されている変数への読み取りまたは書き込みは実際に行う必要があります。
  • (volatile uint8_t*)整数リテラルを目的の型のアドレスにキャストします。
  • 次に、左端*がそのアドレスの内容を取得するため、PORT が通常の変数であるかのようにマクロを使用できます。

これは何も割り当てないことに注意してください! 指定されたアドレスにハードウェア レジスタが存在し、指定された型 ( ) でアクセスできると想定しているだけuint8_tです。

同じ方法を使用して、他の C データ型を直接ハードウェア レジスタに対応させることもできます。たとえば、便利な構造体を使用して、特定のハードウェア ペリフェラルのレジスタ領域全体をマップできます。ただし、このようなコードは、アラインメント/構造体のパディングやエイリアシングなどを考慮する必要があるため、少し危険で疑わしいものです。


例の特定のコードに関しては、特定のマイクロコントローラーの特定のハードウェア周辺機器 (プレーンな汎用 I/O ポートのように見える) の典型的なひどいレジスタ マップです。通常、MCU をサポートする各コンパイラには、このようなビーストが 1 つ付属しています。

悲しいことに、このようなレジスタ マップは、常にひどい、完全に移植性のない方法で書かれています。たとえば、2 つのアンダースコア__は C では禁止されている識別子です。コンパイラもプログラマも、そのような識別子を宣言することはできません (7.1.3)。

本当に奇妙なのは、volatileキーワードが省略されていることです。これは、次のいずれかのシナリオがあることを意味します。

  • volatile キーワードは、Port定義の下に隠されています。ほとんどの場合、これが当てはまるか、または
  • レジスタマップは致命的なバグでいっぱいです、または
  • コンパイラは、変数をまったく最適化しないほどひどいがらくたです。これにより、問題volatileが解消されます。

これをさらに調査します。

構造体のパディングとエイリアシングに関しては、コンパイラ ベンダーは暗黙のうちに自社のコンパイラのみを使用することを前提としている可能性があります。同じ MCU に対して競合他社のコンパイラを切り替えることができるように、移植可能なレジスタ マップを提供することには関心がありません。

于 2015-07-07T11:01:16.737 に答える