OpenCores
URL https://opencores.org/ocsvn/tinyvliw8/tinyvliw8/trunk

Subversion Repositories tinyvliw8

[/] [tinyvliw8/] [trunk/] [tools/] [bin2hex/] [src/] [main.c] - Rev 7

Compare with Previous | Blame | View Log

/**
 * \file   main.c
 * \author Oliver Stecklina <stecklina@ihp-microelectronics.com>
 * \date   25.07.2013
 * 
 * \brief  Binary to hex copy program for the tinyVLIW8 processor.
 *
 * <p>
 *    Copyright (C) 2015 IHP GmbH, Frankfurt (Oder), Germany
 *
 * This code is free software. It is licensed under the EUPL, Version 1.1
 * or - as soon they will be approved by the European Commission - subsequent
 * versions of the EUPL (the "License").
 * You may redistribute this code and/or modify it under the terms of this
 * License.
 * You may not use this work except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl/licence-eupl
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * </p>
 */
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
 
typedef enum _mem_width_e {
	_mem_width_8bit = 0,
	_mem_width_16bit,
	_mem_width_32bit
} _mem_width_t;
 
static char         *_infile     = NULL;
static _mem_width_t  _mem_width  = _mem_width_32bit;
static unsigned int  _start_addr = 0x0000;
static char         *_outfile    = NULL;
static unsigned char _ascii      = 0;
 
static int _parse_args(int argc, char *argv[])
{
	int err, i;
 
	err = 0;
	for (i = 1; 0 == err && i < argc; i++) {
		if ('-' != *argv[i]) {
			if ((i + 1) == argc) {
				_infile = argv[i];
				break;
			}
 
			fprintf(stderr, "\tERROR! bad option <%s>\n", argv[i]);
			err = -EINVAL;
 
			break;
		}
 
		switch (*(argv[i] + 1)) {
		case 'a':
			_ascii = 1;
			break;
		case 'o':
			if ((i + 1) < argc) {
				i++;
				_outfile = argv[i];
 
				break;
			}
 
			fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
			        argv[i]);
			err = -EINVAL;
 
			break;
		case 's':
			if ((i + 1) < argc) {
				long num;
 
				i++;
				num = strtol(argv[i], NULL, 0);
				if (0 <= num && 0x10000 > num) {
					_start_addr = num;
				} else {
					fprintf(stderr, "\tERROR! bogus start address\n");
					err = -ERANGE;
				}
 
				break;
			}
 
			fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
			        argv[i]);
			err = -EINVAL;
 
			break;
		case 'w':
			if ((i + 1) < argc) {
				long num;
 
				i++;
				num = strtol(argv[i], NULL, 0);
				switch (num) {
				case 8:
					_mem_width = _mem_width_8bit;
					break;
				case 16:
					_mem_width = _mem_width_16bit;
					break;
				case 32:
					_mem_width = _mem_width_32bit;
					break;
				default:
					fprintf(stderr, "\tERROR! invalid memory width\n");
					err = -ERANGE;
				}
 
				break;
			}
 
			fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
			        argv[i]);
			err = -EINVAL;
 
			break;
		case 'h':
			printf("%s [option] <input>\n", argv[0]);
			printf("\t-a           ascii input\n");
			printf("\t-o <file>    output filename (default: stdout)\n");
			printf("\t-s <num>     start address (default: 0x0000)\n");
			printf("\t-w [8|16|32] memory width in bit (default: 32)\n");
			printf("\t-h           useful help\n");
 
			exit(0);
		}
	}
 
	if (0 == err && NULL == _infile) {
		fprintf(stderr, "\tERROR! no input file given\n");
		err = -EINVAL;
	}
 
	return err;
}
 
static unsigned char _mem_width2byte(const _mem_width_t mwidth)
{
	unsigned char width;
 
	switch (mwidth) {
	case _mem_width_8bit:
		width = 1;
		break;
	case _mem_width_16bit:
		width = 2;
		break;
	case _mem_width_32bit:
		width = 4;
		break;
	}
 
	return width;
}
 
static char *_asci2bin(char *img, unsigned int *size_ptr)
{
	unsigned int i, j, k;
	unsigned char c;
	char *p;
 
	for (i = 0, j = 0, k = 7, c = 0; i < *size_ptr; i++) {
		switch (*(img + i)) {
		case '0':
			break;
		case '1':
			c |= 1 << k;
			break;
		default:
			/* ignore */
			continue;
		}
 
		if (0 == k) {
			/* move char to buffer */
			*(img + j) = c;
 
			/* reset bit pos and char */
			k = 7;
			c = 0;
 
			/* increment pos in output buffer */
			j++;
		} else
			k--;
	}
 
	if (7 != k) {
		fprintf(stderr, "\tWARNING! input is not byte aligned.\n");
 
		*(img + j) = c;
		j++;
	}
 
	p = NULL;
	*size_ptr = j;
 
	if (0 < j) {
		p = malloc(j);
		if (NULL != p)
			memcpy(p, img, j);
	}
 
	free(img);
 
	return p;
}
 
static char *_load_image(const char *filename, unsigned int *size_ptr,
                         const unsigned char ascii, const _mem_width_t mwidth)
{
	char *img;
	int err;
 
	img = NULL;
	err = open(filename, O_RDONLY);
	if (0 <= err) {
		struct stat s;
		int fd;
 
		fd = err;
 
		err = fstat(fd, &s);
		if (0 == err) {
			img = malloc(s.st_size);
			if (NULL != img) {
				unsigned int done;
 
				done = 0;
				do {
					err = read(fd, img + done, s.st_size - done);
					if (0 > err) {
						err = -errno;
						if (-EINTR == err) {
							err = 0;
							continue;
						}
 
						break;
					}
 
					done += err;
					err = 0;
				} while (0 == err && done < s.st_size);
 
				if (0 == err) {
					unsigned int size;
 
					size = s.st_size;
					if (0 != ascii) {
						img = _asci2bin(img, &size);
					}
 
					if (0 != (s.st_size & (_mem_width2byte(mwidth) - 1))) {
						fprintf(stderr, "\tWARNING! input size does not match with memory width\n");
					}
 
					*size_ptr = size;
				} else {
					free(img);
					img = NULL;
				}
			} else
				err = -ENOMEM;
		} else
			err = -errno;
 
		close(fd);
	} else
		err = -errno;
 
	if (0 != err)
		fprintf(stderr, "\tERROR! loading input file <%s>", filename);
 
	return img;
}
 
#define _BUFSIZ ((16 << 1) + 4 + 2 + 2 + 2 + 1 + 1 + 1)
 
static int _ihex_out(const int fd, const unsigned short addr, const char *data,
                     const unsigned int len)
{
	unsigned int j, i;
	char buf[_BUFSIZ];
	int err;
 
	if (0 < len) {
		unsigned char chksum;
 
		chksum = 0;
 
		i = snprintf(&buf[0], _BUFSIZ, ":%02x%04x00", len, addr);
		if (_BUFSIZ < i)
			return -ENOSPC;
 
		for (j = 0; j < len; j++) {
			i += snprintf(&buf[i], _BUFSIZ - i, "%02x", (unsigned char) *(data + j));
			if (_BUFSIZ < i)
				return -ENOSPC;
 
			chksum += *(data + j);
		}
 
		chksum += len;
		chksum += addr & 0x00ff;
		chksum += addr >> 8;
 
		chksum = (chksum ^ 0xff) + 0x01;
		i += snprintf(&buf[i], _BUFSIZ - i, "%02x\n", chksum);
		if (_BUFSIZ < i)
			return -ENOSPC;
	} else
		i = snprintf(&buf[0], _BUFSIZ, ":00000001ff\n");
 
	j = 0;
	do {
		err = write(fd, &buf[j], i - j);
		if (0 > err) {
			err = -errno;
			if (-EINTR == err) {
				err = 0;
				continue;
			}
 
			break;
		}
 
		j += err;
		err = 0;
	} while (0 == err && j < i);
 
	return err;
}
 
static int _out_image(const char *image, const unsigned int size,
                      const _mem_width_t mwidth, const char *outfile)
{
	int err;
 
	if (NULL != outfile) {
		err = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
		if (0 > err)
			err = -errno;
	} else
		err = fileno(stdout);
 
	if (0 <= err) {
		const unsigned int offset = _mem_width2byte(mwidth);
 
		unsigned short addr;
		unsigned int i;
		int fd;
 
		fd = err;
 
		addr = _start_addr;
		i = 0;
		do {
			char buf[4];
 
			memset(&buf[0], 0x00, offset);
			memcpy(&buf[0], &image[i], 
			       ((size - i) < offset) ? (size - i) : offset);
 
			err = _ihex_out(fd, addr, &image[i], offset);
 
			i += offset;
			addr += 1;
		} while (0 == err && i < size);
 
		/* finish line */
		if (0 == err)
			err = _ihex_out(fd, 0x00, NULL, 0);
 
		if (fd != fileno(stderr))
			close(fd);
	}
 
	if (0 != err)
		fprintf(stderr, "\tERROR! dump image failed\n");
 
	return err;
}
 
int main(int argc, char *argv[])
{
	int err;
 
	err = _parse_args(argc, argv);
	if (0 == err) {
		unsigned int size;
		char *img;
 
		img = _load_image(_infile, &size, _ascii, _mem_width);
		if (img) {
			err = _out_image(img, size, _mem_width, _outfile);
 
			free(img);
		} else
			err = -EIO;
	}
 
	return err;
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.