ビットバンド

ビットバンド

従来のビット操作(リード、モディファイ、ライト)

RAMやレジスタの1ビットだけを変更したい場合、Cortex-M3では、ビットバンドという方式で、1命令で変更できます。従来、RAMやレジスタの1ビットだけを変更したい場合、バイト単位で、リード、モディファイ、ライト処理を行わなければなりませんでした。

図1

このリード、モディファイ、ライト処理の最中に割り込み等のイベントが発生すると処理が中断され、場合によっては、モディファイ中のデータが変化してしまうという問題がありました。そこで、従来方式では、まず最初に外部イベント(割り込み)を禁止して、変更したいビットの含まれているバイトを読み出し、変更したいビット以外をマスクして、変更したいビットだけを変更します。そして、もとの場所に戻して、最後に外部イベント(割り込み)を有効にするという、手間がかかりました。

ビットバンド方式では、この1連の作業が、1命令(新命令ではない従来の命令)で行うことができます。

ビットバンド方式

ビットバンド方式とは、簡単に言うと、RAMやレジスタの各ビットがアドレス単位で指定できるエイリアス領域を持っており、そのエイリアスを変更することにより、オリジナルのビットが自動的に変更されるというものです。エイリアス領域は各ビットに対し、1アドレスが対応しているため、そのアドレスに変更後の値を書き込む1命令だけで、オリジナルのビットが変更できます。(かなり贅沢なメモリの使い方ですよね)

メモリマップは、2つの1MBビットバンド領域にマップされる2つの32MBエイリアス領域を持っています。

図2
  • ●1MBのSRAMビットバンド領域は、32MBのSRAMエイリアス領域にマッピングされます。具体的には、20000000h〜200FFFFFhの1MBのエイリアスは22000000h〜23FFFFFFhにマッピングされています。
  • ●1MBのペリフェラルビットバンド領域は、32MBのペリフェラルエイリアス領域にマッピングされます。具体的には、40000000h〜400FFFFFhの1MBのエイリアスは42000000h〜43FFFFFFhにマッピングされています。

マッピングの式により、エイリアス領域の各ワード(32ビット)が、ビットバンド領域の対応するビット(ターゲットのビット)に、どのように参照されるのかを示します。マッピングの式は次のとおりです。

 bit_word_offset = (byte_offset x 32) + (bit_number × 4)
 bit_word_addr = bit_band_base + bit_word_offset

bit_word_offset ビットバンド領域での、ターゲットビットの位置
bit_word_addr エイリアス領域での、ターゲットビットがマップされるワードのアドレス
bit_band_base エイリアス領域の開始アドレス
byte_offset ビットバンド領域での、ターゲットビットを含むバイトの位置(バイト数)
bit_number (ビットバンド領域の)ターゲットビット(を含むバイト中での)のビット位置(0〜7)

SRAMのエイリアス領域とSRAMのビットバンド領域との間におけるビットバンドのマッピング例を示します。

  • ●200FFFFFhにあるビットバンド領域のバイトのビット[0]は、23FFFFE0hにあるエイリアスのワードにマッピングされます。
    23FFFFE0h = 22000000h + (FFFFFh*32) + 0*4
  • ●200FFFFFhにあるビットバンド領域のバイトのビット[7]は、23FFFFFChにあるエイリアスのワードにマッピングされます。
    23FFFFFCh = 22000000h + (FFFFFh*32) + 7*4

エイリアス領域へのワードの書き込みは、ビットバンド領域のターゲットビットに対する読み出し-変更-書き込み操作と同じ効果があります。エイリアス領域のワードに書き込まれる値のビット[0] により、ビットバンド領域のターゲットビットに書き込まれる値が決定されます。
ビット[0]が1にセットされた値を書き込むと、ビットバンド領域の該当ビットに1が書き込まれ、
ビット[0]が0にクリアされた値を書き込むと、ビットバンド領域の該当ビットに0が書き込まれます。

ビットバンド領域とエイリアス領域との関係

エイリアス領域のワード中のビット[31:1]は、ビットバンド領域のビットには影響しません。
0x01の書き込みは、0xFFの書き込みと同じ効果があります。
0x00の書き込みは、0x0Eの書き込みと同じ効果があります。
エイリアス領域でのワードの読み出しは、0x01または0x00を返します。(読み出しでは、ビット[31:1]は常に0です。)

0x01という値は、ビットバンド領域のターゲットビットが1にセットされていることを示します。
0x00という値は、ターゲットビットが0にクリアされていることを示します。