1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AllwinnerA64(SOPINE)でGPIOとUARTをBaremetalで使ってみた

Posted at

◆ はじめに

SOPINE(sun50i)でレジスタを直接操作してGPIOとUARTを使う方法について記載します。
本稿ではAllwinnerA64のUART0を設定する方法になりますが、他のUARTも同じだと思います(多分)。
GPIOもPortBの#2(PB2)を設定する方法になりますが、(おそらく)他も一緒だと思います。

◆ PIN SELECT

最初に、GPIOのPB2とUART0のTXとRXを使うようにPINの設定を行います。
GPIOのPB2は、そのままの意味ですがPB2(bank:1, pin:2)を使います。
UART0のTXはPB8(bank:1, pin:8)、UART0のRXはPB9(bank:1, pin:9)を使います。
それぞれの設定は該当するレジスタの値をセットすればOKです。
各ピンにどの機能が割り当てられているかは、AllwinnerA64のUserManualのP.376〜を見てください。

◆ Port Configure Register

PortControllerのBaseAddressは0x01c20800になります。
各PINでどの機能を使うかはPort n Configure Register 0-3で設定します。
詳細は下記表になります。

レジスタ offset 対応GPIO
PB_CFG0 +0x24 PB0〜PB7
PB_CFG1 +0x28 PB8〜PB9

今回はPortBに限定してますが、PortC、PortD、PortDの場合はOffisetに+0x24、+0x48、+0x6Cを加算してください。
つまり一般化すると、
Pnmのピン(nはB,C,D,・・・,H、 mは0〜24)のConfigure Registerのアドレスは、

BaseAddress(0x01c20800) + 0x24 * p + 0x4 * q
(pは、B=1, C=2, D=3・・・、 q=0:0≦m≦7、1:8≦m≦15、2:16≦m≦23、3:24≦m≦31)

細かいのはUserManual参照でお願いします。

また、各ピンの機能はLSBから4bitごとに分けて設定します。
PB_CFG0の場合、[3:0]がPB0、[7:4]がPB1となります。
そこで、PB2をGPIOのOutput、PB8をUART0_TX、PB9をUART0_RXに設定する場合、下記のようにします。

レジスタ Offset bit 設定値
PB_CFG0 +0x24 [11:8] 0b0001(0x1)
PB_CFG1 +0x28 [3:0] 0b0100(0x4)
PB_CFG0 +0x28 [7:4] 0b0100(0x4)

◆ UART

UARTの設定では、順番に以下を設定します。

  1. クロックの設定
  2. ボーレートの設定
  3. 一度の送信ビット数、パリティ、ストップビットの設定

◆ クロックの設定

BUS_CLK_GATING_REG3(0x01c2006c)の[16]がUART0のクロックゲーティング用bitですので、
このbitを1にセットすればOKです。
なお、UserManualによるとこのクロックは24MHzのようです。
また、BUS_SOFT_RST_REG4(0x01c202d8)の[16]に1をセットします。
これでソフトウェアリセットがかかります。

◆ ボーレートの設定

今回はFIFOを使わない方法を記載します。
まずボーレートをDivisor Latch Low Registor(UART0_DLL)とDivisor Latch High Register(UART0_DLH)で指定することを、
UART0 Line Control Register(UART0_LCR:0x01c28000)で指定します。
UART0_LCR[7]に1をセットすればOKです。
このあと、UART0_DLLとUART0_DLHを使いDivisorを設定しますが、この設定値は以下のように算出します。
ボーレート = クロック周波数 / (16 * Divisor)
AllwinnerのUART0のボーレートは115,200にすること通例のようです。
また、クロック周波数は前述のとおり24MHzです。
そうなるとDivisorは下記の通りになります

Divisor = 24 * 1000 * 1000 / 16 / 115200 = 0xD
(余りが出るけどいいのだろうか・・・。サンプルでもコレだし動くから目をつぶります)

そこで、UART0_DDHに0x0、UART_DDLに0xDを設定します。

◆ 一度の送信ビット数、パリティ、ストップビットの設定

ここでは、一度の送信ビット数、パリティ、ストップビットの設定を行います。
それぞれは下記の通りにUART0_LCR(0x01c28000)を設定します。

設定項目 bit 設定値
パリティ [3] 1:enable
0:disable
ストップビット [2] 1:2bit
0:1bit
送信bit数 [1:0] 11:8bit
10:7bit
01:6bit
00:5bit

今回は、一度の送信で8bit、パリティビットなし、ストップビットは1bitで設定します。
したがって、0x00000003をUART0_LCR(0x01c28000)に書き込みます。

◆ 使ってみる

それでは、GPIOやUARTを使ってみます。
まずGPIOにHigh/Lowを出力させてみます。
PB2の場合、PB Data Registerを使います。
具体的には、PB_DATA_REG(0x01c20834)[2]がそれに該当しますので、
ここに1をセットすればHigh、0をセットすればLowになります。

次にUART0を使います。
FIFOを使ってないので、UART Transmit Holding Register(送信)、UART Receive Buffer Register(受信)を使います。
両方ともアドレスは0x01c28000となります。
ここの[7:0]に書き込み/読み込みした値がそれぞれ、UART0の送信/受信となります。
送信時は、UART Line Status Register(0x01c28014)[6]が0の時はデータ送信中となるので、
1になるまでループなりで待つ必要があります。
受信時は、UART Line Status Register(0x01c28014)[0]が0の時はデータ受信中になるので、
1になるまでループなりで待つ必要があります。

◆ おわりに

以上が、GPIO、UARTの設定と使う方法になります。
これでBareMetalプログラミングをする際にデバッグメッセージを出力させたり、
簡単なLED点灯による動作確認などができるかと思います。
次は今のコードをRust化させるところですが、どうなるやら。

あと、sunxi-felのhex[dump]が32bitのLSBの8bitしか表示されないことにハマりました。
自分の環境が悪いのかどうかは調査してないので不明ですが、結果として動いたのでよしとします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?