目次

I/O操作

 利用するForthインタプリタは、ARMの中のCPUコアである
 Cortex-M0を利用したLPC1114にインプリメントされてます。

 I/O操作はSFR(Special Function Register)への値設定か
 値取得で実現できます。

 LPC1114のピンアサインは、以下。



 傍に赤の線をつけたピンをGPIO(General Purpose Input and
  Output)として利用可能。

 ワンチップマイコンの常で、ピンに複数の機能を
 割り当てられるので、場面に応じた設定が必要。

 データシートから、単純なI/Oとして利用するため
 必要なパラメータ設定に関係する部位を探します。

 メモリマップを眺めると、以下。




 CPUチップをひとつのシステムとみれば、configurationで
 動作仕様を指定できるはずと、レジスタを探していきます。

 アドレス0x40044000に、IOCONFIGというラベルがありました。

 NXPのARMプロセッサのメモリマップでは、アドレス32ビットの
 上位16ビットで大まかな機能分野を指定し、下位16ビットで
 より細かい内容に絞り込むよう。

 IOCONFIGで、GPIOとして利用できるようにするとともに
 内部抵抗を活用したプルアップ、プルダウンの指定まで
 も可能となります。

 PIO1_8をGPIOで利用してみます。
 デフォルトで、GPIOの設定になっているのですが
 細かい設定をしたいときには、次のようにコードを入力。

\ define LABEL
$40044014 constant IOCON_PIO1_8

$C0 IOCON_PIO1_8 !
\ Set P1.8 as GPIO without Pullup/Pulldown.
\ $C0 are reserved bits that must be set.

 IOCONFIGレジスタのビット割り当てに関しては、後で説明。

 Forthのコードでは、以下のことがわかります。

 日本語語順でワードを並べると、コードになります。

 「$40044014を、定数でラベルIOCON_PIO1_8に割当て」
 と言ってみれば、理解できるはず。

 「$C0をIOCON_PIO1_8に転送」という日本語の
 表現が、そのままForthのコードと等価と理解
 できます。

 ピンアサインで確認すると、以下。



 PIO1_8が、GPIOとして利用できるようになったなら
 LEDを接続して、点灯、消灯させてみることに。




 方向を設定するには、Data Direction Registerを
 論理値の出力は、Data Registerを利用します。

 Data Direction Registerは、メモリマップでみると
 $50010000から始まるどこかにあるレジスタのはず。



 Data Direction Registerのアドレスは、$50018000。

 このレジスタは、32ビット中の下位16ビットでピンの
 入出力を設定し、論理値の'1'を与えると出力に。

 PIO1_8では、PORT1という範囲で$50018000にしてある
 ので、下位16ビットの8ビット目を'1'にすれば出力
 になります。

 注目しているのは、8ビット目だけとすると、$100
 (10進数で256)を指定すればよいはず。

 コードでは、以下。

\ define LABEL
$50018000 constant GPIO1_DDR

\ Set P1.8 as Output
$100 GPIO1_DDR !

 論理値の出力には、指定レジスタに論理値を書き込む
 だけですが、LPCシリーズでは、他のピンに影響を与え
 ないで、該当ピンだけを操作可能。

 2進数で該当ビットだけを1にし、その2進数を4倍
 した値が、そのピンのData Registerのアドレスになる。

 PIO1_8のデータレジスタのアドレスは、次の計算で
 求められます。(ビット番号は、0から始めます。)

entry address $50010000
offset        0001_0000_0000 -> 0100_0000_0000 = $400
PIO1_8 Data Register Address => $50010400

 レジスタは32ビットなので、4バイト分の
 オフセットを加え、バイトアドレスに換算
 と考えればよいです。

 論理値を出力するコードは、以下。

\ define LABEL
$50010400 constant PIO1_8D

\ Set 1
$100 PIO1_8D !
\ Set 0
$000 PIO1_8D !

 LEDをブリンクする自前のワード定義は、次の
 ようにします。

\ define LABEL
$50018000 constant GPIO1_DDR

\ Set P1.8 as Output
$100 GPIO1_DDR !

\ assing target pin number register
$50010400 constant PIO1_8D

\ delay
: xdelay
  1000000 0 do loop
;

\ primitive
: blink
  $100 PIO1_8D !
  xdelay
  $000 PIO1_8D !
  xdelay
;

\ 10 times blink
: blinky
  10 0 do blink loop
;

 LPC1114は、ポート0、1しか持ってないので
 Data Direction Registerは、次の定義でよい
 でしょう。

$50008000 constant GPIO0_DDR
$50018000 constant GPIO1_DDR

 Data Registerは、複数ピンを扱うのか単独ピンを
 扱うのかで、ラベル定義がかわるので、その都度
 考えなければなりません。

 以下のリストで限定するとわかりやすくなります。

  • GPIO
  • Match Compare Output
  • Input Capture
  • Analog Digital Converter  GPIOを除き、使えるピンは固定されているので  図で分けておき、一目でわかるようにすれば  よいでしょう。  ADC  Match Compare Output  Input Capture  利用しているForthインタプリタで、ピンの  configrationを知りたければ、対応レジスタ  の内容を見ればよいはず。  ラベルを定義し、そのラベルをアドレスと見なして  内容を16進数で表示すれば、情報を得られるはず。  コードは、以下。 \ define LABEL $40044000 constant SFR_IOCON \ show address with hexadecimal SFR_IOCON hex. \ get context from target address and show it with hexadecimal SFR_IOCON 2@ hex. SFR_IOCON @ hex.  TeraTermを使うときは、次のようにクリップボードにコピーした  内容を貼り付ける操作で、タイプミスを防げます。  端末操作で、SFRの該当レジスタの内容を表示すると、以下。  ワード「hex.」を利用すると、16進数表示になるので  SFRのレジスタアドレスをスタックに入れて、内容を  取得後に、わかりやすいフォーマットで表示できます。  システムのconfigrationも確認してみます。  SFRのアドレスがあるので、ラベルをアサインして内容を  表示させます。 \ define LABEL $40048000 constant SFR_SYSTEM \ get context SFR_SYSTEM @ hex.  コードを貼付け後、表示すると以下。  表示内容からわかることは、内蔵モジュールに対して  電源、供給するクロックをどうするかの指定です。  次の図を参照すると、よくわかります。  Forthインタプリタ関係のファイルをダウンロードし  展開したときに、次のサンプルコードを見つけました。 : 48MHz ( -- ) 0 $40048070 ! \ MAINCLKSEL: Switch to IRC "Internal RC oscillator" clock 0 $40048074 ! \ MAINCLKUEN: Toggle this bit from zero 1 $40048074 ! \ to one to update clock selection 1 7 lshift $40048238 bis! \ PDRUNCFG: Set power-down bit for PLL \ Simply keep reset values here \ 0 $40048040 ! \ SYSPLLCLKSEL: Set IRC clock \ 0 $40048044 ! \ SYSPLLCLKUEN: Toggle this bit from zero \ 1 $40048044 ! \ to one to update clock selection \ FCLKOUT = M * FCLKIN = FCCO / (2*P) \ * Specify the input clock frequency FCLKIN. \ * Calculate M to obtain the desired output frequency FCLKOUT with M = FCLKOUT / FCLKIN. \ * Find a value so that FCCO = 2 * P * FCLKOUT. \ * FCCO needs to be between 156 and 320 MHz. \ * Ensure that FCLKOUT < 100 MHz. \ Here: FCLKIN = 12 MHz \ M = 48 MHz / 12 MHz = 4 \ FCCO = 2 * 2 * 48 MHz = 192 MHz 3 \ Feedback divider value, ranging from 0 (M=1) to 31 (M=32) 1 5 lshift or \ Post divider ratio: 0: P=1 1: P=2 3: P=4 4: P=8 $40048008 ! \ SYSPLLCTRL: Configure PLL dividers 1 7 lshift $40048238 bic! \ PDRUNCFG: Clear power-down bit for PLL begin $4004800C @ until \ SYSPLLSTAT: Wait for lock of PLL $4003C010 @ 3 bic 2 or $4003C010 ! \ FLASHCFG: Set wait states for frequencies up to 50 MHz 4 $40048098 ! \ UARTCLKDIV: Divide 48 MHz / 4 = 12 MHz to get desired baud rate of 115200 baud. 3 $40048070 ! \ MAINCLKSEL: Switch to PLL output 0 $40048074 ! \ MAINCLKUEN: Toggle this bit from zero 1 $40048074 ! \ to one to update clock selection 48000 flash-khz ! \ Update current clock frequency, it is needed to write flash. ;  一度、上のコードを動かすと、48MHzにできるので  PLL関係の操作その他は、このスクリプトに任せてしまう  ことにしておきます。  48MHzにシステムクロックを変更後、次のコードで  点滅が高速になったことを確認しました。 $50010800 constant PIO1_9D : blinkz 10 0 do $100 PIO1_8D ! $000 PIO1_9D ! xdelay $000 PIO1_8D ! $200 PIO1_9D ! xdelay loop $000 $50010C00 ! ;  2ビットを一度に処理するのなら、$50013FFCを使う  方法もありだとして、次のワードでも確認しました。 $50013FFC constant PIO1 : blinku 10 0 do $100 PIO1 ! xdelay $200 PIO1 ! xdelay loop 0 PIO1 ! ;  GPIOのポート1で全体を使うなら、$50013FFCとする方が  複数ビットの操作は簡単になります。  デフォルトでは、ポート0、1ともにGPIOとなっているので  次の操作で、各ピンの入出力とリード、ライトの操作ができ  ます。 \ SFR $50008000 constant GPIO0_DDR $50018000 constant GPIO1_DDR $50003FFC constant GPIO0_DR $50013FFC constant GPIO1_DR \ set data direction $300 GPIO0_DDR ! $0FF GPIO1_DDR ! \ data read GPIO0_DR @ . \ data write $A5 GPIO1_DR !  利用LEDは、次の基板上にあるもの。  インバータを利用して、正論理でLEDを点灯します。  回路は、以下。  この基板を使って、デジタルI/Oで使える  ビットを調べると、次のようになりました。 P0.2 P0.3 P0.6 P0.7 P0.8 P0.9 P1.4 P1.5 P1.8 P1.9  P0.4、P0.5はIICバスで使えるので、システムとしては  デフォルトでI/Oにアサインしないのでしょう。  P1.0からP1.3は、A/Dコンバータの入力とタイマーカウンタ  のインプットキャプチャやコンペアマッチ出力での利用を  想定して、デジタルI/Oとして使えないようにしていると  考えられます。  パワーオンリセット後、指定しなければ、どのモードにも  ならないように設定されています。  GPIO、A/D変換器、タイマーカウンタのモードで使うかを  指定してから、利用という流れをとります。  P1.6、P1.7はシリアルインタフェースで使っています。  シリアルインタフェースがないと、端末接続でForthの  インタプリタと情報交換できないので、当然の仕様。  Forthインタプリタ設計者は、P0.10、P0.11はタイマーカウンタ  での利用を想定しているのかも、知れません。  GPIO、A/D変換、その他のモードで使うときは、利用前  指定と、事前準備を挟むと覚えればよいでしょう。

  • 目次

    inserted by FC2 system