Armadilloフォーラム

SPI CLK (POL,PHA)設定について

k-tsuru

2017年7月5日 17時37分

いつもお世話になっております。

Armadillo-X1、拡張I/F(CON8)のSPIにて、
SCLKのタイミング変更を行おうとしております。

imx7dual-reference-manualのP2592、Fig.10-10を参考に、
POL=1, PHA=1の設定を使用したいのですが、
ユーザーランド側にて、spidevのioctl、
・SPI_IOC_RD_MODE
・SPI_IOC_WR_MODE
をそれぞれ、SPI_MODE_3に設定したところ、
POL=0, PHA=0のクロックが出力されているように見られました。

設定が足りないと思うのですが、
その他変更に必要な項目をご教授いただけませんでしょうか。
(SPIの設定に関しては、https://users.atmark-techno.com/blog/615/2577 を利用中です。)

コメント

溝渕です。

恐らくドライバとしてはちゃんと対応しています。

> Armadillo-X1、拡張I/F(CON8)のSPIにて、
> SCLKのタイミング変更を行おうとしております。
>
> imx7dual-reference-manualのP2592、Fig.10-10を参考に、
> POL=1, PHA=1の設定を使用したいのですが、

該当レジスタは、P2603、Config Register (ECSPIx_CONFIGREG)です。
SCLK_POLとSCLK_PHAはチャンネルごとに設定します、

> ユーザーランド側にて、spidevのioctl、
> ・SPI_IOC_RD_MODE
> ・SPI_IOC_WR_MODE
> をそれぞれ、SPI_MODE_3に設定したところ、
> POL=0, PHA=0のクロックが出力されているように見られました。

ちなみにioctlは成功していますか?

ドライバの実装は、

include/linux/spi/spi.h:
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)

drivers/spi/spi-imx.c:
static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
{
:snip
if (config->mode & SPI_CPHA)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);

if (config->mode & SPI_CPOL) {
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
}

のようになっています。

> 設定が足りないと思うのですが、
> その他変更に必要な項目をご教授いただけませんでしょうか。

実装が上記の通りであるため、足りないとするとcsの指定くらいでしょうか。

spi driverにデバッグコードを入れると何が起っているか理解しやすくなると
思います。

溝渕様

いつもお世話になっております。
回答ありがとうございます。

デバッグコードを仕込むことで、設定の確認が出来ました。

> ちなみにioctlは成功していますか?
SPI_IOC_RD_MODE/SPI_IOC_WR_MODE設定時、SPI_IOC_MESSAGE通信時共に成功しておりました。

> 実装が上記の通りであるため、足りないとするとcsの指定くらいでしょうか。
CSも問題なかったと思われます。

当初、実装は下記の流れとなっておりました。
open→ioctl(SPI_IOC_RD_MODE)→ioctl(SPI_IOC_WR_MODE)→ioctl(SPI_IOC_MESSAGE)→close

この場合、デバッグにて確認したところ、
/drivers/spi/spi-imx.c mx51_ecspi_config()での、
SCLKPHA設定、SCLKPOL設定が行われておりませんでした。

しかし、SPI_IOC_RD_MODEの設定を行わない、下記の流れでは、
SCLKPHA設定、SCLKPOL設定が成功しておりました。
open→ioctl(SPI_IOC_WR_MODE)→ioctl(SPI_IOC_MESSAGE)→close

後者の設定にて、期待の動作が確認出来ましたが、
SPIの書き込み、読み込みに全二重通信(ioctl(SPI_IOC_MESSAGE))を使用する場合、
SPI_IOC_RD_MODEの設定は不要なのでしょうか。

以上、よろしくお願い致します。

溝渕です。

> 当初、実装は下記の流れとなっておりました。
> open→ioctl(SPI_IOC_RD_MODE)→ioctl(SPI_IOC_WR_MODE)→ioctl(SPI_IOC_MESSAGE)→close

1. openして、
2. 現在のmodeを読み出して、
3. 新しいmodeを設定して
:(以下略)

とやると、

> この場合、デバッグにて確認したところ、
> /drivers/spi/spi-imx.c mx51_ecspi_config()での、
> SCLKPHA設定、SCLKPOL設定が行われておりませんでした。

新しいmodeの設定がなされず、

> しかし、SPI_IOC_RD_MODEの設定を行わない、下記の流れでは、
> SCLKPHA設定、SCLKPOL設定が成功しておりました。
> open→ioctl(SPI_IOC_WR_MODE)→ioctl(SPI_IOC_MESSAGE)→close

1. openして、
2. 新しいmodeを設定して
:(以下略)

とやると、

> 後者の設定にて、期待の動作が確認出来ましたが、

新しいmodeの設定がなされた。

ということなので、新しいmodeの値更新タイミングが問題なのではないでしょうか?

SPI_MODE_3を格納したmodeを、SPI_IOC_RD_MODEの読み出しで上書きしていませんか?

> SPIの書き込み、読み込みに全二重通信(ioctl(SPI_IOC_MESSAGE))を使用する場合、
> SPI_IOC_RD_MODEの設定は不要なのでしょうか。

設定ではなく読み出しです。

drivers/spi/spidev.c:

static long
spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
:(snip)
case SPI_IOC_RD_MODE:
retval = __put_user(spi->mode & SPI_MODE_MASK,
(__u8 __user *)arg);
break;

なので、ユーザー空間に現在のSPI modeをコピーしているだけです。

溝渕様

いつもお世話になっております。

> SPI_MODE_3を格納したmodeを、SPI_IOC_RD_MODEの読み出しで上書きしていませんか?
上書きしていた模様です。
私の仕様誤認によるミスでした。

SPI_IOC_RD_MODEの処理をよく理解しておりませんでした。
お騒がせして申し訳ありません。

SPI_IOC_WR_MODEにて、modeの"設定"、解決致しました。
解りやすく詳細な説明、誠にありがとうございました。

以上、よろしくお願い致します。

溝渕です。

> > SPI_MODE_3を格納したmodeを、SPI_IOC_RD_MODEの読み出しで上書きしていませんか?
> 上書きしていた模様です。
> 私の仕様誤認によるミスでした。

すみません。そもそもドキュメントに誤りがあります。

参照されていた、
https://users.atmark-techno.com/blog/615/2577
からリンクされている
http://manual.atmark-techno.com/armadillo-guide/armadillo-guide-3_ja-3…
で、次のように記載されています

> SPI_IOC_RD_MODE, SPI_IOC_WR_MODE: 読み出しまたは書き込み時に使用するSPIモードを設定します

spidevがlinux kernelに入った2007年から今現在もAPI仕様は変更されておら
ず、SPI_IOC_RD_MODEはSPIモードの読み出し用のioctlコマンドです。

混乱させてしまい大変申し訳ございません。

溝渕様

いつもお世話になっております。

無事、期待のモードへ設定が出来ました。
また、SPI_IOC_RD_MODEは、現在のモード呼び出しとして使用させていただきます。

丁寧なご説明、ありがとうございました。