spi-gpio时钟频率问题

1. 问题描述

  • iso1i811t.ko驱动模块加载成功后,运行spidev.out -v -s 125000测试用例,示波器发现SCK的频率是500 khz。
  • 通过-s参数反复切换不同频率,示波器测量到的频率都是500 khz,设置的频率参数没有起作用。

2.问题分析

通过跟踪内核代码,发现模拟SPI SCK的频率在$(KERN-DIR)/drivers/spi/spi-bitbang-rxtx.h函数bitbang_txrx_be_cpha1里:

static inline u32
bitbang_txrx_be_cpha0(struct spi_device *spi,
		unsigned nsecs, unsigned cpol, unsigned flags,
		u32 word, u8 bits)
{
	/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
	u32 oldbit = (!(word & (1<<(bits-1)))) << 31;

	//printk("<***Liuyh***>: nsecs: %d cpol: %d flags: %d word:%d bits:%d\n",nsecs,cpol,flags,word,bits);	
	/* clock starts at inactive polarity */
	for (word <<= (32 - bits); likely(bits); bits--) {

		/* setup MSB (to slave) on trailing edge */
		if ((flags & SPI_MASTER_NO_TX) == 0) {
			if ((word & (1 << 31)) != oldbit) {
				setmosi(spi, word & (1 << 31));
				oldbit = word & (1 << 31);
			}
		}
		spidelay(nsecs);	/* T(setup) */

		setsck(spi, !cpol);
		spidelay(nsecs);

		/* sample MSB (from slave) on leading edge */
		word <<= 1;
		if ((flags & SPI_MASTER_NO_RX) == 0)
			word |= getmiso(spi);
		setsck(spi, cpol);
	}
	
	return word;
}

    可以发现,我们通过spidev.out -s 125000设置频率参数,最终会换算成nsecs。频率换算成nesec是通过$(KERN-DIR)/drivers/spi/spi-bitbang.c里的spi_bitbang_setup_transfer函数完成:

int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{
	struct spi_bitbang_cs	*cs = spi->controller_state;
	u8			bits_per_word;
	u32			hz;

	if (t) {
		bits_per_word = t->bits_per_word;
		hz = t->speed_hz;
	} else {
		bits_per_word = 0;
		hz = 0;
	}

	/* spi_transfer level calls that work per-word */
	if (!bits_per_word)
		bits_per_word = spi->bits_per_word;
	if (bits_per_word <= 8)
		cs->txrx_bufs = bitbang_txrx_8;
	else if (bits_per_word <= 16)
		cs->txrx_bufs = bitbang_txrx_16;
	else if (bits_per_word <= 32)
		cs->txrx_bufs = bitbang_txrx_32;
	else
		return -EINVAL;

	
	/* nsecs = (clock period)/2 */
	if (!hz)
		hz = spi->max_speed_hz;
	if (hz) {
		cs->nsecs = (1000000000/2) / hz;
		if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
			return -EINVAL;
	}

	return 0;
}

     通过分析上面折代码可以发现,125000 hz频率换算后,结果是4000nsecs,所以在bitbang_txrx_be_cpha0中,最终通过spidelay(nsecs)实现SCK的时钟频率。

 

接下来进一步分析spidelay函数的定义:

/*
 * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
 * requested device clock.  Software overhead means we usually have trouble
 * reaching even one Mbit/sec (except when we can inline bitops), so for now
 * we'll just assume we never need additional per-bit slowdowns.
 */
#define spidelay(nsecs)	do {} while (0)

通过分析上面问题,发现频率没有设置成功的原因是出现在spidelay上面。

 

3. 问题解决

#if defined (CONFIG_SPI_GPIO_DELAY)
#define spidelay(nsecs) ndelay(nsecs)
#else

/*
 * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
 * requested device clock.  Software overhead means we usually have trouble
 * reaching even one Mbit/sec (except when we can inline bitops), so for now
 * we'll just assume we never need additional per-bit slowdowns.
 */
#define spidelay(nsecs)	do {} while (0)
#endif

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值