SSブログ

ネットワーク電飾 (3) [ColdFire V2]このエントリーを含むはてなブックマーク#

2068980

今回は、さらにDMAタイマを組み合わせて、自動的にLEDを点灯させます。

DTIM0の設定

DTIM0には、0.2秒ごとにDMA1に転送要求を発行させます。 設定項目は、SilentCが使っていないモジュールを探せ(5)の設定から少しだけ変更されています。

DTIM0のレジスタ設定
レジスタ設定値備考
DTMR0 [PS]0x3B (60-1) プリスケーラの分周比を60に設定します。 カウンタを動作させるクロック周期は、1µ秒になります。
DTMR0 [CE]00 (disable) 入力キャプチャは使いません。
DTMR0 [OM]1 (toggle) 今回は、DTOUT0端子は使わないのですが、トグルに設定しておきます。 何かあったら、デバッグに使えるでしょう。
DTMR0 [ORRI]1 (enable) DMA転送要求を発行します。 このビットは、DMA要求と割り込み要求の双方の許可ビットになっています。 どちらの要求を発行するかは、DTXMR0[DMAEN]ビットで設定します。
DTMR0 [FRR]1 (enable) リファレンス・レジスタの周期でイベントを発生させます。
DTMR0 [CLK]01 (BUSCLK×1) プリスケーラをバスクロック (60MHz) で駆動します。
DTMR0 [RST]0 (reset) → 1 (run) リセットした状態でタイマを設定し、最後にこのビットをセットしてタイマを起動します。
DTXMR0 [DMAEN]1 (DMA) イベントが発生したら、DMA転送要求を発行します。
DMXMR0 [HALTED]0 (run when HALT) STOP状態の時にタイマを停止するかどうかを決定します。 このアプリケーションでは、STOPは使いませんが、STOP状態でも止まらないように設定しておきます。
DMXMR0 [MODE16]0 (32-bit mode) タイマカウンタを16-bitレジスタとして使いたい場合にセットします。 このアプリケーションでは、32-bitカウンタとして使います。
DTRR0199999 (200000-1) プリスケーラ出力の200000周期ごとにイベントを発生させます。 プリスケーラ出力は、1µ秒としたので、0.2秒ごとにDMA転送が発生します。

設定方針が決まったので、固定点灯パターンを使ったプログラムを作成します。

main() {
  char *pubpar  = 0x40100072;
  char *portub  = 0x40100012;
  char *ddrub   = 0x4010002a;
  long *dmareqc = 0x40000014;
  long *sar1    = 0x40000110;
  long *dar1    = 0x40000114;
  long *bcr1    = 0x40000118;
  long *dcr1    = 0x4000011c;
  char *gpacr0  = 0x40000030;
  int  *dtmr0   = 0x40000400;
  char *dtxmr0  = 0x40000402;
  long *dtrr0   = 0x40000404;
  long *dtcn0   = 0x4000040c;
  
  char *alloc;
  char *pat;

  alloc = MemoryAlloc(32);
  pat = (alloc+15)&0xFFFFFFF0;
  pat[0]=1;pat[1]=3;pat[2]=11;pat[3]=15;
  pat[4]=14;pat[5]=12;pat[6]=4;pat[7]=0;
  pat[8]=pat[10]=pat[12]=15;
  pat[9]=pat[11]=pat[13]=pat[14]=pat[15]=0;

  *gpacr0  = 0x04; // ACCESS_CTRL=0100
  *pubpar  = 0x00; // PUBPAR[3:0]=0000
  *portub  = 0x00; // PORTUB[3:0]=0000
  *ddrub   = 0x0F; // DDRUB[3:0]=1111
  *bcr1    = 0x01000000; // clear DONE
  *sar1    = pat;    // source
  *dar1    = portub; // destination
  *bcr1    = 0x00FFFFF0; // byte count
  *dcr1    = 0x62521080; // See table
  *dmareqc = 0x00000040; // DMAC1=DTIM0
  *dtmr0   = 0x0000; // software reset
  *dtmr0   = 0x3B3A; // See table
  *dtxmr0  = 0x80;   // enable DMA
  *dtrr0   = 199999; // period 200000
  *dtmr0  |= 0x0001; // RST=1

  #stop 0
  for(;;){
    if (Getc(0)=='q')break;
    SystemSleep();
  }
  *dtmr0 &= 0xFFFE; // RST=0
  *bcr1   = 0x00000000; // reset byte count
  MemoryFree(alloc);
}

プログラムを実行させると、固定パターンでの点滅が始まります。 プログラムを見るとわかるように、レジスタ設定が終わったら、CPUは休眠状態に入っていて、あとはDMAタイマとDMAが自動的にLEDを点滅させています。

ネットワーク電飾

それでは、最後に点灯パターンをネットワークから送り込めるようにUDP受信機能を取り入れます。 今までのプログラムの組み合わせなので、簡単ですね。 PC側のプログラムは、ネットワーク電飾 (1)で作成したJavaのプログラムがそのまま使えます。

main() {
  char *pubpar  = 0x40100072;
  char *portub  = 0x40100012;
  char *ddrub   = 0x4010002a;
  long *dmareqc = 0x40000014;
  long *sar1    = 0x40000110;
  long *dar1    = 0x40000114;
  long *bcr1    = 0x40000118;
  long *dcr1    = 0x4000011c;
  char *gpacr0  = 0x40000030;
  int  *dtmr0   = 0x40000400;
  char *dtxmr0  = 0x40000402;
  long *dtrr0   = 0x40000404;
  long *dtcn0   = 0x4000040c;
  
  char *alloc;
  char *pat;
  char socket;
  int  errcode;
  char *buf;

  alloc = MemoryAlloc(32);
  pat = (alloc+15)&0xFFFFFFF0;

  *gpacr0  = 0x04; // ACCESS_CTRL=0100
  *pubpar  = 0x00; // PUBPAR[3:0]=0000
  *portub  = 0x00; // PORTUB[3:0]=0000
  *ddrub   = 0x0F; // DDRUB[3:0]=1111
  *bcr1    = 0x01000000; // clear DONE
  *sar1    = pat;    // source
  *dar1    = portub; // destination
  *bcr1    = 0x00FFFFF0; // byte count
  *dcr1    = 0x62521080; // See table
  *dmareqc = 0x00000040; // DMAC1=DTIM0
  *dtmr0   = 0x0000; // software reset
  *dtmr0   = 0x3B3A; // See table
  *dtxmr0  = 0x80;   // enable DMA
  *dtrr0   = 199999; // period 200000
  *dtmr0  |= 0x0001; // RST=1

  socket = CreateSocket(0); // UDP socket
  Bind(socket, 30049, 1); // Bind to port
  MemClear(pat,16);

  #stop 0
  for(;;){
    if (Getc(0)=='q')break;
    errcode = RecvFrom(socket, 100); // 1sec
    if (errcode >= 16){
      buf=GetReceiveBuffer(socket,1);
      BufCopy(pat,buf,16);
      MemoryFree(buf);
    }
    SystemSleep();
  }
  CloseSocket(socket);
  *dtmr0 &= 0xFFFE; // RST=0
  *bcr1   = 0x00000000; // reset byte count
  MemoryFree(alloc);
}

メインループでは、UDPの受信作業しか行っていません。

また、パケット待ちタイムアウト時間は、1秒と長めにしました。 このタイムアウト時間は、プログラムを停止させるための'q'キーの検出時間になるので、1秒にしましたが、キー入力で停止させる必要が無いのであれば、もっともっと長いタイムアウト時間にしてもかまいません。 プログラムがパケット待ちをしている間、DMAタイマとDMAが、せっせとLEDを点滅させてくれます。

参考文献

Interface (インターフェース) 2008年 09月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。