⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 linux 嵌入式原代码
💻 C
字号:
/* *  Sample program for FR400 Companion Chip I2C axLinux driver. *   *  Copyright (C) 2002  AXE,Inc. * */#include <stdio.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <linux/fr400cc_i2c.h>#define CFGCHK		1	/* 2002/Dec/20 */#define OPTCHK		1	/* 2002/Dec/19 */#define SEND_RECV		1#define I2C_REPEAT_START	1#define CH1			1#if CFGCHKstatic int v16 = 0;#elsestatic int verb = 0;#endifstatic voidhelp(){	printf("--help , -help , -?\n");	printf("-colorbar\n");	printf("-nocolorbar\n");	printf("-nonblock N (N=0|1 , default:1\n");	printf("-block ( == -nonblock 0)\n");	printf("-test-req-sbuf\n");#if I2C_REPEAT_START	printf("-rd-reg <slave addr> <sub addr>\n");	printf("-wt-reg <slave addr> <sub addr> <value>\n");#endif#if CFGCHK	printf("-v16\n");	printf("-v\n");#else	printf("-ver, -verbose\n");#endif}static intopt_chk(int ac, char **av, char *key){	int i;	for(i=1; i<ac; i++){		if(strcmp(av[i], key) == 0) return i;	}	return 0;}static voidopt_chk_str(int ac, char **av, char *key, char **re){	int i;	i = opt_chk(ac, av, key);	if(i!=0 && i+1<ac){		*re = av[i+1];	}}static intint_get(char *s){	int v;	if(strncmp(s, "0x", 2) == 0){		sscanf(s, "0x%x", &v);		return v;	}	sscanf(s, "%d", &v);	return v;}static voidopt_chk_int(int ac, char **av, char *key, int *re){	int i;	i = opt_chk(ac, av, key);	if(i!=0 && i+1<ac){		*re = int_get(av[i+1]);	}}static voidopt_chk_int2(int ac, char **av, char *key, int *re1, int *re2){	int i;	i = opt_chk(ac, av, key);	if(i!=0 && i+2<ac){		*re1 = int_get(av[i+1]);		*re2 = int_get(av[i+2]);	}}static voidopt_chk_int3(int ac, char **av, char *key, 	     int *re1, int *re2, int *re3){	int i;	i = opt_chk(ac, av, key);	if(i!=0 && i+3<ac){		*re1 = int_get(av[i+1]);		*re2 = int_get(av[i+2]);		*re3 = int_get(av[i+3]);	}}#if CFGCHKstatic int verbose = 0;static voidconfig_show(struct fr400i2c_config *cfg){	printf("addr=%02x mss=%d hsm=%d cs=0x%08x bufsz=%d\n",		(unsigned)cfg->addr,	       cfg->mss,	       cfg->hsm,	       (unsigned)cfg->cs,	       cfg->bufsz);}static intioctl_start(int fd, int start_cmd, void *prm){	if(verbose){		struct fr400i2c_config cfg;		if(ioctl(fd, I2CIOCGCFG, &cfg) != 0){			fprintf(stderr, "ioctl get cfg err\n");			return -1;		}		config_show(&cfg);	}	return ioctl(fd, start_cmd, prm);}#endif /* CFGCHK */static void *mmap_fd(int fd, int bufsz){	void *start;	int length, prot, flags, offset;	start = NULL;	length = bufsz;	prot = PROT_READ | PROT_WRITE;	flags = MAP_SHARED;	offset = 0;	return mmap(start, length, prot, flags, fd, offset);}#if I2C_REPEAT_STARTstatic char *err_msg(int kind){	switch(kind){	case FR400CC_I2C_RCOUNT_ERR_DETECT_BUSERR:		return "bus error";	case FR400CC_I2C_RCOUNT_ERR_DETECT_STOP_COND:		return "detect stop condition error";	case FR400CC_I2C_RCOUNT_ERR_DETECT_RSTART_COND:		return "detect rstart condition error";	case FR400CC_I2C_RCOUNT_ERR_DETECT_ARBITO_LOST:		return "detect arbito lost error";	case FR400CC_I2C_RCOUNT_ERR_DETECT_NACK:		return "detect nack error";	}	return "???";}static intrd_work(int fd, int nonblock, struct fr400i2c_read *rinf){	fd_set setr;	int run, ret;	int i, n, x;	run = 1;	while(run){		if(nonblock){			FD_ZERO(&setr);			FD_SET(fd, &setr);			x = select(fd+1, &setr, NULL, NULL, NULL);			if(x <= 0 || !FD_ISSET(fd, &setr)) continue;		}		if(read(fd, (void*)rinf, sizeof(*rinf)) <= 0) continue;		run = 0;	}	return 0;}#if 1 /* test */static intrd_reg_work3(	int fd, int nonblock,	int slave_addr, int subaddr, 	struct fr400i2c_config *cfg,	char *buf){	struct fr400i2c_master mst;	struct fr400i2c_sbuf sbuf;	struct fr400i2c_read rinf;	int i;	bzero(&mst, sizeof(mst));	mst.addr = slave_addr;	mst.bytes = 16;	sbuf.offset = 0;	sbuf.bytes = 16;	if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){		fprintf(stderr, "err ioctl sbuf\n");		goto err;	}#if CFGCHK	if(ioctl_start(fd, I2CIOCRECV, &mst) != 0){#else	if(ioctl(fd, I2CIOCRECV, &mst) != 0){#endif		fprintf(stderr, "err ioctl send\n");		goto err;	}	if(rd_work(fd, nonblock, &rinf) != 0){		fprintf(stderr, "err rd_work\n");		goto err;	}	switch(rinf.type){	case FR400CC_I2C_RTYPE_TRANS_FIN:		break;	case FR400CC_I2C_RTYPE_REQ_SBUF:		fprintf(stderr, "req_sbuf ??\n");		goto err;	case FR400CC_I2C_RTYPE_ERR:		fprintf(stderr, "err <0x%x> %s\n", rinf.count,			err_msg(rinf.count));		goto err;	}	for(i=0; i<sbuf.bytes; i++){		printf("%02x ", ((unsigned char *)buf)[sbuf.offset+i]);	}	printf("\n");	close(fd);	return 0;err:	close(fd);	return -1;}#endif#if SEND_RECVstatic intrd_reg_work_send_recv(	int fd, int nonblock,	int slave_addr, int subaddr, 	struct fr400i2c_config *cfg,	char *buf){	struct fr400i2c_send_recv prm;	struct fr400i2c_master mst;	struct fr400i2c_sbuf sbuf;	struct fr400i2c_read rinf;	int i;	bzero(&prm, sizeof(prm));	prm.mst_send.addr = slave_addr;	buf[0] = subaddr;	prm.mst_send.bytes = 1;	prm.sbuf_send.offset = 0;	prm.sbuf_send.bytes = prm.mst_send.bytes;	prm.mst_recv.addr = slave_addr;	prm.mst_recv.bytes = 1;#if CFGCHK	if(v16){#else	if(verb){#endif		prm.mst_recv.bytes = 16;	}	prm.sbuf_recv.offset = 1;	prm.sbuf_recv.bytes = prm.mst_recv.bytes;#if CFGCHK	if(ioctl_start(fd, I2CIOCSEND_RECV, &prm) != 0){#else	if(ioctl(fd, I2CIOCSEND_RECV, &prm) != 0){#endif		fprintf(stderr, "err ioctl send_recv\n");		goto err;	}	if(rd_work(fd, nonblock, &rinf) != 0){		fprintf(stderr, "err rd_work\n");		goto err;	}	switch(rinf.type){	case FR400CC_I2C_RTYPE_TRANS_FIN:		break;	case FR400CC_I2C_RTYPE_REQ_SBUF:		fprintf(stderr, "req_sbuf ??\n");		goto err;	case FR400CC_I2C_RTYPE_ERR:		fprintf(stderr, "err <0x%x> %s\n", rinf.count,			err_msg(rinf.count));		goto err;	}	printf("slave_addr 0x%02x , subaddr 0x%02x value ", slave_addr, subaddr);	for(i=0; i<prm.sbuf_recv.bytes; i++){		printf("%02x ", ((unsigned char *)buf)[prm.sbuf_recv.offset+i]);	}	printf("\n");	close(fd);	return 0;err:	close(fd);	return -1;}#endif#if SEND_RECV/* cut */#elsestatic intrd_reg_work(	int fd, int nonblock,	int slave_addr, int subaddr, 	struct fr400i2c_config *cfg,	char *buf){	struct fr400i2c_master mst;	struct fr400i2c_sbuf sbuf;	struct fr400i2c_read rinf;	int i;	bzero(&mst, sizeof(mst));	mst.addr = slave_addr;	buf[0] = subaddr;	mst.bytes = 1;	mst.no_stop_cond = 1;	mst.repeat_start = 0;	sbuf.offset = 0;	sbuf.bytes = 1;	if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){		fprintf(stderr, "err ioctl sbuf\n");		goto err;	}#if CFGCHK	if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else	if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif		fprintf(stderr, "err ioctl send\n");		goto err;	}	if(rd_work(fd, nonblock, &rinf) != 0){		fprintf(stderr, "err rd_work\n");		goto err;	}	switch(rinf.type){	case FR400CC_I2C_RTYPE_TRANS_FIN:		break;	case FR400CC_I2C_RTYPE_REQ_SBUF:		fprintf(stderr, "req_sbuf ??\n");		goto err;	case FR400CC_I2C_RTYPE_ERR:		fprintf(stderr, "err <0x%x> %s\n", rinf.count,			err_msg(rinf.count));		goto err;	}	/**/	mst.bytes = 1;	mst.no_stop_cond = 0;	mst.repeat_start = 1;	sbuf.offset = 1;	sbuf.bytes = mst.bytes;	if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){		fprintf(stderr, "err ioctl sbuf\n");		goto err;	}#if CFGCHK	if(ioctl_start(fd, I2CIOCRECV, &mst) != 0){#else	if(ioctl(fd, I2CIOCRECV, &mst) != 0){#endif		fprintf(stderr, "err ioctl send\n");		goto err;	}	if(rd_work(fd, nonblock, &rinf) != 0){		fprintf(stderr, "err rd_work\n");		goto err;	}	switch(rinf.type){	case FR400CC_I2C_RTYPE_TRANS_FIN:		break;	case FR400CC_I2C_RTYPE_REQ_SBUF:		fprintf(stderr, "req_sbuf ??\n");		goto err;	case FR400CC_I2C_RTYPE_ERR:		fprintf(stderr, "err <0x%x> %s\n", rinf.count,			err_msg(rinf.count));		goto err;	}	printf("slave_addr 0x%02x , subaddr 0x%02x value 0x%02x\n",	       slave_addr, subaddr, ((unsigned char *)buf)[1]);	close(fd);	return 0;err:	close(fd);	return -1;}#endifstatic intwt_reg_work(	int fd, int nonblock,	int slave_addr, int subaddr, int value,	struct fr400i2c_config *cfg,	char *buf){	struct fr400i2c_master mst;	struct fr400i2c_sbuf sbuf;	struct fr400i2c_read rinf;	bzero(&mst, sizeof(mst));	mst.addr = slave_addr;	buf[0] = subaddr;	buf[1] = value;	mst.bytes = 2;	sbuf.offset = 0;	sbuf.bytes = 2;	if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){		fprintf(stderr, "err ioctl sbuf\n");		goto err;	}#if CFGCHK	if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else	if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif		fprintf(stderr, "err ioctl send\n");		goto err;	}	if(rd_work(fd, nonblock, &rinf) != 0){		fprintf(stderr, "err rd_work\n");		goto err;	}	switch(rinf.type){	case FR400CC_I2C_RTYPE_TRANS_FIN:		break;	case FR400CC_I2C_RTYPE_REQ_SBUF:		fprintf(stderr, "req_sbuf ??\n");		goto err;	case FR400CC_I2C_RTYPE_ERR:		fprintf(stderr, "err <0x%x> %s\n", rinf.count,			err_msg(rinf.count));		goto err;	}	close(fd);	printf("(^_^)/~~~\n");	return 0;err:	close(fd);	return -1;}#endif /* I2C_REPEAT_START */#if OPTCHKstatic char *opt_list[] = {"-help", "help", "?",#if CFGCHK"v16", "v",#else"ver", "verbose",#endif"colorbar","nocolorbar","test-req-sbuf","nonblock", "block","rd-reg", "wt-reg","type3", "ch1",};static intoptchk_top(int ac, char **av){	int i, j, n, ret;	ret = 0;	n = sizeof(opt_list) / sizeof(opt_list[0]);	for(i=1; i<ac; i++){		if(av[i][0] != '-') continue;		if('0' <= av[i][1] && av[i][1] <= '9') continue;		for(j=0; j<n; j++){			if(strcmp(&av[i][1], opt_list[j]) == 0) break;		}		if(j<n) continue;		fprintf(stderr, "ignore option '%s' ?\n", av[i]);		ret = -1;	}	return ret;}#endif /* OPTCHK */main(int ac, char **av){	int nonblock, colorbar;	int fd, open_flag;	struct fr400i2c_config cfg;	char *buf;	int subaddr, run, x, n, i;	struct fr400i2c_read rinf[100];#if CH1	char dev_name[32];#endif#if I2C_REPEAT_START	int rd_reg, wt_reg, slave_addr, value;#else	struct fr400i2c_master mst;	struct fr400i2c_sbuf sbuf;	fd_set setr;	int test_req_sbuf;#endif#if OPTCHK	if(optchk_top(ac,av) != 0) return -1;#endif#if CFGCHK	verbose = (opt_chk(ac,av, "-v") != 0);#endif	if(opt_chk(ac,av,"--help") != 0 ||	   opt_chk(ac,av,"-help") != 0 ||	   opt_chk(ac,av,"-?") != 0){		help();		return 0;	}#if CFGCHK	v16 = (opt_chk(ac,av,"-v16") != 0);#else	verb = opt_chk(ac,av,"-ver") | opt_chk(ac,av,"-verbose");#endif	colorbar = opt_chk(ac, av, "-colorbar");	if(opt_chk(ac, av, "-nocolorbar")) colorbar = 0;#if I2C_REPEAT_START#else	test_req_sbuf = opt_chk(ac, av, "-test-req-sbuf");#endif	nonblock = 1;	opt_chk_int(ac, av, "-nonblock", &nonblock);	if(nonblock == 1 && opt_chk(ac, av, "-block") != 0){		nonblock = 0;	}#if I2C_REPEAT_START	rd_reg = 0;	slave_addr = -1;	opt_chk_int2(ac, av, "-rd-reg", &slave_addr, &subaddr);	if(slave_addr != -1){		rd_reg = 1;		if(opt_chk(ac, av, "-type3")) rd_reg = 3;	}else{		wt_reg = 0;		opt_chk_int3(ac, av, "-wt-reg", &slave_addr, &subaddr, &value);		if(slave_addr != -1){			wt_reg = 1;			rd_reg = 0;		}	}#endif /* I2C_REPEAT_START */	/**/	open_flag = O_RDONLY;	if(nonblock) open_flag |= O_NONBLOCK;#if CH1	sprintf(dev_name, "/dev/fr400cc_i2c%d", 		opt_chk(ac,av,"-ch1") ? 1 : 0);	if((fd = open(dev_name, open_flag)) < 0){#else	if((fd = open("/dev/fr400cc_i2c0", open_flag)) < 0){#endif		fprintf(stderr, "fd=%d\n", fd);		return -1;	}	if(ioctl(fd, I2CIOCGCFG, &cfg) != 0){		fprintf(stderr, "err ioctl get cfg\n");		close(fd);		return -1;	}	if((buf = mmap_fd(fd, cfg.bufsz)) == (void*)-1){		fprintf(stderr, "err mmap\n");		close(fd);		return -1;	}#if 0	cfg.addr = 	cfg.mss = 	cfg.hsm = 	cfg.cs = #endif#if CH1	cfg.mss = 1;#endif	if(ioctl(fd, I2CIOCSCFG, &cfg) != 0){		fprintf(stderr, "err ioctl set cfg\n");		close(fd);		return -1;	}#if I2C_REPEAT_START	switch(rd_reg){#if SEND_RECV	case 1: return rd_reg_work_send_recv(fd, nonblock, #else	case 1: return rd_reg_work(fd, nonblock, #endif				   slave_addr, subaddr,				   &cfg, buf);	case 3: return rd_reg_work3(fd, nonblock, 				   slave_addr, subaddr,				   &cfg, buf);	}	if(wt_reg){		return wt_reg_work(fd, nonblock,				   slave_addr, subaddr, value,				   &cfg, buf);	}	return wt_reg_work(fd, nonblock,			   0x88, 2, 			   colorbar ? (1<<3) : 0,			   &cfg, buf);#else /* I2C_REPEAT_START */	/* --> FJDL7654-01 */	mst.addr = 0x88; /* target slave */	subaddr = 2; /* CR0 */	buf[0] = subaddr; 	buf[1] = 0;	if(colorbar){		buf[1] |= (1<<3); /* CR0[3] Color Bar */	}	mst.bytes = 2;	/* <-- FJDL7654-01 */	sbuf.offset = 0;	if(test_req_sbuf){		sbuf.bytes = 1; /* == mst.bytes */	}else{		sbuf.bytes = 2; /* == mst.bytes (all at once) */	}	if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){		fprintf(stderr, "err ioctl sbuf \n");		close(fd);		return -1;	}#if CFGCHK	if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else	if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif		fprintf(stderr, "err ioctl send \n");		close(fd);		return -1;	}	run = 1;	while(run){		if(nonblock){			FD_ZERO(&setr);			FD_SET(fd, &setr);			x = select(fd+1, &setr, NULL, NULL, NULL);			if(x <= 0 || !FD_ISSET(fd, &setr)) continue;		}		if((x = read(fd, (void*)rinf, sizeof(rinf))) < 0) continue;		n = x / sizeof(rinf[0]);		for(i=0; i<n; i++){			printf("rinf[%d].type=%d count=%d\n",				i, rinf[i].type, rinf[i].count);			switch(rinf[i].type){			case FR400CC_I2C_RTYPE_TRANS_FIN:				run = 0;				break;			case FR400CC_I2C_RTYPE_REQ_SBUF:				if(test_req_sbuf){					fprintf(stderr, "application get sbuf req\n");					sbuf.offset = 1;					sbuf.bytes = 1;					if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){						fprintf(stderr, "err ioctl sbuf 2\n");						close(fd);						return -1;					}				}				break;			}		}	}	printf("(^_^)/~~~\n");	close(fd);	return 0;#endif /* I2C_REPEAT_START */}/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -