用mini2440烧写spiflash『上』

本文介绍了如何利用mini2440开发板制作SPI闪存烧录器。首先,确保SPI硬件接口正确连接,SPI Flash的WP#和Hold#引脚需拉高。然后,参考相关资料修改驱动程序,成功后通过ls -l /dev/spi*命令查看设备节点。这是一个动手实践的过程,旨在解决小容量Flash和RAM限制的问题。

       前段时间,偶然发现有些路由器是可以下第三方的固件,自己就弄了下。可我的740N的flash和ram都比较小,要升级硬件。就从TB上买了4M的25L32,从公司捞了几片32M的SDRAM。spiflash先是用同事的烧写器烧的,后来就萌发出用以前买的mini2440弄出烧写器。

mini2440上没有spiflash的例子程序真是遗憾。

        首先是spi硬件接口。

        在板子上GPIO接口上是可以引出来的。引线方法不再多说,在原理图或手册上都可以看清楚。强调一下,spiflash的wp#与hold#是要拉高的,不能悬空,没有电阻的话直接接3.3V上也可以。

        接下来是修改驱动程序。

        我是参考http://blog.youkuaiyun.com/lxmky/article/details/6858322弄得。下好重启后,会

[root@FriendlyARM fengchen]# ls -l /dev/spi*

crw-rw----    1 root     root     153,   0 Jan  1 08:00 /dev/spidev0.0

crw-rw----    1 root     root     153,   1 Jan  1 08:00 /dev/spidev1.0

[root@FriendlyARM fengchen]# 

        随后确实可以用Documentation/spi/spidev_test.c作测试。
        不过,程序中用ioctl的返回是否为1判断调用是否成功,这样是有问题的(新版本内核已修改)。其一,返回是1会让人觉得调用是有问题;其二,返回值其实是传输的个数(read/write,全双工),如果传输一个字节,就会被认为是调用不成功。
        可以看下driver/spi/spidev.c,spidev_ioctl函数调用spidev_message,在函数中添加的printk如下:
static int spidev_message(struct spidev_data *spidev,
		struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
{
	struct spi_message	msg;
	struct spi_transfer	*k_xfers;
	struct spi_transfer	*k_tmp;
	struct spi_ioc_transfer *u_tmp;
	unsigned		n, total;
	u8			*buf;
	int			status = -EFAULT;


	spi_message_init(&msg);
	k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
	if (k_xfers == NULL)
		return -ENOMEM;


	/* Construct spi_message, copying any tx data to bounce buffer.
	 * We walk the array of user-provided transfers, using each one
	 * to initialize a kernel version of the same transfer.
	 */
	buf = spidev->buffer;
	total = 0;		printk("\n[0status=%d/total=%d]\n",status,total);
	for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
			n;
			n--, k_tmp++, u_tmp++) {
		k_tmp->len = u_tmp->len;


		total += k_tmp->len;		printk("[1status=%d/total=%d]\n",status,total);
		if (total > bufsiz) {
			status = -EMSGSIZE;		printk("[goto done 0]");
			goto done;
		}


		if (u_tmp->rx_buf) {
			k_tmp->rx_buf = buf;
			if (!access_ok(VERIFY_WRITE, (u8 __user *)
						(uintptr_t) u_tmp->rx_buf,
						u_tmp->len)){		printk("[goto done 1]");
				goto done;}
		}
		if (u_tmp->tx_buf) {
			k_tmp->tx_buf = buf;
			if (copy_from_user(buf, (const u8 __user *)
						(uintptr_t) u_tmp->tx_buf,
					u_tmp->len)){		printk("[goto done 2]");
				goto done;}
		}
		buf += k_tmp->len;


		k_tmp->cs_change = !!u_tmp->cs_change;
		k_tmp->bits_per_word = u_tmp->bits_per_word;
		k_tmp->delay_usecs = u_tmp->delay_usecs;
		k_tmp->speed_hz = u_tmp->speed_hz;
#ifdef VERBOSE
		printk(
			"  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
			u_tmp->len,
			u_tmp->rx_buf ? "rx " : "",
			u_tmp->tx_buf ? "tx " : "",
			u_tmp->cs_change ? "cs " : "",
			u_tmp->bits_per_word ? : u_tmp->bits_per_word,
			u_tmp->delay_usecs,
			u_tmp->speed_hz ? : u_tmp->speed_hz);
#endif
		spi_message_add_tail(k_tmp, &msg);
	}		printk("[2status=%d/total=%d]\n",status,total);


	status = spidev_sync(spidev, &msg);//返回传输的个数
	if (status < 0){		printk("[goto done 3]");
		goto done;}
		printk("[3status=%d/total=%d]\n",status,total);
	/* copy any rx data out of bounce buffer */
	buf = spidev->buffer;
	for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
		if (u_tmp->rx_buf) {
			if (__copy_to_user((u8 __user *)
					(uintptr_t) u_tmp->rx_buf, buf,
					u_tmp->len)) {
				status = -EFAULT;		printk("[goto done 4]");
				goto done;
			}
		}
		buf += u_tmp->len;
	}		printk("[4status=%d/total=%d]\n",status,total);
//	status = total;
//上面这句是不应该有的

done:			printk("[5status=%d/total=%d]\n",status,total);
	kfree(k_xfers);
	return status;
}

在传输时通过串口的打印可以看出问题产生在哪儿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值