目次: ARM
以前(2018年12月)にROCKPro64を購入したのですが、シリアルが文字化けして使い物にならず、ずっとお蔵入りになっていました。
最初はケーブルの接続や、接地がおかしいのかと思いましたが、GND側はきっちり0Vでした。どうも単純な原因ではなさそうだったので、オシロスコープで信号を見ることにしました。テストパターンとして0と1が交互に出現し、一番転送が難しいパターンと思われる0x55 'U' の文字を出力しています。
正常に出力できているROCK64と比較すると、ROCK64は出力が0 → 1 → 0と変化する際に0V → 3V → 0Vのように電圧が振れますが、ROCKPro64は、0V → 2.48V → 0Vのように立ち上がり側が遅く、中途半端な電圧になっています。
下記の画像の青色の線がROCK64のシリアル出力で、オレンジ色の線がROCKPro64のシリアル出力です。どちらも1秒ごとに 'U' を出力して、最初の立ち下がり(Start Bit、必ず0)にトリガを掛けています。
ROCK64は綺麗な波形ですが、ROCKPro64は0V → 3Vへの立ち上がりが間に合っていないことが分かるかと思います。
文字化けの原因ですけども、シリアルの転送速度(1.5Mbps、1ビット666ns)に対し、0 → 1の立ち上がりが遅すぎる(650nsくらい)からでしょう。出力側は1を送出しているつもりでも、信号が立ち上がるのが遅いため、受信側は0だと解釈してしまう場合があります。
転送速度を落とせば改善するかもしれません。しかしRockchipのU-Bootはなぜか1.5Mbps固定で転送してくる困った奴で、下手にシリアルの転送速度を変えるとU-Bootが操作できなくなり、非常に使いづらいのです。イマイチですね……。
ROCKPro64にはRockchipのRK3399と言うSoCが搭載されていて、RK3399は一部のピンのDrive Strength、つまりピンに流せる電流量を調整できます。決して特殊な機能ではなく、大抵のSoCが持つ普通の機能です。
ROCKPro64がコネクタに引き出しているシリアルはUART2です。UART2はGPIO4_C4(TX)とGPIO4_C3(RX)というピンに割り当てられています。幸運なことにRK3399ではこれらのピンのDrive Strengthが変更できるので、設定値を振って(※)オシロで波形を見てみました。
下記の画像が測定結果です。1枚目はデフォルトかつ最小の3mA、2枚目は最大の12mA設定です。出力している文字は前回同様0x55 'U' で、トリガも前回同様Start Bitの立ち下がりに仕掛けています。オシロのRising, Falling Time解析をONにしたので、立ち上がり、立ち下がりに掛かった時間も一緒に表示されています。

Drive Strength = 3mAのときのシリアル出力波形

Drive Strength = 12mAのときのシリアル出力波形
字が若干見づらいので、一応書いておくと、立ち上がりの時間は650ns → 300nsくらいに改善しました。良い感じですね。
ちなみにスクリーンショットの色が変で、文字が読みづらいのは仕様です。Tektronixさん、スクリーンショット背景の白黒反転処理、バグってますよ……??
それはさておきDrive Strengthの変更で、ROCKPro64のシリアル文字化けはかなり改善されました。しかし完全ではなく大量に出力した際に若干文字化けします。
さらなる改善のためには、シリアルの転送速度を落とすくらいしか思いつきません。が、U-Bootの書き換えをするのが面倒くさいので、また今度にします……。
(※)レジスタ名はGRF_GPIO4C_Eで、アドレスは0xff77e138です。書き込む値は0x03c00xx0をお勧めします。xxの部分はドライブ能力を最小にするなら00で、最大にするなら3cです。
メモ: 技術系の話はFacebookから転記しておくことにした。追記、文章の組み換えをした。
この記事にコメントする
目次: Linux
Linuxのクロックフレームワークで実装できるクロック分周器のドライバは2種類あります。
1つはinteger dividerで、入力されたクロック周波数の1/3や1/4など整数比の周波数で出力するハードウェアです。もう1つはfractional dividerで、周波数をx/yにするハードウェアです。
後者のfractional dividerドライバは、標準動作とカスタム動作のドライバが書けます。標準動作の場合、分子と分母に設定できる値に、何ら制約がないものとして動作します。カスタム動作のドライバは、特殊な制約のあるハードウェア向けです。
今のところカスタム動作のfractional dividerドライバを実装しているのはRockchipだけです。Rockchipの場合、分母が分子の20倍以上でなければ出力周波数が不安定になる制約があるようです。
Rockchipが変な仕様であることは間違いないと思いますが、Linuxに対応しているだけ、まだマシとも取れますね。世の中には「どうしてこうなった??」としか思えない、変な仕様のハードウェアがたくさん存在しますし……。
メモ: 技術系の話はFacebookから転記しておくことにした。
この記事にコメントする
目次: ARM
先日購入したHDMIモニタのおかげで、ROCK64のI2S0つまりHDMI Audioの動作確認ができました。
しかし以前(2018年11月11日の日記参照)悩んでいた通り、単純にI2S0を有効にすることはできません。DMAチャネルが足りない問題が発生するためです。
ROCK64に搭載されているRockchip RK3328のDMACは、16のDMAチャネルを持っていますが、そのうち8chしか同時に使えない仕様になっています。
現在のlinux-nextのROCK64向けデバイスツリーでは、既に7chを使用(I2S1 2ch, SPDIF 1ch, SPI0 2ch, UART2 2ch)していますから、ここに2chを使用するI2S0を追加すると合計9chになって、オーバーしてしまいます。
仕方ないのでUART2のDMA割り当てを解除して、I2S0に割り当てるパッチを投稿しました。
私がパッチに書いた説明が悪かったのだと思いますが、メンテナーのHeikoさんから「どうしてUART2のDMAチャネルをI2S0が使えるのかわからない」という返事がきました。ですよね……私も最初意味不明でしたし。
できる限り説明を加えて返事しましたが、理解してもらえると良いな。
ややこしいことに、RK3328の仕様書を見ると、各DMAチャネルにはIDが(仕様書ではReq number)が振られていて、ぱっと見16チャネルが全て同時に使えそうに見えるんですよ。
この仕様書から「各DMAチャネルは独立しているけど、全てのチャネルが同時に使える訳ではない」という意味を読み取れる人はなかなかいないと思います。
少なくとも私はDMAのReq numberとチャネル数の関係を理解するのは無理だったので、DMACのドライバ(PL330)を追いかけました。
サウンド系からDMAチャネルの割り当てを要求するとき、次のような呼び出し関係になります。
rockchip_pcm_platform_register()
devm_snd_dmaengine_pcm_register()
snd_dmaengine_pcm_register()
dmaengine_pcm_request_chan_of()
dma_request_slave_channel_reason()
of_dma_request_slave_channel()
ofdma->of_dma_xlate() => of_dma_pl330_xlate()
dma_get_slave_channel()
dma_chan_get()
pl330_alloc_chan_resources()
pl330_request_channel()
まず、関数of_dma_pl330_xlate() にはローカル変数chan_idが登場します。これがDMAのIDに相当します。例えばUART2の送信側ならchan_id = 6になります。
元になる数字はどこから来るかというと、of_dma_match_channel() でデバイスツリーから情報を貰っています。RK3328の場合、デバイスツリーでDMAチャネルを指定する際は、Req numberを書くようです。
次に、関数pl330_request_channel() に構造体struct pl330_dmacのメンバーchannelsという配列が登場します。このchannelsの数がDMACのDMAチャネルの数と等しいです。Req numberとは無関係に、DMAチャネルを要求されると先頭から埋まっていきます。
こんな仕様が初見でわかる訳ないじゃない。むり。
メモ: 技術系の話はFacebookから転記しておくことにした。1節加筆。
この記事にコメントする
| < | 2019 | > | ||||
| << | < | 02 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | - | - | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | - | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: