この節では、ATmega48/88/168の各メモリについて説明します。 AVRアーキテクチャには、データメモリとプログラムメモリという二つのメインメモリ空間が存在します。 さらに、ATmega48/88/168はEEPROMをデータ保存用に備えています。どのメモリ空間も、リニアで標準的な構造になっています。
ATmega48/88/168 には、ISPにより再プログラム可能な4/8/16Kバイトの内蔵フラッシュ・メモリが実行プログラム格納用に備わっています。 すべてのAVRの命令は16または32ビット幅であるため、フラッシュメモリは 2/4/8K x 16ビットになっています。 ソフトウェアのセキュリティのため、ATmega88とATmega168では、フラッシュメモリ空間がブートローダー領域とアプリケーション・プログラム領域に分割されています。 ATmega48では、ブートローダー領域とアプリケーション・プログラム領域が分割されておらず、SPM命令はフラッシュメモリ領域のどこでも実効可能です。 詳細については、"SPMCSR Store Program Memory Control and Status Register"(p.266, およびp.282)にあるSELFPRGENの説明をご覧ください。
フラッシュメモリは10,000回以上の書き込み/消去サイクルが可能な耐久性をもっています。 ATmega48/88/168のプログラム・カウンタ(PC)は11/12/13ビット幅をもち、2/4/8Kのプログラム・メモリ・アドレスを指定することができます。 ブート・プログラム領域および、それに関連してソフトウェア・プロテクトのために用いるブート・ロック・ビットの詳細については「フラッシュ・メモリの自己プログラミング ATmega48」(p.261)、および「ブートローダーのサポート、読み書き並行自己プログラミング ATmega88/168」(p.268) を参照してください。 「メモリーのプログラミング」(p.284)にはSPI、またはパラレル・プログラミング・モードについての詳細な説明があります。
プログラム・メモリ空間のアドレスには、どこにでも定数テーブルを配置しておくことができます(LPM ロード・プログラムメモリ命令の説明を参照してください)。
命令フェッチと実行のタイミングについては、「命令の実行タイミング」(p.13)に説明があります。
Figure 7-3に、ATmega48/88/168 のSRAMメモリの構成を示します。
ATmega48/88/168 はIN、OUT命令で指定できる64個以内のアドレスで対応可能な範囲よりも多くの周辺機能を持つ複雑なマイクロ・コントローラーです。SRAMの0x60 - 0xFFにある拡張I/O領域には、ST/STS/STD および LD/LDS/LDD 命令が使用できます。
低位の768/1280/1280バイトのデータメモリ・アドレスには、レジスタ・ファイル、I/Oメモリアドレス、拡張I/Oメモリアドレス、および内蔵データRAMが含まれます。最初の32個のアドレス位置にはレジスタ・ファイルがあり、次に64個の標準I/Oメモリ、そして160個の拡張I/Oメモリ、そしてそれにつづく512/1024/1024個のアドレスに内蔵データSRAMが位置します。
5つのアドレッシング・モードがデータ・メモリのアドレスを指定するために使用できます:絶対アドレス指定、ディスプレースメントつき間接指定、間接指定、プレ・デクリメントつき間接指定、ポスト・インクリメントつき間接指定です。レジスタ・ファイルのうち、R26からR31は間接アドレッシングのためのポインタレジスタとしての機能を備えています。
直接指定では、データ・メモリ空間すべてを指定可能です。
ディスプレースメントつき間接指定では、ベースアドレスYまたはZの位置から63個のアドレス位置を指定可能です。
レジスタ間接アドレッシング・モードを自動プレ・デクリメントやポスト・インクリメントとともに使用すると、X、Y、およびZレジスタが増加または減少します。
ATmega48/88/168の、32個の汎用レジスタ、64個のI/Oレジスタ、160個の拡張I/Oレジスタ、および、512/1024/1024バイトの内蔵データSRAMの各アドレスは、全てこれらのアドレッシング・モードによって指定することが出来ます。レジスタ・ファイルについての説明は、「汎用レジスタ・ファイル」(p.11)を参照してください。
データ・メモリ | ||
---|---|---|
32 レジスタ | 0x000 - 0x001F | |
64 I/Oレジスタ | 0x020 - 0x005F | |
160 拡張I/Oレジスタ | 0x060 - 0x00FF | |
0x0100 | ||
内蔵SRAM (512/1024/1024 x 8) |
||
0x02FF/0x04FF/0x04FF |
この節では、内蔵メモリの一般的なアクセスタイミングについて説明します。内蔵データSRAMへのアクセスは、Figure 7-4にあるように、clkCPU 2クロック期間で実行されます。
ATmega48/88/168には、256/512/512バイトのEEPROMが搭載されています。分離されたデータ空間として構成されており、そこでは1バイトごとに読み出しと書き込みができます。EEPROMは100,000回以上の書き込み/消去サイクルの耐久性能があります。EEPROMとCPUのアクセスは、後述のように、EEPROMのアドレス・レジスタ、EEPROMのデータ・レジスタ、そして、EEPROMのコントロール・レジスタを指定する必要があります。
「メモリーのプログラミング」(p.284)に、SPIまたはパラレル・プログラミング・モードによるEEPROMのプログラミングについての詳細があります。
EEPROMのアクセス・レジスタには、I/O空間からアクセス可能です。
EEPROMのライト・アクセス時間はTable 7-2に記載されているとおりです。ただし、セルフ・タイミング機能により、ユーザー・ソフトウェアが次のバイト書き込みが可能になるタイミングを検出することが出来ます。ユーザー・プログラムがEPROMへの書き込みを行う命令を含んでいる場合、いくつか注意が必要な事項があります。供給電源に大きな定数のフィルタが接続されている場合、VCC端子の電圧は電力消費の増加/減少において、ゆっくりと立ち上がる、または立ち下がる傾向があります。この現象は、デバイスが、その動作クロック周波数において供給すべき最小電圧値を下回る時間帯を作る原因となります。このような状況における問題を回避する方法については、「EEPROMのデータ破壊を防止する」(p.19)を参照してください。
意図しないEEPROMへの書き込みを防止するために、指定された手順にしたがって書き込みを行う必要があります。詳細は、EEPROMコントロール・レジスタの説明を参照してください。
EEPROMを読み込む場合、CPUは次の命令を実行する前に4クロック停止します。EEPROMに書き込む場合、CPUは次の命令を実行する前に2クロック停止します。
VCCの電圧が低くなっている時間帯において、CPUとEEPROMの正常動作に必要な電圧が供給されていないと、EEPROMのデータが破壊される場合があります。この問題は、EEPROMを使用したボード上でおこるシステム・レベルの問題と同様のものであり、したがって、同様のソリューションにより解決することができます。
EEPROMデータの破壊は、供給電圧が低い場合に生じる二つのケースで発生する可能性があります。一つは、定められたEEPROMへの書き込みシーケンスが正しく動作するための最低電圧を下回る場合です。そしてつぎに、CPU自体が供給電圧が低すぎて正しく動作しない場合です。
EEPROMのデータ破壊は次のような推奨事項にしたがって設計を行うことで容易に回避できます。
それは、十分な供給電圧がない時間帯において、確実にAVRのRESETをアクティブ状態(Low)にすることです。これは、内蔵のブラウン・アウト検出回路(BOD)を有効にすることで実現できます。内蔵BODの検出電圧レベルが必要とされるレベルに適合していない場合には、外部に低電圧リセット保護回路を使用することで実現できます。書き込み動作実行中にリセットが発生した場合でも、その書き込み動作は十分な供給電圧がある間に完了します。
ATmega48/88/168のI/O空間の定義内容は、「各レジスタについて」(p.342)に記載されています。
ATmega48/88/168の入出力ポートおよび周辺回路は、全てI/O空間に配置されています。I/O空間の全アドレスに対して、LD/LDS/LDDおよびST/STS/STD命令でアクセスすることができ、32個の汎用レジスタとI/O空間との間でのデータのやりとりができます。
0x00-0x1Fの範囲のアドレスのI/Oレジスタには、SBIおよびCBI命令を使って直接ビットアクセスを行うことが可能です。これらのレジスタでは、単一のビットの値をSBISおよびSBIC命令を使って調べることができます。詳細については、命令セットの節を参照してください。I/O固有の命令であるINおよびOUTは、I/Oアドレスの0x00-0x3Fに対してのみ使用できます。I/Oレジスタへのアドレス指定をLDおよびST命令を使用してデータ空間としてアクセスする場合、0x20をそのアドレスに加算する必要があります。ATmega48/88/168は、INおよびOUT命令のオペコードで指定できる64個のアドレスで対応可能な範囲よりも多くの周辺機能をもっている複雑なマイクロコントローラーです。SRAM領域上の0x60-0xFFアドレスを通して拡張I/O空間にアクセスするために、ST/STS/STDおよびLD/LDS/LDD命令を使用することができます。
将来のデバイスとの互換性を保持するため、予約となっているビットにアクセスする場合はゼロを書き込んでください。予約となっているI/Oメモリアドレスには書き込みを行うべきではありません。
ステータス・フラグには、論理値1を書き込むことによってクリアされるものがあります。他のほとんどのAVRと異なり、CBIおよびSBI命令は指定されたビットに対してのみ実行され、そのため、上記のようなステータス・フラグを含んでいるレジスタにおいて使用することが可能です。CBIおよびSBI命令は0x00から0x1Fのレジスタでのみ動作します。
入出力ポートおよび周辺機能のコントロール・レジスタについては、後の各節において説明を記載します。
ATmega48/88/168には3つの汎用I/Oレジスタがあります。これらのレジスタには、どのような値でも格納することができ、特にグローバル変数やステータス・フラグを保存するのに便利です。0x00-0x1Fのアドレス範囲にある汎用I/Oレジスタには、SBI、CBI、SBIS、SBIC命令を使用して直接ビットアクセスすることが可能です。
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x22(0x42) | - | - | - | - | - | - | - | EEAR8 | EEARH |
0x22(0x41) | EEAR7 | EEAR6 | EEAR5 | EEAR4 | EEAR3 | EEAR2 | EEAR1 | EEAR0 | EEARL |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
Read/Write | R | R | R | R | R | R | R | R/W | |
R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W | ||
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | X | |
X | X | X | X | X | X | X | X |
これらのビットはATmega48/88/168では予約となっており、読み出し時には常にゼロとなります。
EEPROMアドレス・レジスタEEARHおよびEEARLは、256/512/512バイとのEEPROM領域のアドレスを指定するために用います。EEPROMデータ・バイトはアドレス0から255/511/511までのリニアに配置されています。EEARレジスタの初期値は未定義です。EEPROMにアクセスする前に、適切な値を書き込んでおく必要があります。
EEAR8 はATmega48では未使用のビットであり、常にゼロを書き込む必要があります。
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x20(0x40) | MSB | LSB | EEDR | ||||||
Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W | |
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
EEPROMの書き込み動作では、EEDRレジスタには、EEARレジスタで示されたEEPROM上のアドレスに書き込むためのデータが保持されます。EEPROMの読み出し動作では、EEDRレジスタには、EEARで指定されたアドレスから読み出されたデータが保持されます。
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x1F(0x3F) | - | - | EEPM1 | EEPM0 | EERIE | EEMPE | EEPE | EERE | EECR |
Read/Write | R | R | R/W | R/W | R/W | R/W | R/W | R/W | |
初期値 | 0 | 0 | X | X | 0 | 0 | X | 0 |
これらのビットはATmega48/88/168では予約となっており、読み出し時には常にゼロとなります。
EEPROMプログラミング・モード・ビットの設定により、EEPEビットへの書き込みで、どのプログラミング動作を開始するかが決定されます。分割されていない単一動作(古い値を消すと同時に新しい値を書き込む)によりデータ・プログラミングすることや、消去動作と書き込み動作を二つの別々の操作として分割することが可能です。それぞれのモードでのプログラミングのタイミングはTable7-1にあるとおりです。EEPEがセットされている間は、EEPMnビットへの書き込み動作は全て無視されます。リセット状態では、EEPROMがプログラミング中でビジーとなっていない限り、EEPMnビットは0b00にリセットされます。
EEPM1 | EEPM0 | 書き込み時間 | 動作 |
---|---|---|---|
0 | 0 | 3.4ms | 消去・書き込み同時(単一の動作) |
0 | 1 | 1.8ms | 消去のみ |
1 | 0 | 1.8ms | 書き込みのみ |
1 | 1 | - | (将来拡張予約) |
EERIEビットに1をセットすると、SREGのIビットがセットされている時にEEPROMレディー割込みが有効になります。EERIEにゼロを書き込むと、割込みは無効になります。EEPROMレディー割込みはEEPEがクリアされるたびに割込みを発生させます。ただし、EEPROMの書き込み期間中、およびSPM実行中は割込みは発生しません。
EEMPEビットは、EEPEを1にセットしたことによってEEPROMへの書き込みを行うかどうかを設定します。EEMPEがセットされている場合、EEPEビットを4クロック以内にセットすることでEEPROMの指定アドレスにデータ書き込みが行われます。EEMPEがゼロになっている場合、EEPEビットの設定は動作に無関係となります。EEMPEに対して、ソフトウェアにより1を書き込むと、4クロック後にハードウェアによってゼロにクリアされます。EEPEビットの詳細については、EEPROMの書き込み手順を参照してください。
EEPROM書き込み許可ビット EEPE はEEPROMへの書き込みストローブ信号として使用されます。アドレスとデータを正しくセットした後、EEPROMに値を書き込むために、EEPEビットに1を書き込む必要があります。EEPEビットに1を書き込む前に、EEMPEビットは1にセットしておかねばなければ、EEPROMへの書き込み動作は行われません。EEPROMへ書き込みを行うには、次のような手順(手順3と4の順序は必ずしもこのとおりでなくても可)が必要です。
EEPROMは、CPUがフラッシュメモリに書き込みを行っている間はプログラミング出来ません。EEPROMへの書き込みを開始する前に、ソフトウェアでフラッシュメモリへのプログラミングが完了していることを確認しておく必要があります。手順2は、CPUがフラッシュメモリに書き込みを行うブートローダーを搭載したソフトウェアにおいてのみ必要です。フラッシュメモリへのプログラミングをCPU自身によって行わない場合、手順2は省略可能です。ブートローダーによるプログラミングの詳細については、「ブートローダーのサポート、読み書き並行自己プログラミング ATmega88/168」(p.268)を参照してください。
注意: 手順5と手順6の間で割込みが発生すると、EEPROMのマスター書き込み許可ビットがタイムアウトするため、その書き込みサイクルは正しく実行されません。他のEEPROMへのアクセスの間に、EEPROMにアクセスする割込み処理では、EEARやEEDRレジスタが変更されるため、割込みされたEEPROMへのアクセスは正しく実行されません。グローバル割込み許可ビットをクリアして、EEPROMアクセス手順実行期間中において、このような問題が起きることを回避するようにしてください。
書き込み時間経過後、EEPEビットはハードウェアによってクリアされます。ユーザー・ソフトウェアでは、このビットをポーリングしてゼロになるのを待ってから、次のバイト書き込みを行います。EEPEがセットされると、CPUは次の命令を実行する前に2サイクル停止状態になります。
EEPROMリード・イネーブル信号EEREはEEPROMの読み出しストローブ信号として使用されます。正しいアドレスをEARレジスタにセットした後、EEREビットに1を書き込んでEEPROM読み出し動作を開始する必要があります。EEPROMの読み出しアクセスは1命令で実行され、要求されたデータは即座に利用可能となります。EEPROMを読み出すとき、CPUは次の命令を実行する前に4サイクル停止状態となります。
ユーザー・ソフトウェアではEEPEビットを監視してから、読み出しを実行するようにしてください。書き込み動作が進行中の場合、EEPROMから読み出しを行うことも、EARレジスタを変更することもできません。
EEPROMへのアクセス時間を計測するために、調整済み発振器が使用されます。Table 7-2 にCPUからEEPROMへのプログラミングに必要な通常値が記載されています。
記号 | 調整済みRC発振器のクロック数 | プログラミング時間(Typ) |
---|---|---|
EEPROM write (from CPU) | 26,368 | 3.3ms |
以下のプログラム例で、アセンブリ言語とC言語によるEEPROMの書き込みを例示します。この例では割込みは(例えば、グローバル割込み許可ビットにより)全て抑制されており、この関数を実行する期間では割込みが発生しないものと仮定しています。また、この例ではソフトウェアにはブートローダーによるフラッシュ書き込みは無い、という前提です。そういったコードが存在する場合には、EEPROMへの書き込み関数は、進行中のSPM命令が完了するまで待機する必要があります。
アセンブリ言語での例 |
|
C言語での例 |
|
次のプログラム例は、アセンブリ言語とC言語でのEEPROM読み出し関数の例を示しています。この例では、割込みは抑制されており、関数実行中に割込みが発生することはないものと仮定しています。
アセンブリ言語での例 |
|
C言語での例 |
|
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2B(0x4B) | MSB | LSB | GPIOR2 | ||||||
Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W | |
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2A(0x4A) | MSB | LSB | GPIOR1 | ||||||
Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W | |
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x1E(0x3E) | MSB | LSB | GPIOR0 | ||||||
Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W | |
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |