华为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位置:
其中擦写的起始地址和大小可通过宏来改变:
#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
/************************************************************************
*文件名: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”的使用:
设备端将自动接收文件并写入到Norflash对应地址处(注意 IP得在同一网段且互相能ping通)。
success!