Line 1... |
Line 1... |
/**
|
/**
|
|
|
* \file main.c
|
* \file main.c
|
|
|
* \date 25.07.2013
|
|
|
|
* \author Oliver Stecklina <stecklina@ihp-microelectronics.com>
|
* \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/types.h>
|
|
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
|
|
#include <fcntl.h>
|
#include <fcntl.h>
|
|
|
#include <unistd.h>
|
#include <unistd.h>
|
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
|
|
#include <string.h>
|
#include <string.h>
|
|
|
#include <errno.h>
|
#include <errno.h>
|
|
|
|
|
|
|
typedef enum _mem_width_e {
|
typedef enum _mem_width_e {
|
|
|
_mem_width_8bit = 0,
|
_mem_width_8bit = 0,
|
|
|
_mem_width_16bit,
|
_mem_width_16bit,
|
|
|
_mem_width_32bit
|
_mem_width_32bit
|
|
|
} _mem_width_t;
|
} _mem_width_t;
|
|
|
|
|
|
|
static char *_infile = NULL;
|
static char *_infile = NULL;
|
|
|
static _mem_width_t _mem_width = _mem_width_32bit;
|
static _mem_width_t _mem_width = _mem_width_32bit;
|
|
|
static unsigned int _start_addr = 0x0000;
|
static unsigned int _start_addr = 0x0000;
|
|
|
static char *_outfile = NULL;
|
static char *_outfile = NULL;
|
|
|
static unsigned char _ascii = 0;
|
static unsigned char _ascii = 0;
|
|
|
|
|
|
|
static int _parse_args(int argc, char *argv[])
|
static int _parse_args(int argc, char *argv[])
|
|
|
{
|
{
|
|
|
int err, i;
|
int err, i;
|
|
|
|
|
|
|
err = 0;
|
err = 0;
|
|
|
for (i = 1; 0 == err && i < argc; i++) {
|
for (i = 1; 0 == err && i < argc; i++) {
|
|
|
if ('-' != *argv[i]) {
|
if ('-' != *argv[i]) {
|
|
|
if ((i + 1) == argc) {
|
if ((i + 1) == argc) {
|
|
|
_infile = argv[i];
|
_infile = argv[i];
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
fprintf(stderr, "\tERROR! bad option <%s>\n", argv[i]);
|
fprintf(stderr, "\tERROR! bad option <%s>\n", argv[i]);
|
|
|
err = -EINVAL;
|
err = -EINVAL;
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
switch (*(argv[i] + 1)) {
|
switch (*(argv[i] + 1)) {
|
|
|
case 'a':
|
case 'a':
|
|
|
_ascii = 1;
|
_ascii = 1;
|
|
|
break;
|
break;
|
|
|
case 'o':
|
case 'o':
|
|
|
if ((i + 1) < argc) {
|
if ((i + 1) < argc) {
|
|
|
i++;
|
i++;
|
|
|
_outfile = argv[i];
|
_outfile = argv[i];
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
|
|
argv[i]);
|
argv[i]);
|
|
|
err = -EINVAL;
|
err = -EINVAL;
|
|
|
|
|
|
|
break;
|
break;
|
|
|
case 's':
|
case 's':
|
|
|
if ((i + 1) < argc) {
|
if ((i + 1) < argc) {
|
|
|
long num;
|
long num;
|
|
|
|
|
|
|
i++;
|
i++;
|
|
|
num = strtol(argv[i], NULL, 0);
|
num = strtol(argv[i], NULL, 0);
|
|
|
if (0 <= num && 0x10000 > num) {
|
if (0 <= num && 0x10000 > num) {
|
|
|
_start_addr = num;
|
_start_addr = num;
|
|
|
} else {
|
} else {
|
|
|
fprintf(stderr, "\tERROR! bogus start address\n");
|
fprintf(stderr, "\tERROR! bogus start address\n");
|
|
|
err = -ERANGE;
|
err = -ERANGE;
|
|
|
}
|
}
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
|
|
argv[i]);
|
argv[i]);
|
|
|
err = -EINVAL;
|
err = -EINVAL;
|
|
|
|
|
|
|
break;
|
break;
|
|
|
case 'w':
|
case 'w':
|
|
|
if ((i + 1) < argc) {
|
if ((i + 1) < argc) {
|
|
|
long num;
|
long num;
|
|
|
|
|
|
|
i++;
|
i++;
|
|
|
num = strtol(argv[i], NULL, 0);
|
num = strtol(argv[i], NULL, 0);
|
|
|
switch (num) {
|
switch (num) {
|
|
|
case 8:
|
case 8:
|
|
|
_mem_width = _mem_width_8bit;
|
_mem_width = _mem_width_8bit;
|
|
|
break;
|
break;
|
|
|
case 16:
|
case 16:
|
|
|
_mem_width = _mem_width_16bit;
|
_mem_width = _mem_width_16bit;
|
|
|
break;
|
break;
|
|
|
case 32:
|
case 32:
|
|
|
_mem_width = _mem_width_32bit;
|
_mem_width = _mem_width_32bit;
|
|
|
break;
|
break;
|
|
|
default:
|
default:
|
|
|
fprintf(stderr, "\tERROR! invalid memory width\n");
|
fprintf(stderr, "\tERROR! invalid memory width\n");
|
|
|
err = -ERANGE;
|
err = -ERANGE;
|
|
|
}
|
}
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
|
|
|
argv[i]);
|
argv[i]);
|
|
|
err = -EINVAL;
|
err = -EINVAL;
|
|
|
|
|
|
|
break;
|
break;
|
|
|
case 'h':
|
case 'h':
|
|
|
printf("%s [option] <input>\n", argv[0]);
|
printf("%s [option] <input>\n", argv[0]);
|
|
|
printf("\t-a ascii input\n");
|
printf("\t-a ascii input\n");
|
|
|
printf("\t-o <file> output filename (default: stdout)\n");
|
printf("\t-o <file> output filename (default: stdout)\n");
|
|
|
printf("\t-s <num> start address (default: 0x0000)\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-w [8|16|32] memory width in bit (default: 32)\n");
|
|
|
printf("\t-h useful help\n");
|
printf("\t-h useful help\n");
|
|
|
|
|
|
|
exit(0);
|
exit(0);
|
|
|
}
|
}
|
|
|
}
|
}
|
|
|
|
|
|
|
if (0 == err && NULL == _infile) {
|
if (0 == err && NULL == _infile) {
|
|
|
fprintf(stderr, "\tERROR! no input file given\n");
|
fprintf(stderr, "\tERROR! no input file given\n");
|
|
|
err = -EINVAL;
|
err = -EINVAL;
|
|
|
}
|
}
|
|
|
|
|
|
|
return err;
|
return err;
|
|
|
}
|
}
|
|
|
|
|
|
|
static unsigned char _mem_width2byte(const _mem_width_t mwidth)
|
static unsigned char _mem_width2byte(const _mem_width_t mwidth)
|
|
|
{
|
{
|
|
|
unsigned char width;
|
unsigned char width;
|
|
|
|
|
|
|
switch (mwidth) {
|
switch (mwidth) {
|
|
|
case _mem_width_8bit:
|
case _mem_width_8bit:
|
|
|
width = 1;
|
width = 1;
|
|
|
break;
|
break;
|
|
|
case _mem_width_16bit:
|
case _mem_width_16bit:
|
|
|
width = 2;
|
width = 2;
|
|
|
break;
|
break;
|
|
|
case _mem_width_32bit:
|
case _mem_width_32bit:
|
|
|
width = 4;
|
width = 4;
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
return width;
|
return width;
|
|
|
}
|
}
|
|
|
|
|
|
|
static char *_asci2bin(char *img, unsigned int *size_ptr)
|
static char *_asci2bin(char *img, unsigned int *size_ptr)
|
|
|
{
|
{
|
|
|
unsigned int i, j, k;
|
unsigned int i, j, k;
|
|
|
unsigned char c;
|
unsigned char c;
|
|
|
char *p;
|
char *p;
|
|
|
|
|
|
|
for (i = 0, j = 0, k = 7, c = 0; i < *size_ptr; i++) {
|
for (i = 0, j = 0, k = 7, c = 0; i < *size_ptr; i++) {
|
|
|
switch (*(img + i)) {
|
switch (*(img + i)) {
|
|
|
case '0':
|
case '0':
|
|
|
break;
|
break;
|
|
|
case '1':
|
case '1':
|
|
|
c |= 1 << k;
|
c |= 1 << k;
|
|
|
break;
|
break;
|
|
|
default:
|
default:
|
|
|
/* ignore */
|
/* ignore */
|
|
|
continue;
|
continue;
|
|
|
}
|
}
|
|
|
|
|
|
|
if (0 == k) {
|
if (0 == k) {
|
|
|
/* move char to buffer */
|
/* move char to buffer */
|
|
|
*(img + j) = c;
|
*(img + j) = c;
|
|
|
|
|
|
|
/* reset bit pos and char */
|
/* reset bit pos and char */
|
|
|
k = 7;
|
k = 7;
|
|
|
c = 0;
|
c = 0;
|
|
|
|
|
|
|
/* increment pos in output buffer */
|
/* increment pos in output buffer */
|
|
|
j++;
|
j++;
|
|
|
} else
|
} else
|
|
|
k--;
|
k--;
|
|
|
}
|
}
|
|
|
|
|
|
|
if (7 != k) {
|
if (7 != k) {
|
|
|
fprintf(stderr, "\tWARNING! input is not byte aligned.\n");
|
fprintf(stderr, "\tWARNING! input is not byte aligned.\n");
|
|
|
|
|
|
|
*(img + j) = c;
|
*(img + j) = c;
|
|
|
j++;
|
j++;
|
|
|
}
|
}
|
|
|
|
|
|
|
p = NULL;
|
p = NULL;
|
|
|
*size_ptr = j;
|
*size_ptr = j;
|
|
|
|
|
|
|
if (0 < j) {
|
if (0 < j) {
|
|
|
p = malloc(j);
|
p = malloc(j);
|
|
|
if (NULL != p)
|
if (NULL != p)
|
|
|
memcpy(p, img, j);
|
memcpy(p, img, j);
|
|
|
}
|
}
|
|
|
|
|
|
|
free(img);
|
free(img);
|
|
|
|
|
|
|
return p;
|
return p;
|
|
|
}
|
}
|
|
|
|
|
|
|
static char *_load_image(const char *filename, unsigned int *size_ptr,
|
static char *_load_image(const char *filename, unsigned int *size_ptr,
|
|
|
const unsigned char ascii, const _mem_width_t mwidth)
|
const unsigned char ascii, const _mem_width_t mwidth)
|
|
|
{
|
{
|
|
|
char *img;
|
char *img;
|
|
|
int err;
|
int err;
|
|
|
|
|
|
|
img = NULL;
|
img = NULL;
|
|
|
err = open(filename, O_RDONLY);
|
err = open(filename, O_RDONLY);
|
|
|
if (0 <= err) {
|
if (0 <= err) {
|
|
|
struct stat s;
|
struct stat s;
|
|
|
int fd;
|
int fd;
|
|
|
|
|
|
|
fd = err;
|
fd = err;
|
|
|
|
|
|
|
err = fstat(fd, &s);
|
err = fstat(fd, &s);
|
|
|
if (0 == err) {
|
if (0 == err) {
|
|
|
img = malloc(s.st_size);
|
img = malloc(s.st_size);
|
|
|
if (NULL != img) {
|
if (NULL != img) {
|
|
|
unsigned int done;
|
unsigned int done;
|
|
|
|
|
|
|
done = 0;
|
done = 0;
|
|
|
do {
|
do {
|
|
|
err = read(fd, img + done, s.st_size - done);
|
err = read(fd, img + done, s.st_size - done);
|
|
|
if (0 > err) {
|
if (0 > err) {
|
|
|
err = -errno;
|
err = -errno;
|
|
|
if (-EINTR == err) {
|
if (-EINTR == err) {
|
|
|
err = 0;
|
err = 0;
|
|
|
continue;
|
continue;
|
|
|
}
|
}
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
done += err;
|
done += err;
|
|
|
err = 0;
|
err = 0;
|
|
|
} while (0 == err && done < s.st_size);
|
} while (0 == err && done < s.st_size);
|
|
|
|
|
|
|
if (0 == err) {
|
if (0 == err) {
|
|
|
unsigned int size;
|
unsigned int size;
|
|
|
|
|
|
|
size = s.st_size;
|
size = s.st_size;
|
|
|
if (0 != ascii) {
|
if (0 != ascii) {
|
|
|
img = _asci2bin(img, &size);
|
img = _asci2bin(img, &size);
|
|
|
}
|
}
|
|
|
|
|
|
|
if (0 != (s.st_size & (_mem_width2byte(mwidth) - 1))) {
|
if (0 != (s.st_size & (_mem_width2byte(mwidth) - 1))) {
|
|
|
fprintf(stderr, "\tWARNING! input size does not match with memory width\n");
|
fprintf(stderr, "\tWARNING! input size does not match with memory width\n");
|
|
|
}
|
}
|
|
|
|
|
|
|
*size_ptr = size;
|
*size_ptr = size;
|
|
|
} else {
|
} else {
|
|
|
free(img);
|
free(img);
|
|
|
img = NULL;
|
img = NULL;
|
|
|
}
|
}
|
|
|
} else
|
} else
|
|
|
err = -ENOMEM;
|
err = -ENOMEM;
|
|
|
} else
|
} else
|
|
|
err = -errno;
|
err = -errno;
|
|
|
|
|
|
|
close(fd);
|
close(fd);
|
|
|
} else
|
} else
|
|
|
err = -errno;
|
err = -errno;
|
|
|
|
|
|
|
if (0 != err)
|
if (0 != err)
|
|
|
fprintf(stderr, "\tERROR! loading input file <%s>", filename);
|
fprintf(stderr, "\tERROR! loading input file <%s>", filename);
|
|
|
|
|
|
|
return img;
|
return img;
|
|
|
}
|
}
|
|
|
|
|
|
|
#define _BUFSIZ ((16 << 1) + 4 + 2 + 2 + 2 + 1 + 1 + 1)
|
#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,
|
static int _ihex_out(const int fd, const unsigned short addr, const char *data,
|
|
|
const unsigned int len)
|
const unsigned int len)
|
|
|
{
|
{
|
|
|
unsigned int j, i;
|
unsigned int j, i;
|
|
|
char buf[_BUFSIZ];
|
char buf[_BUFSIZ];
|
|
|
int err;
|
int err;
|
|
|
|
|
|
|
if (0 < len) {
|
if (0 < len) {
|
|
|
unsigned char chksum;
|
unsigned char chksum;
|
|
|
|
|
|
|
chksum = 0;
|
chksum = 0;
|
|
|
|
|
|
|
i = snprintf(&buf[0], _BUFSIZ, ":%02x%04x00", len, addr);
|
i = snprintf(&buf[0], _BUFSIZ, ":%02x%04x00", len, addr);
|
|
|
if (_BUFSIZ < i)
|
if (_BUFSIZ < i)
|
|
|
return -ENOSPC;
|
return -ENOSPC;
|
|
|
|
|
|
|
for (j = 0; j < len; j++) {
|
for (j = 0; j < len; j++) {
|
|
|
i += snprintf(&buf[i], _BUFSIZ - i, "%02x", (unsigned char) *(data + j));
|
i += snprintf(&buf[i], _BUFSIZ - i, "%02x", (unsigned char) *(data + j));
|
|
|
if (_BUFSIZ < i)
|
if (_BUFSIZ < i)
|
|
|
return -ENOSPC;
|
return -ENOSPC;
|
|
|
|
|
|
|
chksum += *(data + j);
|
chksum += *(data + j);
|
|
|
}
|
}
|
|
|
|
|
|
|
chksum += len;
|
chksum += len;
|
|
|
chksum += addr & 0x00ff;
|
chksum += addr & 0x00ff;
|
|
|
chksum += addr >> 8;
|
chksum += addr >> 8;
|
|
|
|
|
|
|
chksum = (chksum ^ 0xff) + 0x01;
|
chksum = (chksum ^ 0xff) + 0x01;
|
|
|
i += snprintf(&buf[i], _BUFSIZ - i, "%02x\n", chksum);
|
i += snprintf(&buf[i], _BUFSIZ - i, "%02x\n", chksum);
|
|
|
if (_BUFSIZ < i)
|
if (_BUFSIZ < i)
|
|
|
return -ENOSPC;
|
return -ENOSPC;
|
|
|
} else
|
} else
|
|
|
i = snprintf(&buf[0], _BUFSIZ, ":00000001ff\n");
|
i = snprintf(&buf[0], _BUFSIZ, ":00000001ff\n");
|
|
|
|
|
|
|
j = 0;
|
j = 0;
|
|
|
do {
|
do {
|
|
|
err = write(fd, &buf[j], i - j);
|
err = write(fd, &buf[j], i - j);
|
|
|
if (0 > err) {
|
if (0 > err) {
|
|
|
err = -errno;
|
err = -errno;
|
|
|
if (-EINTR == err) {
|
if (-EINTR == err) {
|
|
|
err = 0;
|
err = 0;
|
|
|
continue;
|
continue;
|
|
|
}
|
}
|
|
|
|
|
|
|
break;
|
break;
|
|
|
}
|
}
|
|
|
|
|
|
|
j += err;
|
j += err;
|
|
|
err = 0;
|
err = 0;
|
|
|
} while (0 == err && j < i);
|
} while (0 == err && j < i);
|
|
|
|
|
|
|
return err;
|
return err;
|
|
|
}
|
}
|
|
|
|
|
|
|
static int _out_image(const char *image, const unsigned int size,
|
static int _out_image(const char *image, const unsigned int size,
|
|
|
const _mem_width_t mwidth, const char *outfile)
|
const _mem_width_t mwidth, const char *outfile)
|
|
|
{
|
{
|
|
|
int err;
|
int err;
|
|
|
|
|
|
|
if (NULL != outfile) {
|
if (NULL != outfile) {
|
|
|
err = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
err = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
|
if (0 > err)
|
if (0 > err)
|
|
|
err = -errno;
|
err = -errno;
|
|
|
} else
|
} else
|
|
|
err = fileno(stdout);
|
err = fileno(stdout);
|
|
|
|
|
|
|
if (0 <= err) {
|
if (0 <= err) {
|
|
|
const unsigned int offset = _mem_width2byte(mwidth);
|
const unsigned int offset = _mem_width2byte(mwidth);
|
|
|
|
|
|
|
unsigned short addr;
|
unsigned short addr;
|
|
|
unsigned int i;
|
unsigned int i;
|
|
|
int fd;
|
int fd;
|
|
|
|
|
|
|
fd = err;
|
fd = err;
|
|
|
|
|
|
|
addr = _start_addr;
|
addr = _start_addr;
|
|
|
i = 0;
|
i = 0;
|
|
|
do {
|
do {
|
|
|
char buf[4];
|
char buf[4];
|
|
|
|
|
|
|
memset(&buf[0], 0x00, offset);
|
memset(&buf[0], 0x00, offset);
|
|
|
memcpy(&buf[0], &image[i],
|
memcpy(&buf[0], &image[i],
|
|
|
((size - i) < offset) ? (size - i) : offset);
|
((size - i) < offset) ? (size - i) : offset);
|
|
|
|
|
|
|
err = _ihex_out(fd, addr, &image[i], offset);
|
err = _ihex_out(fd, addr, &image[i], offset);
|
|
|
|
|
|
|
i += offset;
|
i += offset;
|
|
|
addr += 1;
|
addr += 1;
|
|
|
} while (0 == err && i < size);
|
} while (0 == err && i < size);
|
|
|
|
|
|
|
/* finish line */
|
/* finish line */
|
|
|
if (0 == err)
|
if (0 == err)
|
|
|
err = _ihex_out(fd, 0x00, NULL, 0);
|
err = _ihex_out(fd, 0x00, NULL, 0);
|
|
|
|
|
|
|
if (fd != fileno(stderr))
|
if (fd != fileno(stderr))
|
|
|
close(fd);
|
close(fd);
|
|
|
}
|
}
|
|
|
|
|
|
|
if (0 != err)
|
if (0 != err)
|
|
|
fprintf(stderr, "\tERROR! dump image failed\n");
|
fprintf(stderr, "\tERROR! dump image failed\n");
|
|
|
|
|
|
|
return err;
|
return err;
|
|
|
}
|
}
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
|
|
{
|
{
|
|
|
int err;
|
int err;
|
|
|
|
|
|
|
err = _parse_args(argc, argv);
|
err = _parse_args(argc, argv);
|
|
|
if (0 == err) {
|
if (0 == err) {
|
|
|
unsigned int size;
|
unsigned int size;
|
|
|
char *img;
|
char *img;
|
|
|
|
|
|
|
img = _load_image(_infile, &size, _ascii, _mem_width);
|
img = _load_image(_infile, &size, _ascii, _mem_width);
|
|
|
if (img) {
|
if (img) {
|
|
|
err = _out_image(img, size, _mem_width, _outfile);
|
err = _out_image(img, size, _mem_width, _outfile);
|
|
|
|
|
|
|
free(img);
|
free(img);
|
|
|
} else
|
} else
|
|
|
err = -EIO;
|
err = -EIO;
|
|
|
}
|
}
|
|
|
|
|
|
|
return err;
|
return err;
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|