コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

ColdFireの内部クロックと通信速度の変更

JM128を用いてUART通信を行うときに、通信速度(ボーレート)を設定しなければなりません。このボーレートはJM128のバスクロックによっても変わるので、先ず、バスクロックを決める必要があります。バスクロックは内部クロックの半分になっているので、この内部クロックを設定しなければなりません。

今回、シリアル通信のボーレートとして9600bpsと115200bpsを切り替えて使いたかったので、内部クロックの設定を変更しました。忘れないようにブログに書いておこうと思います。

ボーレートと内部クロック

ボーレートとして9600bpsと115200bpsを使うということですが、内部クロックを変更しても、ベースクロックと乗除できる値が決まっているので、きっちりこのボーレートを出せるわけではありません。そこで、クロックを作るレジスタの値を書き換えながら、なるべくボーレートと近い値になるように調整していきます。慣れている人は悩まずにできてしまうと思うのですが、私は初めてのことだったので、レジスタの調整にCodeWarriorProcessor Expert機能を利用しました。
Processor Expertはレジスタの調整だけに使って、自動生成したレジスタ設定プログラムを自作のプログラムにコピーして流用する感じです。
以下に説明していきます。

CWの新規プロジェクトを作成

 CWの新規プロジェクトを作成します。Processor Expertを用いてパラメータを調整する目的に使うプロジェクトです。「Create New Project」→「MCF51JM128」→「P&E Multilink/Cyclone Pro」を選び「次へ」を押します。

プロジェクト名を入力して「次へ」を押します。今回は"TESTPE"としました。

ここは「次へ」のみ。

ここで、「Processor Expert」を選びます。そして「次へ」

このまま「完了」を押します。

これで、Processor Expertが起動します。Processor Expertが起動しない場合は、CWのバージョンが古くてJM128のデータが無い恐れがあります。私もこれで悩みました。バージョンを6.2以降にする必要がありそうです。現在、私はCW v6.3を使っています。

Processor Expert起動

Processor Expertを起動すると、CPUを選ぶモードになるので、DEMOJMに搭載されているMCF51JM128VLH64-pinsLQFPを選びます。記号のLHの意味は、たぶん、"L"はLQFPの"L"で"H"は64ピンを示すものだと勝手に思っています。

「OK」を押すとCPU設定画面がでて来ます。

コンポーネントの追加

UARTのボーレート設定の調整を行いたいので、componentsにシリアル通信のコンポーネントを追加する必要があります。メニュから「add components」を選びます。

Components Libraryが出てくるので、「CPU Internal Peripherals」の「Communication」の「AsynchroSerial」を選び、「Add&Clode」を押します。

そうすると、コンポーネントが追加されますが、セッティングエラーになります。これはボーレートが設定されていないからです。

Processor Expertを使った内部クロックの調整


ボーレートとして、Baud Rateに9600と入れて改行すると、エラー表示が消えます。

そこで、次に、ボーレートを115200とするとエラーがでます。これはCPUのバスクロックが低すぎるからです。

CPUのバスクロックを見ると4.194304MHzになっています。

それではバスクロックを変更してみます。ここのところに、適当に7.5とか入れます。そうすると自動的にバスクロックが選ばれて、7.471104MHzとなりました。Processor Expertの便利なところは、この調整を自動計算してくれるところです。


AS1のコンポーネントのエラーも消えています。AS1コンポーネントの方を見てみると、Baud Rateのところのエラーが消え、右にhigh: 116736baudと表示されています。これが今設定した内部クロックを用いた実際の通信速度となります。

ここで、Baud Rateのところの[...]をクリックします。そうするとタイミングの評価画面が出てきます。

画面のError欄に1.333%と表示されています。これは実際のボーレートより1.333%ずれているという意味です。Valueのところの数値は自分で入れることができるので、9600と入れてみましょう。Errorが0.735%になりました。ボーレートが低いほど、誤差が少ないことになります。

それでは、このErrorを小さくするにはどうすればいいかと言うと、バスクロックを調整すればいいわけです。ちなみに、画面右の「from」と「till」はこの内部クロックで設定できるボーレートの範囲です。
 もう少しエラーが小さい条件を探すために、ボーレートを115200にし、Error allowedを1.5%から1.3%に厳しくします。すると、下にエラーが表示されました。そのまま「OK」で閉じてバスクロックを変えて行きます。

 現在は7.114704となっており、エラーが出ています。

そこで、今度はバスクロックに17と入れてみます。

すると、自動計算され、16.777216となり、エラーが消えました。

Timing画面を出してみると、エラーが1.136%になっていました。

ちなみに、9600にしてエラー量を調べてみると、0.208%となっています。

このバスクロックを用いると、9600bpsも115200bpsも精度良くレートが出せることがわかりました。
まあ、バスクロックの速度は必要に応じて変えればいいので、この速度で無いといけないというものではないです。

Processor Expertによるソース自動生成

それでは、この条件でソースを自動生成します。「Processeor Exoertメニュ」の「Generate Code」を選びます。これでソースが自動生成します。既に生成したものがある場合は上書きしても良いか聞いてくるので、上書きするならOKしてください。OKしても、自動生成される関数以外は消えないようです。

Filesタグを見るとコードが自動生成されます。
内部クロックレジスタの設定は、Cpu.cのvoid __initialize_hardware(void)内で行われていました。

場所は、/* System clock initialization */以下です。

  /*  System clock initialization */
  /* MCGC2: BDIV=0,RANGE=0,HGO=0,LP=0,EREFS=0,ERCLKEN=0,EREFSTEN=0 */
  setReg8(MCGC2, 0x00);                /* Set MCGC2 register */ 
  /* MCGC1: CLKS=0,RDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */
  setReg8(MCGC1, 0x06);                /* Set MCGC1 register */ 
  /* MCGC3: LOLIE=0,PLLS=0,CME=0,DIV32=0,VDIV=1 */
  setReg8(MCGC3, 0x01);                /* Set MCGC3 register */ 
  /* MCGC4: ??=0,??=0,DMX32=0,??=0,??=0,??=0,DRST_DRS=1 */
  setReg8(MCGC4, 0x01);                /* Set MCGC4 register */ 
  while(!MCGSC_LOCK) {                 /* Wait until FLL is locked */

この部分がバスクロックを16.777216MHzに設定しているところです。
ここまでが、Processor Expertを使うところです。System clock initializationを自分で考えるのが難しかったので、Processor Expertにやってもらいました。AS1.cにUARTの初期化ソースも自動生成されています。このソースを使いたい場合は、これを使ってプログラムを組んでいってもOKです。

 今回、私は、自作のプログラムのCPU初期化部分init_clock()に上記設定をコピーして使いました。

//**********************************************************
// 内部クロックの設定
// BUS_CLOCK=16.777216MHzに設定している
//**********************************************************
static void init_clock(void)
{
  //  System clock initialization
  // MCGC2: BDIV=0,RANGE=0,HGO=0,LP=0,EREFS=0,ERCLKEN=0,EREFSTEN=0
  MCGC2 = 0x00;                // Set MCGC2 register
  // Reset時と違うところ、BDIV=0  
  // Divides selected clock by 1
   
  // MCGC1: CLKS=0,RDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0
  MCGC1 = 0x06;                // Set MCGC1 register
  // Reset時と違うところ、IRCLKEN=1  
  // Internal Reference Clock Enable .
  // Enables the internal reference clock for use as MCGIRCLK. 1=MCGIRCLK active
  
  // MCGC3: LOLIE=0,PLLS=0,CME=0,DIV32=0,VDIV=1
  MCGC3 = 0x01;                // Set MCGC3 register
  //  Reset時と同じ
  // VDIV=1 Encoding 1 . Multiply by 4.
  
  // MCGC4: ??=0,??=0,DMX32=0,??=0,??=0,??=0,DRST_DRS=1
  MCGC4 =  0x01;                // Set MCGC4 register
  // Reset時と違うところ、DRST_DRS=1 
  // DMX32=0:0 DCO has default range of 25%.
  // DRST_DRS=1:01Mid range.
  // ---------------------------
  // Reference range:31.25 - 39.0625 kHz(32.768kHz)
  // FLL factor:1024
  // DCO range:32 - 40 MHz

  while(!MCGSC_LOCK) {}                 // Wait until FLL is locked
}

これで、バスクロックが16777216Hzになるはずです。

バスクロックの具体的な計算式

Processor Expertが自動生成したプログラムからどうやって、バスクロック16777216Hzが出てきたか自分で計算してみました。
先ず、基本クロック32768Hzがあります。FLL=1024設定なので、これを1024倍します。32768*1024=33554432Hz。そして、BDIV=0なので、1で割ります。33554432/1=33554432Hz。さらに、バスクロックは内部クロックの半分なので、33554432/2=16777216Hzとなります。

ボーレートの設定

ボーレートはバスクロックとSCIxBDレジスタの値で決まります。計算式は下記です。

バスクロックを1/16して、ボーレート生成レジスタの下位13ビットの値で割ったものがボーレートとなります。ボーレート生成レジスタSCIxBDは下記のような16bitです。

つまり、115200bpsを作ろうとすると、16777216/16=1048576。これをボーレートで割った値がSCIxBDレジスタの下位13ビットに設定する値となります。
1048576/115200=9.1022。すなわち、9をセットすればいいことになります。
この要領でボーレートを設定するプログラムを作りました。実際はBUS_CLKは別のところで定義しています。

#define	BUS_CLK       16777216ul	/* bus frequency in Hz */

//**********************************************************
// ボーレートの設定
// num: 1=UART1, 2=UART2
//**********************************************************
hcc_u32 uart_set_bps(hcc_u8 num, hcc_u32 bps)
{
  /* Calculate baud settings */
  hcc_u16 d = (hcc_u16)((BUS_CLK/16)/bps);
  if( d>8192 ){
    d=8192;  
  }
  if( d <1 ){
    d=1;
  }
  if( num==1 ){
    SCI1BD = d;
    return(uart_get_bps_1());
  }else{
    SCI2BD = d;
    return(uart_get_bps_2());
  }
}

下位13ビットなので、if文で上限下限を制限しています。

これでJM128の内部クロックと通信速度の設定ができました。Processor Expertを使うと外部クロックを使った場合でも同様な方法で楽に設定ができます。便利ですね。

本当にやりたいことリスト

(ブログの終わりにやりたいことを書いておきたいと思います)

  • 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
  • Androidプログラム
  • Web系のプログラム