LiteOS系统--快速烧写.bin文件到norflash相应位置

华为LiteOS系统因OS和app代码是通过接口app_init衔接在一块的,所以在开发调试中每次进行修改后都需要重新烧写flash,这样其实很麻烦,所以干脆写了个工具辅助进行文件传输,使用TCP协议,代码分为设备端和linux主机端,

注意在LiteOS系统调用的app_init()函数里边,注册如下命令:

    osCmdReg(CMD_TYPE_EX, "WriteNorFlash",1, (CMD_CBK_FUNC)write_file_to_nor_flash);
    osCmdReg(CMD_TYPE_EX, "RecvWriteNor",0, (CMD_CBK_FUNC)receive_and_write_file_to_nor_flash);

 

用来在命令行下通过输入命令“WriteNorFlash” 或者“RecvWriteNor”直接调用如下函数写入或接收写入.bin文件到指定Norflash位置:

  • 设备端代码 .c  和 .h文件:

 其中擦写的起始地址和大小可通过宏来改变:

#define FLASH_START_ADDRESS 0x100000   //liteOS写OS和app的起始地址
#define ERRASE_SIZE   (7*1024*1024)           //擦除7M大小的空间

#include 
#include 
#include 
#include 
#include 
#include 

#include "write_file_to_flash.h"
#include "spinor.h"

#include //不加会报隐式声明与内建函数'exit'不兼容
#include 
#include //因用了地址

/*******************************************************************
手动烧写文件到norflash,
从设备文件系统中读取一个系统文件(ipc8.bin)烧到norflash的系统位置,
********************************************************************/
//argv[1]:要读取的源文件
int  write_file_to_nor_flash(int argc,char**argv)
{
	char need_help = !strcmp(argv[0],"-h")||!strcmp(argv[0],"-help");
	if(argc < 1||need_help)
	{
		
		printf("usage: WriteNorFlash  [inputfile]\n\
			Atteion : inputfile need absolute path\n\
			eg : WriteNorFlash /jffs0/ipc18.bin  \n");
		return 0;
	}
	//printf("argv[0] = %s \n",argv[0]);
	int read_file = open((const char *)argv[0], O_RDONLY);
	if( read_file < 0)
	{
		
		perror("open read_file  error !\n");
		return -1;
	}

	/*分配缓存空间*/
	char * read_buffer = (char*)malloc(ERRASE_SIZE);
	if(NULL == read_buffer)
	{
		perror("malloc failed !\n");
		return -1;
	}
	memset(read_buffer,0,ERRASE_SIZE);

	/*读取文件至缓存空间*/
	unsigned long size = read(read_file,read_buffer,ERRASE_SIZE);
	printf("read size = %d bytes\n",size);

	/*擦除NorFlash*/
	printf("erase NorFlash......\n");
	int ret = hispinor_erase(FLASH_START_ADDRESS, ERRASE_SIZE);

	/*写NorFlash*/
	printf("write NorFlash......\n");
	ret = hispinor_write(read_buffer, FLASH_START_ADDRESS, size);
	if(0 == ret)
	{
		printf("write NroFlash success ,write(%d)bytes!\n",size);
	}
	else
	{
		perror("write NroFlash failed !\n");
	}
	

	free(read_buffer);
	close(read_file);
	return 0;
}

/*******************************************************************
功能:接收文件到内存并直接烧写到norflash (TCP传输):
	专门烧写系统文件(ipc18.bin)用,提高开发调试速度,比ftp传输文件
	再烧写的方式要快,因接收的数据不保存成文件,而是直接从内存写入norflash
使用:配合客户端程序 send_and_write_file_to_norflash 使用
	1.设备端运行命令“RecvWriteNor”(会调用该函数)等待接收数据;
	2.虚拟机(linux主机)下运行客户端程序 send_and_write_file_to_norflash
		格式:send_and_write_file_to_norflash [file name] [deviceIP]
		eg: ./send_and_write_file_to_norflash ipc18.bin 192.168.3.82
注意:目前没有加入文件校验机制
*******************************************************************/
#define portnum  5555  //端口有可能端口被占用,可以改端口才能通
int  receive_and_write_file_to_nor_flash(int argc,char**argv)
{

	char need_help = !strcmp(argv[0],"-h")||!strcmp(argv[0],"-help");
	if(argc !=0||need_help)
	{
		
		printf("usage: RecvWriteNor\n\
			Atteion : need to be used in conjunction with client process: send_and_write_file_to_norflash]\n\
			eg : \n\
			board: RecvWriteNor\n\
			linux computer: send_and_write_file_to_norflash [file name] [deviceIP]\n");
		return 0;
	}

	int sockfd;
	int new_fd;//建立连接后会返回一个新的fd
	struct sockaddr_in sever_addr; //服务器的IP地址
	struct sockaddr_in client_addr; //客户机的IP地址
	char *buffer = (char*)malloc(ERRASE_SIZE);
	if(NULL == buffer)
	{
		perror("malloc failed!\n");
		return -1;
	}
	char *p_buffer = buffer;
	memset(buffer,0,ERRASE_SIZE);
	int nbyte;
	int checkListen;
	unsigned int filesize = 0;
	unsigned int countbytes = 0;
	
	/***为了消除accept函数第3个参数的类型不匹配问题的警告***********/
	int sockaddr_size = sizeof(struct sockaddr);
	/******************************************************/
	
	//1.创建套接字
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		printf("create socket error!\n");
		return -1;
	}
	printf("create socket success!\n");

	//2.1设置要绑定的服务器地址
	bzero(&sever_addr,sizeof(struct sockaddr_in));
	sever_addr.sin_family = AF_INET;
	sever_addr.sin_port = htons(portnum);//将主机字节序转换成网络字节序
	sever_addr.sin_addr.s_addr = htonl(INADDR_ANY);//绑定任意的IP地址,要和网络上所有的IP地址通讯
	
	
	//2.2绑定地址
	if(bind(sockfd,(struct sockaddr*)&sever_addr,sizeof(struct sockaddr)) < 0)
	{
		printf("bind socket error!\n");
		return -1;
	}
	printf("bind socket success!\n");
	
	//3.监听端口
	printf("into listen portnum(%d)......!\n",portnum);
	checkListen = listen(sockfd,5);
	if(checkListen < 0)
	{
		perror("socket listen error!\n");
		return -1;
	}
	
	do
	{
		//4.等待连接
		new_fd = accept(sockfd,(struct sockaddr*)(&client_addr),(socklen_t *)(&sockaddr_size));
		if(new_fd<0)
		{
			printf("accept eror!\n");
			return -1;
		}
		printf("sever get connection from %s\n",inet_ntoa(client_addr.sin_addr.s_addr));
		
		//5.接收文件大小信息
		recv(new_fd,&filesize,sizeof(filesize),0);
		printf("receive file size = %ld bytes\n",filesize);
		if(filesize <= 0)return -1;

		//5.1接收数据
		while(1)
		{
			if(countbytes >= filesize)break;
			nbyte = recv(new_fd,p_buffer+countbytes,filesize - countbytes,0);
			countbytes = countbytes + nbyte;
			//printf("countbytes = %d bytes...\n",countbytes);
			
		}
		printf("success ! server received (%d)bytes!\n",countbytes);

	
	}while(0);

	/*****debug code ***/
	#if 0
		int tmp_file = open("/jffs0/tmp.bin", O_RDWR| O_CREAT,0660);
		if( tmp_file < 0)
		{
			
			perror("open read_file  error !\n");
			return -1;
		}
		printf("open read_file  success !\n");

	//debug
		printf("receive:%s \n",buffer);
		unsigned int tmp_ret = write(tmp_file, buffer, countbytes);
		if(tmp_ret < 0)
		{
			perror("write file error!\n");
			return -1;
		}
		printf("write file success! write size(%ld)bytes! \n",tmp_ret);

	#endif

	/*******************/
#if 1
	/*擦除NorFlash*/
	if(countbytes != filesize)
	{
		printf("countbytes != filesize\n");
		return -1;
	}

	printf("erase NorFlash......\n");
	int ret = hispinor_erase(FLASH_START_ADDRESS, ERRASE_SIZE);

	/*写NorFlash*/
	printf("write NorFlash......\n");
	ret = hispinor_write(buffer, FLASH_START_ADDRESS,countbytes);
	if(0 == ret)
	{
		printf("write NroFlash success ,write(%d)bytes!\n",countbytes);
	}
	else
	{
		perror("write NroFlash failed !\n");
	}

#endif

	close(new_fd);
	close(sockfd);
	free(buffer);

	return 0;
}
#ifndef WRITE_FILE_TO_FLASH_H
#define WRITE_FILE_TO_FLASH_H



#define FLASH_START_ADDRESS 0x100000   //liteOS写OS和app的起始地址
#define ERRASE_SIZE   (7*1024*1024)		   //擦除7M大小的空间


int  write_file_to_nor_flash(int argc,char**argv);
int  receive_and_write_file_to_nor_flash(int argc,char**argv);


#endif
  • linux主机端代码:

/************************************************************************
*文件名:send_and_write_file_to_norflash.c
*创建者:spy_007
*创见时间:2018/10/11
*文件说明:
功能:发送文件到给设备:client端程序
	专门烧写系统文件(ipc18.bin)用,提高开发调试速度,比ftp传输文件
	再烧写的方式要快,因接收的数据不保存成文件,而是直接从内存写入norflash
使用:配合设备端(服务端)命令 “RecvWriteNor” 使用
	1.设备端运行命令“RecvWriteNor”等待接收数据;
	2.虚拟机(linux主机)下运行客户端程序 send_and_write_file_to_norflash
		格式:send_and_write_file_to_norflash [file name] [deviceIP]
		eg: ./send_and_write_file_to_norflash ipc18.bin 192.168.3.82
注意:目前没有加入文件校验机制
************************************************************************/

#include//不加会报隐式声明与内建函数'exit'不兼容
#include
#include
#include
#include//因用了地址

#include 
#include 
#include 




//3333是主机字节序
#define portnum  5555

#define ERRASE_SIZE   (7*1024*1024)		   //文件缓存空间大小

int main(int argc,char**argv)
{
	if(argc < 3)
	{
		printf("usage:%s [filename] [device ip]\n",argv[0]);
		return -1;
	}
	int sockfd,checkConnect;
	struct sockaddr_in sever_addr; //服务器的IP地址
	
	//1.创建套接字
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		printf("create socket error!\n");
		exit(1);
	}
	
	//2.1设置需要连接的服务器地址
	bzero(&sever_addr,sizeof(struct sockaddr_in));
	sever_addr.sin_family = AF_INET;
	sever_addr.sin_port = htons(portnum);//host to net  (short) 先要将主机字节序转换成网络字节序
	sever_addr.sin_addr.s_addr =  inet_addr(argv[2]);//绑定IP地址
	
	
	//2.2连接服务器
	checkConnect = connect(sockfd,(struct sockaddr*)(&sever_addr),sizeof(struct sockaddr));
	if(checkConnect < 0)
	{
		printf("connect error!\n");
		exit(1);
	}
	
	
	/*分配缓存空间*/
	char * read_buffer = (char*)malloc(ERRASE_SIZE);
	if(NULL == read_buffer)
	{
		perror("malloc failed !\n");
		return -1;
	}
	memset(read_buffer,0,ERRASE_SIZE);
	
	//打开文件
	int read_file = open((const char *)argv[1], O_RDONLY);
	if( read_file < 0)
	{
		
		printf("open %s  error !\n",argv[1]);
		return -1;
	}
	
	/*读取文件至缓存空间*/
	unsigned int size = read(read_file,read_buffer,ERRASE_SIZE);
	printf("read size = %d bytes\n",size);
	
	//发送文件大小信息
	unsigned int  size_bak = size;
	printf("sizeof(unsigned long) = %d\n",sizeof(unsigned long));
	if(send(sockfd,&size_bak,sizeof(size_bak),0) < 0)
	{
		perror("send file size failed!\n");
		return -1;
	}
	printf("send file size success!\n");
	
	//3.发送数据到服务器
	int countbytes = 0;
	int sendbytes = 0;
	usleep(100);
	while(1)
	{
		if(0 == size) break;
		
		while(1)
		{
			sendbytes  = send(sockfd,read_buffer + countbytes,size,0);
			if(sendbytes < 0)
			{
				perror("send failed!\n");
				return -1;
			}
			
			break;
		}
	
		countbytes = countbytes + sendbytes;
		printf("countbytes = %d\n",countbytes);
		size = size - countbytes;
		usleep(100);
		
	}
	printf("success send(%ld)bytes!\n",countbytes);
	
	
	//4.关闭连接
	close(sockfd);
	free(read_buffer);
	return 0;
	
}

这里就举例其中一个命令“RecvWriteNor”的使用:

  • 设备端先输入命令进入监听模式:

  • 之后linux端运行: ./send_and_write_file_to_norflash ipc18.bin 192.XXX.XXX.XXX

设备端将自动接收文件并写入到Norflash对应地址处(注意 IP得在同一网段且互相能ping通)。

success!

你可能感兴趣的:(LiteOS,Hi3516EV100,lite-ipc-app)