加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

用mini2440烧写spiflash『中』

发布时间:2020-12-15 06:13:16 所属栏目:百科 来源:网络整理
导读:上部分主要是说了下调试方法。 另外修改了下spidev.c中的 //static unsigned bufsiz = 4096;static unsigned bufsiz = 4*1024*1024; 下面贴上烧写/读取程序。 程序的致命弱点是速度太慢,主要是因为每次ret = ioctl(Fd_dev,SPI_IOC_MESSAGE(2),Spi_tr);调用
上部分主要是说了下调试方法。
另外修改了下spidev.c中的
//static unsigned bufsiz = 4096;
static unsigned bufsiz = 4*1024*1024;

下面贴上烧写/读取程序。
程序的致命弱点是速度太慢,主要是因为每次ret = ioctl(Fd_dev,SPI_IOC_MESSAGE(2),Spi_tr);调用都要花费20ms,

希望高手可以提出解决方法。

/*
 * SPI program chip(using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software,Inc.
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
 * Copyright (c) 2012 fengchen <fengchen_rs@qq.com>
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
 */

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

/*********spi conf******************/
#define SPI_BITS_PER_WORD 8
#define SPI_SPEED 25000000
#define SPI_MODE 0
#define SPI_DEVICE "/dev/spidev0.0"
#define ONCE_READ_MAX_BYTES 3*1024*1024

/*********device******************/
#define MX25L32
//#define MX25L64
//#define W25Q80

/*******************pagesize*******************/
#define SIZE_1M_PAGE_NUM 256*16	//(256sectors)*(16pages/sector)

#ifdef W25Q80
//#define CHIP_ID 0x13
#define SPI_FLASH_25_X_XX
#define PAGE_NUM SIZE_1M_PAGE_NUM
#define TIME_ERASECHIP 2*1000*1000
#define TIME_PAGEPROGRAM 700
#endif

#ifdef MX25L32
//#define CHIP_ID 0x15
#define SPI_FLASH_25_X_XX
#define PAGE_NUM SIZE_1M_PAGE_NUM*4
#define TIME_ERASECHIP 25*1000*1000
#define TIME_PAGEPROGRAM 1400
#endif

#ifdef MX25L64
//#define CHIP_ID 0x16
#define SPI_FLASH_25_X_XX
#define PAGE_NUM SIZE_1M_PAGE_NUM*8
#define TIME_ERASECHIP 50*1000*1000
#define TIME_PAGEPROGRAM 1400
#endif

/*************** cmd type ************/
struct cmd_type {
	char* cmd_name;
	uint8_t cmd;
	uint8_t num_addr;
	uint8_t *p_cmd_addr;
	uint8_t num_dummy;
	uint8_t mode_data_rw;	//r:0,w:1
	uint32_t num_data;	
	uint8_t *p_rw_data;
	uint32_t delay_usecs;
};

#ifdef SPI_FLASH_25_X_XX
#define PAGE_SIZE 256		//256bytes/page
#define CHIP_SIZE PAGE_SIZE*PAGE_NUM
#define NUM_ADDR 3

struct cmd_type cmd_readdeviceid = {
	.cmd_name = "cmd_readdeviceid",.cmd = 0xAB,.num_addr = 0,.p_cmd_addr = NULL,.num_dummy = 3,.mode_data_rw = 0,.num_data = 1,.delay_usecs = 0,};
struct cmd_type cmd_chiperase = {
	.cmd_name = "cmd_chiperase",.cmd = 0x60,.num_dummy = 0,.num_data = 0,.p_rw_data = NULL,.delay_usecs = TIME_ERASECHIP,//
};
struct cmd_type cmd_writeenable = {
	.cmd_name = "cmd_writeenable",.cmd = 0x06,};
struct cmd_type cmd_readstatus = {
	.cmd_name = "cmd_readstatus",.cmd = 0x05,};
struct cmd_type cmd_fastread = {
	.cmd_name = "cmd_fastread",.cmd = 0x0B,.num_addr = NUM_ADDR,.num_dummy = 1,.num_data = CHIP_SIZE,};
struct cmd_type cmd_pageprogram = {
	.cmd_name = "cmd_pageprogram",.cmd = 0x02,.mode_data_rw = 1,.num_data = PAGE_SIZE,.delay_usecs = 0/4,//transmit need too long time
};
#endif

int Fd_dev;//spi device

struct spi_ioc_transfer Spi_tr[2]={
	{
		.cs_change = 0,//not change(??)
		.bits_per_word = SPI_BITS_PER_WORD,.rx_buf = (unsigned long)NULL,},{
		.cs_change = 0,//change(??)
		.bits_per_word = SPI_BITS_PER_WORD,};
struct timeval  tv;

void prt_time(uint8_t num)
{
	gettimeofday(&tv,NULL);
	printf("[%d,time is %ld]n",num,tv.tv_usec);
}

uint8_t transmit(struct cmd_type *p_cmd)
{
	int ret;
	uint32_t i;
	uint8_t *a_tr_buf;
	struct spi_ioc_transfer *p_spi_tr;
	
	/*send cmd+addr+dummy */		prt_time(0);
	p_spi_tr = Spi_tr;
	p_spi_tr->len = 1+(p_cmd->num_addr)+(p_cmd->num_dummy);
	a_tr_buf = (uint8_t *)malloc(p_spi_tr->len);
	p_spi_tr->tx_buf = (unsigned long)a_tr_buf;
	p_spi_tr->rx_buf = (unsigned long)NULL;
	a_tr_buf[0] = p_cmd->cmd;		prt_time(1);
	for(i=0;i<(p_cmd->num_addr);i++){
		a_tr_buf[1+i] = (p_cmd->p_cmd_addr)[(p_cmd->num_addr-1)-i];//large addr first
	}
	for(i=0;i<(p_cmd->num_dummy);i++){
		a_tr_buf[1+(p_cmd->num_addr)+i] = 0xFF;
	}
	/*send/receive data*/			prt_time(2);
	p_spi_tr ++;
	p_spi_tr->len = p_cmd->num_data;
	p_spi_tr->delay_usecs = p_cmd->delay_usecs;
	if(p_cmd->num_data){	
		if(p_cmd->mode_data_rw){	//write
			p_spi_tr->tx_buf = (unsigned long)(p_cmd->p_rw_data);
			p_spi_tr->rx_buf = (unsigned long)NULL;
		}
		else{//read
			p_spi_tr->tx_buf = (unsigned long)NULL;
			p_spi_tr->rx_buf = (unsigned long)(p_cmd->p_rw_data);
		}	
	}	
		
	/*spi operation*/			prt_time(3);
	ret = ioctl(Fd_dev,Spi_tr);		prt_time(4);
	if (ret < 1){
		printf("n[Return = %d. Can't read/write chip !]n",ret);
		goto ERROR;
	}
	free(a_tr_buf);				prt_time(5);
	return 0;

ERROR:
	free(a_tr_buf);
	return 1;
}

uint8_t spi_conf(char *device)
{
  	int ret = 0;
	uint8_t mode = SPI_MODE,bits_per_word = SPI_BITS_PER_WORD;
	uint32_t max_speed_hz = SPI_SPEED;
	
	ret += ioctl(Fd_dev,SPI_IOC_WR_MODE,&mode);
	ret += ioctl(Fd_dev,SPI_IOC_RD_MODE,SPI_IOC_WR_BITS_PER_WORD,&bits_per_word);
	ret += ioctl(Fd_dev,SPI_IOC_RD_BITS_PER_WORD,SPI_IOC_WR_MAX_SPEED_HZ,&max_speed_hz);
	ret += ioctl(Fd_dev,SPI_IOC_RD_MAX_SPEED_HZ,&max_speed_hz);
	
	if(ret||(mode!=SPI_MODE)||(bits_per_word!=SPI_BITS_PER_WORD)||(max_speed_hz!=SPI_SPEED)){
		printf("SPI mode configure ERROR : mode=%d!n",mode);
		return 1;
	}
	
	return 0;
}

uint8_t read_status()
{
	uint8_t status=0x88;
	int ret;
	
	cmd_readstatus.p_rw_data = &status;
	ret = transmit(&cmd_readstatus);	
	if(ret){
		puts("Read status ERROR!");
	}
	
	return status;
}

uint8_t write_enable()
{
	int ret;
	
	ret = transmit(&cmd_writeenable);
	if(ret){
		puts("Set WEL bit ERROR: 0!");
		return 1;
	}
	
	return 0;
}
uint8_t verity_id(char * filename)
{
	uint8_t id=0x1d;
	int ret;
	struct stat file_status;
	
	ret = stat(filename,&file_status);
	if(ret < 0){
		puts("nRead file status ERROR!");
		return 1;
	}
	printf("nFile size is %ldBytes(%.2fMBytes).n",file_status.st_size,(float)file_status.st_size/1024/1024);
	if(file_status.st_size > CHIP_SIZE){
		puts("Error : File size is bigger than Chip size!");
		return 1;
	}
		
	if((read_status())&0x01){
		puts("Device is busy!");
		return 1;
	}
	cmd_readdeviceid.p_rw_data = &id;		
	ret = transmit(&cmd_readdeviceid);
	if(ret){
		puts("Get ID Failure!");
		return 1;
	}
	printf("The chip ID is 0x%x.nContinue ? (y/n)",id);
	if(getchar()=='y'){
		puts("Wait several minute...");
	}
	else{
		puts("Exit.n");
		return 1;
	}
	return 0;
}

uint8_t erase_chip()
{
	int ret;
	uint32_t sleep_time;
	uint32_t i = 0;

	ret = write_enable();
	if(ret){
		puts("Erase disable!");
		return 1;
	}
	ret = transmit(&cmd_chiperase);
	if(ret){
		puts("Erase chip ERROR 1 !");
		return 1;
	}
	else{
		if((read_status())&0x01){
			printf("Erasing...");
		}
		else{		//not working
			puts("Erase chip ERROR 2 !");
			return 1;
		}
	}
	sleep_time = cmd_chiperase.delay_usecs/100;
	while((read_status())&0x01){
		usleep(sleep_time);
	}	
	puts("nErase Done.");//spi_ioc_transfer-delay_usecs
	
	return 0;
}

uint8_t write_page(uint32_t num_page,uint8_t *p_buf_w)
{
	int ret;
	uint32_t j;
	uint32_t sleep_time;
	uint8_t p_addr[NUM_ADDR];

	for(j=0;j<NUM_ADDR;j++){
		p_addr[j] = (uint8_t)((num_page*PAGE_SIZE)>>(8*j));
	}
	cmd_pageprogram.p_cmd_addr = p_addr;
	cmd_pageprogram.p_rw_data = p_buf_w;

	ret = write_enable();
	if(ret){
		puts("nWrite disable!n");
		goto ERROR;
	}
	ret = transmit(&cmd_pageprogram);
	if(ret){
		printf("nWrite Failure! Page : %d!n",num_page);
		goto ERROR;
	}
	sleep_time = cmd_pageprogram.delay_usecs/100;
	while((read_status())&0x01){
		usleep(sleep_time);
	}
	return 0;

ERROR:	
	return 1;
}

uint8_t write_chip(char * filename)
{
	uint8_t *p_buf_w;
	int i;
	int ret;
	int fd_file;
	int size_w,num;
			
	fd_file = open(filename,O_RDONLY);
	if (fd_file < 0){
		printf("Can't open file : %sn",filename);
		return 1;
	}		
	p_buf_w = (uint8_t*)malloc(CHIP_SIZE);
	size_w = read(fd_file,p_buf_w,CHIP_SIZE);
	if(size_w<0){
		puts("Read file ERROR!");
		return 1;
	}	
	memset(p_buf_w+size_w,0xff,PAGE_SIZE-size_w%PAGE_SIZE);	
	
	printf("Writing...  ---%%.");
	num=size_w;
	for(i=0;num>0;i++)
	{		prt_time(10);
		ret = write_page(i,p_buf_w+PAGE_SIZE*i);
		if(ret){
			printf("nWrite page %d ERROR!n",i);
			goto ERROR;
		}
		printf("bbbbb%03d%%.",(i*PAGE_SIZE*100)/size_w);
		num -= PAGE_SIZE;
	}
	printf("bbbbb100%%.nWrite Done.n",size_w);
	close(fd_file);
	free(p_buf_w);
	return 0;
	
ERROR:
	close(fd_file);
	free(p_buf_w);
	return 1;
}

uint8_t read_chip(uint8_t *p_buf_r,uint32_t size_r)
{
	uint8_t p_addr[NUM_ADDR];
	int ret;
	uint32_t i,j;
	int n;
	uint32_t addr;
	
	addr = 0;
	for(n = size_r,i = 0;n > 0;n -= ONCE_READ_MAX_BYTES,i++){
		addr += ONCE_READ_MAX_BYTES*i;
		for(j=0;j<NUM_ADDR;j++){
			p_addr[j] = (uint8_t)(addr>>j*8);
		}
		cmd_fastread.p_cmd_addr = p_addr;

		p_buf_r += ONCE_READ_MAX_BYTES*i;
		cmd_fastread.p_rw_data = p_buf_r;
		
		if(n<ONCE_READ_MAX_BYTES){
			cmd_fastread.num_data = n;
		}
		else{
			cmd_fastread.num_data = ONCE_READ_MAX_BYTES;
		}
		
		ret = transmit(&cmd_fastread);
		if(ret){
			puts("nRead CHIP Failure!");
			goto ERROR;
		}
	}
	return 0;
	
ERROR:
	return 1;
}

uint8_t verity_chip(char * filename)
{
	uint8_t *p_buf_r,*p_buf_file;
	int ret;
	uint32_t i;
	int fd_file;
	int size_r,num;				
		
	fd_file = open(filename,filename);
		return 1;
	}	
	p_buf_file = (uint8_t *)malloc(CHIP_SIZE);
	size_r = read(fd_file,p_buf_file,CHIP_SIZE);
	if(size_r<0){
		puts("Read file ERROR!");
		return 1;
	}		
	
	p_buf_r = (uint8_t *)malloc(CHIP_SIZE);
	ret = read_chip(p_buf_r,size_r);
	if(ret){
		goto ERROR;
	}				

	puts("Veritying...");
/*
 	for(i=0;i<size_r;i++)
	{
		if(p_buf_file[i]!=p_buf_r[i]){	//not match
			printf("nByte num %d Error! p_buf_file[%d]=%2x,p_buf_r[%d]=%2x.n",i,p_buf_file[i],p_buf_r[i]);
			goto ERROR;
		}
		printf("bbbbb%3d%%.",i/(size_r/100));
	}
*/
	ret = memcmp(p_buf_file,p_buf_r,size_r);
	if(ret){
		puts("Verity ERROR!");
		goto ERROR;
	}
	else{
		puts("Verity Done.");
	}
	close(fd_file);
	free(p_buf_file);
	free(p_buf_r);
	return 0;

ERROR:
	close(fd_file);
	free(p_buf_file);
	free(p_buf_r);
	return 1;	
}

void check_exit(int ret)
{
	if(ret){
		close(Fd_dev);
		exit(0);
	}
}
int main(int argc,char *argv[])
{
	int ret;
	char *filename = argv[1];//"/home/fengchen/nfs.dir/spi_flash/MX25L80_firmware";
	
	Fd_dev = open(SPI_DEVICE,O_RDWR);
	if (Fd_dev < 0){
		puts("Can't open device.");
		return 1;
	}
	ret = spi_conf(SPI_DEVICE);
	check_exit(ret);

	ret = verity_id(filename);
	check_exit(ret);
	ret = erase_chip();
	check_exit(ret);

	ret = write_chip(filename);
	check_exit(ret);		
	ret = verity_chip(filename);
	check_exit(ret);

	close(Fd_dev);
	puts("Succeed !");	//ok
	return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读