/* * This file is part of the Black Magic Debug project. * * Copyright (C) 2011 Black Sphere Technologies Ltd. * Written by Gareth McMullin * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "platform.h" #include "gdb_if.h" #include "jtag_scan.h" #include #include #include #include #include #include #include #include #include #include static int serial_fd = -1; static int debug; #define BUF_SIZE 4096 static uint8_t outbuf[BUF_SIZE]; static uint16_t bufptr = 0; int serial_open(const char *name) { int fd; /* Open. */ fd = open(name, O_RDWR | O_NOCTTY); if (fd == -1) return -1; /* Setup raw. */ struct termios tc; if(tcgetattr(fd, &tc) == -1) { close(fd); return -1; } tc.c_iflag &= ~(IGNPAR | PARMRK | ISTRIP | IGNBRK | BRKINT | IGNCR | ICRNL | INLCR | IXON | IXOFF | IXANY | IMAXBEL); tc.c_oflag &= ~(OPOST); tc.c_cflag &= ~(HUPCL | CSTOPB | PARENB | PARODD | CSIZE); tc.c_cflag |= CS8 | CLOCAL | CREAD; tc.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN | NOFLSH | TOSTOP); tc.c_cc[VTIME] = 0; tc.c_cc[VMIN] = 1; tcflush(fd, TCIFLUSH); if(tcsetattr(fd, TCSANOW, &tc) == -1) { close(fd); return -1; } return fd; } int platform_init(int argc, char **argv) { int c; char *serial = NULL; while((c = getopt(argc, argv, "ds:")) != -1) { switch(c) { case 'd': debug = 1; break; case 's': serial = optarg; break; } } if(optind != argc) { fprintf(stderr, "too many arguments\n"); abort(); } serial_fd = serial_open(serial); if(serial_fd == -1) { fprintf(stderr, "unable to open serial device: %s\n", strerror(errno)); abort(); } uint8_t init_str[] = { DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_RESET_SYNC, DEV2_OP_SETUP, 8, 0, 0, 0, 0, DEV2_OP_DIR, TMS_PIN | TCK_PIN | TDI_PIN }; platform_buffer_write (init_str, sizeof (init_str)); assert(gdb_if_init() == 0); jtag_scan(NULL); return 0; } void platform_buffer_flush(void) { if(bufptr) { assert(write(serial_fd, outbuf, bufptr) == bufptr); bufptr = 0; } } int platform_buffer_write(const uint8_t *data, int size) { if((bufptr + size) / BUF_SIZE > 0) platform_buffer_flush(); memcpy(outbuf + bufptr, data, size); bufptr += size; return size; } int platform_buffer_read(uint8_t *data, int size) { int index = 0; platform_buffer_flush(); while((index += read(serial_fd, data + index, size - index)) != size); return size; } #ifdef WIN32 #warning "This vasprintf() is dubious!" int vasprintf(char **strp, const char *fmt, va_list ap) { int size = 128, ret = 0; *strp = malloc(size); while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size)) *strp = realloc(*strp, size <<= 1); return ret; } #endif const char *platform_target_voltage(void) { return "not supported"; } void platform_delay(uint32_t delay) { usleep(delay * 100000); } void platform_debug(const char *fmt, ...) { if(debug) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } }