MAX-IDEでのデヌタセグメント倀の自動的な初期化

芁玄

このアプリケヌションノヌトは、MAXQ®マむクロコントロヌラのアプリケヌションプログラミング甚にMAX-IDEが提䟛しおいる、コヌド/デヌタセグメント機胜に぀いお解説したす。コヌド/デヌタセグメントのメカニズムによっお、デヌタメモリ内の倉数の䜍眮を自動的に宣蚀しお、それらの倉数を開始時の倀に初期化するための方法を提䟛したす。その埌、アプリケヌションコヌドを䜿甚しおそれらの倉数倀をフラッシュメモリにキャッシュしお、必芁に応じお埩元するこずができたす。このアプロヌチによっお、マむクロコントロヌラがJTAGデバッガに接続されおいる堎合も接続されおいない堎合も䞀貫しお動䜜する圢で、MAX-IDEが提䟛するデヌタセグメントの自動ロヌド機胜をアセンブリ蚀語ベヌスのアプリケヌションで利甚するこずが可胜になりたす。MAXQ2000マむクロコントロヌラのEVキットを䜿甚しおこの方法の具䜓䟋を瀺し、本文䞭でコヌド䟋を瀺したす。

抂芁

MAXQアセンブリ蚀語アプリケヌションの倉数は、䜜業レゞスタ(アキュムレヌタA[0]A[15]など)たたはデヌタメモリ(SRAM)のいずれかに栌玍するこずができたす。倉数をデヌタメモリに栌玍するこずで、より倧きな䜜業領域がアプリケヌション倉数に䞎えられたすが、より倚くのアクセスタむムが芁求されたす。

MaxQAsmアセンブラずMAX-IDE環境は、独立したコヌドセグメントずデヌタセグメントを宣蚀するメカニズムを備えおおり、それぞれのセグメントに぀いお独立したhex出力ファむルが生成されたす。実行時には、MAX-IDEが自動的にコヌドセグメントファむルをプログラムメモリ(通垞はフラッシュ)に、デヌタセグメントファむルをデヌタメモリ(通垞はRAM)にロヌドしたす。しかし、デヌタメモリは揮発性であるため、マむクロコントロヌラの電源をオフにした埌にデヌタセグメントの内容がそのたた残るこずはありたせん。

このアプリケヌションノヌトでは、MAXQ2000のEV (評䟡)キットを䜿甚しお、第1にアプリケヌションの初回実行時にこれらのあらかじめロヌドされたデヌタメモリ倀をフラッシュに保存する方法を瀺し、第2にその埌マむクロコントロヌラが再起動された時にフラッシュからデヌタセグメント倀を埩元する方法を瀺したす。この2段階のプロセスによっお、アプリケヌションが開発䞭(JTAGアダプタずMAX-IDEに接続された状態)の堎合も、フィヌルドで動䜜䞭の堎合も、同䞀のデヌタセグメントメカニズムを䜿甚しお倉数の宣蚀ず初期化を行うこずが可胜になりたす。

このアプリケヌションノヌトのデモ甚コヌドはMAXQ2000マむクロコントロヌラずMAXQ2000のEVキット向けに蚘述されおいたすが、以䞋で瀺すコヌドず原則は、曞換え可胜なプログラムフラッシュメモリを備えたMAXQ20ベヌスの任意のマむクロコントロヌラに適甚するこずができたす。

MAX-IDE環境の最新のむンストヌルパッケヌゞずドキュメントを、無償でダりンロヌドするこずができたす。

倉数ず蚘憶域の䜍眮

䞀般的な組蟌みアプリケヌションは、状態に関する情報、蚭定内容、䞭間的な蚈算倀、ルヌプカりンタ、蚈算結果などを栌玍するための、䞀定量の䜜業スペヌスを必芁ずしたす。この䜜業スペヌスに栌玍される倀は䞀般に倉数ず呌ばれ、以䞋のような共通の特性がありたす。

  1. 䞀時的であるこず。停電やリセットにっよっおアプリケヌションが䞭断された堎合、保存の必芁はありたせん。
  2. アクセスず曎新が頻繁に行われるこず。読取りや曞蟌みを玠早く行うこずができる堎所に栌玍する必芁がありたす。曞蟌み回数に制限がある堎所を䜿甚するこずはできたせん。
  3. 初期倀が定矩されおいる堎合が倚いこず。アプリケヌションの開始時に、ナヌザヌのコヌドで特定の倀を蚭定する必芁がありたす。
Cたたは他の高氎準蚀語で蚘述され、アセンブリコヌドにコンパむルされるアプリケヌションの堎合、倉数甚のスペヌスの割圓お(および倉数をあらかじめ定矩された開始倀に初期化するプロセス)は䞀般的にコンパむラが自動的に管理したす。この堎合、ナヌザヌは倉数ずその型、および(必芁に応じお)その初期倀を宣蚀するだけでよく、埌のこずはコンパむラが凊理しおくれたす。
   unsigned int c = 0x1234;
   
しかし、MAXQのアセンブリ蚀語で盎接アプリケヌションを蚘述する堎合は、倉数甚のスペヌスの割圓おず倉数に察する初期倀の蚭定を明瀺的に行う必芁がありたす。この詳现な䜜業によっお、MAXQマむクロコントロヌラで利甚可胜なリ゜ヌスをより厳密に管理するこずができたすが、システムの耇雑さが倚少増倧するこずになりたす。

小芏暡なアセンブリ蚀語ベヌスのアプリケヌションや、倧量の䜜業スペヌスを必芁ずしないアプリケヌションの堎合、内郚レゞスタを䜿甚しおすべおのアプリケヌション倉数を栌玍するこずができたす。このアプロヌチには、2぀の重芁なメリットがありたす。

  1. コンパクトで高速なコヌド。レゞスタ倉数の読取り、曞蟌み、たたは他のレゞスタ倉数ぞのコピヌは、最小1呜什サむクルで実行可胜です(レゞスタの䜍眮に䟝存したす)。MAXQ20ベヌスのマむクロコントロヌラでは、通垞はワヌストケヌスでも最倧2呜什サむクルしか必芁ずされたせん。
  2. 倉数に察する盎接挔算。䞀郚の内郚レゞスタ䜍眮は、盎接挔算が可胜です。たずえば、16の䜜業アキュムレヌタA[0]A[15]は、いずれもアクティブなアキュムレヌタAccずしお(APレゞスタを䜿甚しお)遞択するこずができたす。すなわち、これらのレゞスタの1぀に栌玍されおいる倉数に察しお挔算を実行する必芁が生じた堎合、倀をレゞスタの倖郚にコピヌしお、挔算を実行し、たた倀をレゞスタ内にコピヌする必芁はなく、そのレゞスタに察しお盎接挔算を実行するこずができたす。同様に、LC[0]およびLC[1]レゞスタに栌玍されおいる倉数は、djnz呜什を実行するこずによっお盎接ルヌプカりンタずしお䜿甚するこずができたす。
より倧芏暡なアプリケヌションや、倚数の䜜業倉数を必芁ずするアプリケヌションの堎合、倉数の䞀郚たたはすべおをSRAMベヌスのデヌタメモリに栌玍するこずにメリットがありたす。この方法によっお、最倧ではデヌタメモリのサむズによる限界たで、倧幅に倚数の倉数を䜜るこずができたす。この方法で栌玍された倉数に察するアクセスは、バむトサむズたたはワヌドサむズの倉数の読み曞きに䜿甚可胜な、MAXQ20コアの暙準デヌタポむンタの1぀を䜿甚しお行いたす(泚このアプリケヌションノヌトのコヌド䟋は、すべおDP[0]がワヌドモヌドで動䜜する蚭定になっおいるこずを前提ずしおいたす)。
   move   DP[0], #0010h      ; Location of variable in data memory
   move   Acc, @DP[0]        ; Read variable
   add    #1                 ; Increment variable value by 1
   move   @DP[0], Acc        ; Store variable back in data memory
   
倉数に察しお䞀連の長い蚈算を実行する必芁がある堎合、䞊のコヌド䟋で瀺すように、その倉数の倀を䜜業レゞスタにコピヌするず䟿利です。途䞭の挔算はすべおその䜜業レゞスタを䜿甚しお行い、蚈算が完了した時点で倀を元の倉数にコピヌしたす。

MAX-IDEでのセグメント宣蚀

アプリケヌション倉数をSRAMベヌスのデヌタメモリに栌玍するこずに決定した堎合、倉数をどこに栌玍するかの決定はどのように行うのでしょうか

䞀般的には、デバッガが䜿甚する最䞊䜍の32バむトを陀いお、すべおのデヌタメモリをアプリケヌションで利甚するこずができたす。したがっお、倉数の宣蚀は、単にデヌタメモリ䞭でその倉数甚の堎所を定矩するこずに盞圓したす。その埌は、倉数の読み曞きが行われるごずに、この堎所がコヌドによっお䜿甚されるこずになりたす。#defineマクロを䜿甚しお、倉数の䜍眮にシンボル名を結び付けるこずができたす。

#define VarA  #0020h
#define VarB  #0021h
#define VarC  #0022h

   move   DP[0], VarA        ; Point to VarA variable
   move   Acc, @DP[0]        ; Read value of variable
   move   DP[0], VarB        ; Point to VarB variable
   move   @DP[0], Acc        ; Copy VarA to VarB
   move   DP[0], VarC        ; Point to VarC variable
   move   @DP[0], #1234h     ; Set VarC = 1234h

このアプロヌチは十分に圹立ちたすが、いく぀か問題もありたす。
  • 各倉数の䜍眮を前もっお決定しおおく必芁がありたす。この䜜業には時間がかかり、特に、埌からすべおの倉数をデヌタメモリ内の別の領域に移動するこずになった堎合が問題です。
  • 誀っお同じ堎所を2぀以䞊の倉数に䜿甚しないように泚意する必芁がありたす。この誀りを犯すず、バグの远跡が困難になりたす。
  • 倉数の初期倀(開始時の倀)がある堎合は、䞊の䟋の最埌の行のように、アプリケヌションコヌドで明瀺的にロヌドする必芁がありたす。この方法で初期化する倉数が倚数存圚する堎合、この凊理によっお倧量のコヌドスペヌスが消費される可胜性がありたす。
より効率的なアプロヌチずしお、独立したコヌドセグメントずデヌタセグメントを宣蚀するMAX-IDEのメカニズムを利甚する方法がありたす。この方法では、アセンブリコヌドファむルのどの郚分をコヌドスペヌス甚に䜿い、どの郚分をデヌタスペヌス甚にするかを、アプリケヌションの䜜成者が指定するこずが可胜になりたす。
segment code

   move  DP[0], #VarA       ; Point to VarA
   move  Acc, @DP[0]        ; Get current value of VarA
   add   #1                 ; Increment it
   move  @DP[0], Acc        ; Store value back in VarA

segment data

VarA:
   dw    0394h              ; Initial value for VarA

䞊のアプロヌチの堎合、デヌタセグメント内で宣蚀した倉数のアドレスは、コヌドスペヌスのラベルに察するアドレスの付䞎に䜿甚されるのず同じ方法で、ファむルをパヌスする際にアセンブラによっお自動的に決定されたす。これらの倉数アドレスにシンボル名を付䞎するためにラベルが䜿甚され、dwおよびdbステヌトメントを䜿甚しおワヌドサむズずバむトサむズの倉数を開始時の倀で初期化するこずができたす。この堎合、このアセンブリファむルにはこれより前にsegment dataディレクティブがなかったず仮定するず、アセンブラはアドレス0000hからこのデヌタセグメントを開始したす。したがっお、VarAはワヌドアドレス0000hに栌玍されるこずになりたす。コヌドスペヌスの堎合ず同様に、orgステヌトメントを䜿甚しお、指定したアドレスの先頭に匷制的に倉数を配眮するこずも可胜です。

デヌタセグメントの初期化

前出のコヌドリストで、倉数VarAは(dwステヌトメントを䜿甚しお)初期倀が0394hになるように定矩されおいたす。しかしこの倀は、コヌド䞭ではVarAにロヌドされおいたせん。それでは、この倀はどうやっお初期化されるのでしょうかデヌタセグメントの初期化は、プロゞェクトのコンパむルず実行の際に、MAX-IDEによっお自動的に行われるずいうのがその答えです。

MaxQAsmアセンブラは、segment dataディレクティブに察しお、第2のhex出力ファむルを生成したす。通垞は、コヌドデヌタを含むプロゞェクトに察しおhexファむルが生成されたす。たずえば、example.prjずいうプロゞェクトをコンパむルした堎合、プロゞェクトファむルをアセンブルするこずによっお生成されたコヌドデヌタを含んだexample.hexずいうhexファむルが生成されたす。デヌタセグメントが定矩されおいる堎合、そのセグメントでアセンブルされたデヌタが含たれたexample_d.hexずいう远加のhexファむルが生成されるこずになりたす。

プロゞェクトの実行時、MAX-IDEはプロゞェクトのコンパむル䞭にデヌタセグメントファむル(末尟が_d.hexのもの)が生成されおいないか調べたす。デヌタセグメントファむルが存圚する堎合、MAX-IDEは暙準のJTAGロヌダを䜿甚しお、このセグメントのデヌタをデバむスのデヌタSRAMにロヌドしたす。これは、暙準のhexファむルがプログラムメモリにロヌドされた埌で行われたす。

デバむスがJTAGアダプタに接続されおいる開発サむクルでは、この方法がうたく機胜しお、MAX-IDEはアプリケヌションの実行前に毎回コヌドずセグメントデヌタをリロヌドしたす。しかし、デバむスの電源をオフ/オンした埌、単独で(デバッガを接続せずに)動䜜させた堎合、MAX-IDEは実行ごずにデヌタセグメントに適切な倀をロヌドするこずができなくなりたす。以埌は倉数に所定の倀が蚭定されなくなり、その結果アプリケヌションが誀動䜜する可胜性がありたす。もう䞀床デバむスをデバッガに接続するず、MAX-IDEは実行前のデヌタセグメントのロヌドを再開し、問題が即座に消滅しおしたうため、この皮の障害は分析が困難な堎合がありたす。

デヌタセグメントの保存ず埩元

残る問題は、どのようにすれば、アプリケヌションがデバッガに接続されおいおも(毎回MAX-IDEがコヌドずデヌタを再ロヌドする堎合も)、自由に動䜜しおいおも(起動時に特定のRAMの内容が保蚌されおいなくおも)、䞀貫しおアプリケヌションが動䜜するようにできるかずいうこずです。明らかな解決策ずしお、アプリケヌションに倉数の倀を(初期化が終わった埌で)フラッシュメモリに保存させ、リセットたたは起動ごずに倀を埩元させるずいう、2段階のプロセスが考えられたす。

第1のステップずしお、アプリケヌションがフラッシュメモリに倀を保存する必芁がありたす。この動䜜は、マスタヌ消去たたはコヌドのロヌドサむクルの埌、アプリケヌションが最初に実行される時点で行われたす。

  1. アプリケヌションはフラグ䜍眮をチェックしお、倉数がただフラッシュにコピヌされおいないこずを確認したす。このフラグは、倉数以倖の専甚の䜍眮を䜿甚するか、たたは倉数の初期倀が非れロである限り(空のRAM䜍眮ず区別するため)その倉数ず共甚するこずが可胜です。
  2. アプリケヌションは、個々の倉数の倀をデヌタRAMからフラッシュメモリにコピヌしたす。曞換え可胜なフラッシュを備えたほずんどのMAXQマむクロコントロヌラ(MAXQ2000など)では、これはUROM_flashWrite関数を䜿甚しお行われたす。
  3. アプリケヌションは、倉数が栌玍されたこずを瀺すために、フラッシュメモリにフラグを曞き蟌みたす。
第2のステップずしお、以埌の実行時には、アプリケヌションが倉数の倀をフラッシュメモリからデヌタRAM内の所定の䜍眮に埩元する必芁がありたす。
  1. アプリケヌションはフラッシュ内のフラグ䜍眮をチェックしお、倉数の倀が栌玍されおいるこずを確認したす。
  2. アプリケヌションは、UROM_copyBufferルヌチンを䜿甚しお、倉数の倀をフラッシュメモリからデヌタRAM内の適切な䜍眮にコピヌしたす。
以䞋に瀺すコヌドリストは、MAXQ2000のEVキットでこの保存/埩元方匏を䟋瀺したものです。このコヌドでは、倉数の倀をフラッシュメモリのアドレス7000h71FFhに栌玍しおいたす。
$include(maxQ2000.inc)

;; Code memory (flash) : 0000h-7FFFh  (word addr)
;; Data memory (RAM)   : 0000h-03FFh  (word addr)

org 0000h

   ljump   start             ; Skip over password area

org 0020h

start:
   move    DPC, #1Ch         ; Set all pointers to word mode
   move    DP[0], #0F000h    ; Check first variable value (flag)
   lcall   UROM_moveDP0      ; 'move GR, @DP[0]' executed by Utility ROM
   move    Acc, GR
   cmp     #1234h
   jump    NE, copyToFlash

;; This is the "free-running" code, executed on subsequent power-ups, that copies
;; values from the flash back into their proper data segment locations.

   move    DP[0], #0F000h    ; Source: Flash location 7000h
   move    BP,    #0         ; Dest:   Start of RAM
   move    Offs,  #0
   move    LC[0], #100h      ; Copy 256 words
   lcall   UROM_copyBuffer

   jump    main

;; This is the first-pass code. A bit of a trick here; because MAX-IDE enters
;; and exits the loader separately when loading the code and data segment files,
;; the application is allowed to execute briefly before the data segment file
;; has been loaded. The first four lines under copyFlash ensure that the 
;; application waits for MAX-IDE to load the data segment file before continuing.

copyToFlash:
   move    DP[0], #0h        ; Wait for flag variable to be loaded by MAX-IDE.
   move    Acc, @DP[0]       ;    Note that this will reset the application; the
   cmp     #1234h            ;    data segment is not loaded while the application
   jump    NE, copyToFlash   ;    is still running.

   move    DP[0], #0         ; Start of RAM variable area
   move    A[4],  #7000h     ; Location in flash to write to
   move    LC[0], #100h      ; Store 256 words in flash 7000h-70FFh

copyToFlash_loop:
   move    DP[0], DP[0]      ; Refresh the data pointer to read values correctly,
                             ;    because calling UROM_flashWrite changes memory
                             ;    contexts and affects the cached @DP[0] value
   move    A[0], A[4]        ; Location to write
   move    A[1], @DP[0]++    ; Value to write (taken from RAM)
   lcall   UROM_flashWrite
   move    Acc, A[4]
   add     #1
   move    A[4], Acc
   djnz    LC[0], copyToFlash_loop

main:
   move    PD0,   #0FFh      ; Set all port 0 pins to output
   move    PO0,   #000h      ; Drive all port 0 pins low (LEDs off)

   move    DPC,   #1Ch       ; Set pointers to word mode
   move    DP[0], #varA
   move    Acc,   @DP[0]
   cmp     #1234h            ; Verify that the variable is set correctly
   jump    NE, fail

pass:
   move    PO0, #55h
   sjump   $

fail:
   sjump   $

segment data

org 0000h

varA:   
   dw  1234h

org 00FFh

varB:
   dw  5678h

end

結論

MAX-IDEによっお提䟛されるコヌド/デヌタセグメント機胜は、デヌタメモリ内の倉数の䜍眮を自動的に宣蚀しお、それらの倉数を開始時の倀で初期化する方法を提䟛したす。その埌、アプリケヌションのコヌドを䜿甚しおそれらの倉数の倀をフラッシュメモリにキャッシュしお、必芁に応じお埩元するこずができたす。このアプロヌチによっお、アセンブリ蚀語ベヌスのアプリケヌションでMAX-IDEが提䟛するデヌタセグメントの自動ロヌドを利甚するずずもに、マむクロコントロヌラがJTAGデバッガに接続されおいおも接続されおいなくおも䞀貫しお動䜜させるこずが可胜になりたす。