diff options
Diffstat (limited to 'gm_platform/fw/tw_test.c')
-rw-r--r-- | gm_platform/fw/tw_test.c | 450 |
1 files changed, 0 insertions, 450 deletions
diff --git a/gm_platform/fw/tw_test.c b/gm_platform/fw/tw_test.c deleted file mode 100644 index eb41dbe..0000000 --- a/gm_platform/fw/tw_test.c +++ /dev/null @@ -1,450 +0,0 @@ -#include <errno.h> -#include <sys/ioctl.h> -#include <asm/termbits.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <dirent.h> -#include <sys/types.h> -#include <assert.h> -#include <sys/epoll.h> -#include <time.h> - -#include <sqlite3.h> - -#include <zlib.h> - -int set_interface_attribs (int fd, int baudrate) { - struct termios2 tio; - memset (&tio, 0, sizeof(tio)); - if (ioctl (fd, TCGETS2, &tio) != 0) { - fprintf(stderr, "Could not request termios for given port\n"); - return -1; - } - - /* FIXME set baudrate */ - - tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8; /* 8 bit */ - /* disable IGNBRK for mismatched speed tests; otherwise receive break as \000 chars */ - tio.c_iflag &= ~IGNBRK; /* disable break processing */ - tio.c_lflag = 0; /* no signaling chars, no echo, no canonical processing */ - tio.c_oflag = 0; /* no remapping, no delays */ - - tio.c_iflag &= ~(IXON | IXOFF | IXANY); /* shut off xon/xoff ctrl */ - - tio.c_cflag |= (CLOCAL | CREAD);/* ignore modem controls, enable reading */ - tio.c_cflag &= ~(PARENB | PARODD); /* no parity */ - tio.c_cflag &= ~CSTOPB; - tio.c_cflag &= ~CRTSCTS; - - tio.c_cflag &= ~(CBAUD | CBAUDEX); - tio.c_cflag |= BOTHER; - tio.c_ospeed = baudrate; - tio.c_cflag &= ~((CBAUD | CBAUDEX) << IBSHIFT); - tio.c_cflag |= (B0 << IBSHIFT); /* same as output baudrate */ - - tio.c_cc[VMIN] = 0; /* non-blocking mode */ - tio.c_cc[VTIME] = 10; /* 1000ms seconds read timeout */ - - if (ioctl (fd, TCSETS2, &tio)) { - fprintf(stderr, "Could not set serial port attributes: Error %d in tcsetattr (\"%s\")\n", errno, strerror(errno)); - return -1; - } - return 0; -} - -ssize_t cobs_decode(char *dst, size_t dstlen, char *src, size_t srclen) { - size_t p = 1; - size_t c = (unsigned char)src[0]; - if (c == 0) - return -5; /* invalid framing. An empty frame would be [...] 00 01 00, not [...] 00 00 */ - - while (p < srclen && src[p]) { - char val; - c--; - - if (c == 0) { - c = (unsigned char)src[p]; - val = 0; - } else { - val = src[p]; - } - - if (p > dstlen) - return -4; /* Destination buffer too small */ - dst[p-1] = val; - p++; - } - - if (p == srclen) - return -2; /* Invalid framing. The terminating null byte should always be present in the input buffer. */ - - if (c != 1) - return -3; /* Invalid framing. The skip counter does not hit the end of the frame. */ - - return p-1; -} - -int cobs_encode(char *dst, char *src, size_t srclen) { - if (srclen > 254) - return -1; - - size_t p = 0; - while (p <= srclen) { - - char val; - if (p != 0 && src[p-1] != 0) { - val = src[p-1]; - - } else { - size_t q = p; - while (q < srclen && src[q] != 0) - q++; - val = (char)q-p+1; - } - - - *dst++ = val; - p++; - } - - *dst++ = 0; - - return 0; -} - -void print_usage(char *prog) { - fprintf(stderr, "Usage: %s [-p /dev/serial/some_port] [-b baudrate] dbfile.sqilte3\n", prog); -} - -void hexdump(const void* data, size_t size) { - char ascii[17]; - size_t i, j; - ascii[16] = '\0'; - for (i = 0; i < size; ++i) { - printf("%02X ", ((unsigned char*)data)[i]); - if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { - ascii[i % 16] = ((unsigned char*)data)[i]; - } else { - ascii[i % 16] = '.'; - } - if ((i+1) % 8 == 0 || i+1 == size) { - printf(" "); - if ((i+1) % 16 == 0) { - printf("| %s \n", ascii); - } else if (i+1 == size) { - ascii[(i+1) % 16] = '\0'; - if ((i+1) % 16 <= 8) { - printf(" "); - } - for (j = (i+1) % 16; j < 16; ++j) { - printf(" "); - } - printf("| %s \n", ascii); - } - } - } -} - -int main(int argc, char *argv[]) { - - int opt; - int baudrate = 250000; - char *endptr = NULL; - char *port = NULL; - char *dbfile = NULL; - while ((opt = getopt(argc, argv, "p:b:")) != -1) { - switch (opt) { - case 'p': - port = optarg; - break; - case 'b': - baudrate = strtol(optarg, &endptr, 10); - if (errno == ERANGE || endptr == NULL || *endptr != '\0') { - fprintf(stderr, "Invalid baudrate \"%s\"\n", optarg); - print_usage(argv[0]); - } - break; - default: - print_usage(argv[0]); - exit(EXIT_FAILURE); - } - } - - if (port == NULL) { - DIR *le_dir = opendir("/dev/serial/by-id"); - if (le_dir == NULL) { - fprintf(stderr, "No serial port given and could not find any in /dev/serial\n"); - exit(EXIT_FAILURE); - - } - - struct dirent *de; - while ((de = readdir(le_dir))) { - if (de == NULL) { - fprintf(stderr, "No serial port given and could not find any in /dev/serial\n"); - exit(EXIT_FAILURE); - } - - if (!strncmp(de->d_name, ".", sizeof(de->d_name)) || - !strncmp(de->d_name, "..", sizeof(de->d_name))) - continue; - - if (port != NULL) { - fprintf(stderr, "No serial port given and found multiple candidates in /dev/serial\n"); - exit(EXIT_FAILURE); - } - - const char *prefix = "/dev/serial/by-id/"; - port = malloc(strlen(prefix) + sizeof(de->d_name) + 1); - if (port == NULL) { - fprintf(stderr, "Could not allocate memory\n"); - exit(EXIT_FAILURE); - } - strcpy(port, prefix); - strncat(port, de->d_name, sizeof(de->d_name)); - } - fprintf(stderr, "No port given, defaulting to %s\n", port); - closedir(le_dir); - } - - if (optind != argc - 1) { - fprintf(stderr, "Too few arguments\n"); - print_usage(argv[0]); - exit(EXIT_FAILURE); - } - - dbfile = argv[optind]; - printf("Using database file %s\n", dbfile); - fflush(stdout); - - int fd = open(port, O_RDWR|O_NOCTTY|O_SYNC); - if (fd < 0) { - fprintf(stderr, "Cannot open serial port: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - if (set_interface_attribs (fd, baudrate)) - exit(EXIT_FAILURE); - - sqlite3 *db; - if (sqlite3_open(dbfile, &db) != SQLITE_OK) { - fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - exit(EXIT_FAILURE); - } - - char *errmsg; - if (sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS measurements (rx_time INTEGER, tx_seq INTEGER, rx_seq INTEGER, data BLOB);", - NULL, NULL, &errmsg) != SQLITE_OK) { - fprintf(stderr, "Error initializing databse: %s\n", errmsg); - sqlite3_close(db); - exit(EXIT_FAILURE); - } - - const char *insert_sql = "INSERT INTO measurements VALUES (?, ?, ?, ?)"; - sqlite3_stmt *insert_stmt; - if (sqlite3_prepare_v2(db, insert_sql, strlen(insert_sql), &insert_stmt, NULL) != SQLITE_OK) { - fprintf(stderr, "Error compiling SQL: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - exit(EXIT_FAILURE); - } - - char buf [1024]; - int in_sync = 0, wpos = 0; - struct __attribute__((__packed__)) { - uint32_t crc; - uint8_t pid; - uint8_t _pad; - uint16_t seq; - uint16_t data[32]; - } packet; - struct __attribute__((__packed__)) { - uint8_t type; - uint8_t pid; - } wpacket; - char wbuf[4]; - - int epollfd = epoll_create1(0); - if (epollfd < 0) - goto epoll_err; - - #define MAX_EVENTS 10 - struct epoll_event ev, events[MAX_EVENTS]; - ev.events = EPOLLIN; - ev.data.fd = fd; - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) - goto epoll_err; - - wpacket.type = 1; - wpacket.pid = 0; - cobs_encode(wbuf, (char *)&wpacket, sizeof(wpacket)); - write(fd, wbuf, sizeof(wbuf)); - - /* FIXME begin debug code */ - for (int i=0; i<32; i++) { - wpacket.type = 2; - wpacket.pid = packet.pid; - cobs_encode(wbuf, (char *)&wpacket, sizeof(wpacket)); - write(fd, wbuf, sizeof(wbuf)); - usleep(20); - } - /* FIXME end debug code */ - - int current_seq = -1; - uint64_t local_seq = 0; - while (23) { - int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); - if (nfds == -1) - goto epoll_err; - - if (nfds == 0) - continue; - - ssize_t n = read(fd, buf+wpos, sizeof(buf)-wpos); - printf("--- read wpos=%d n=%ld\n", wpos, n); - hexdump(buf+wpos, n); - if (n<0) { - if (errno == EAGAIN || errno == EINTR) - continue; - - fprintf(stderr, "Error reading from port: %s\n", strerror(errno)); - goto loop_err; - } - //printf("--- debug: read n=%d bytes at wpos=%d\n", n, wpos); - //fflush(stdout); - wpos += n; - - while (23) { - void *first_nul = memchr(buf, 0, wpos) ; - ssize_t first_nul_offx = first_nul - (void*)buf; - ssize_t remaining = wpos - first_nul_offx; - - if (!in_sync) { - if (first_nul) { - memmove(buf, first_nul+1, remaining-1); - wpos = remaining-1; - in_sync = 1; - continue; - - } else { - wpos = 0; - break; - } - } - - if (!first_nul) - break; - - printf("--- debug: first_nul=%p (idx=%ld) wpos=%d remaining=%ld\n", first_nul, first_nul_offx, wpos, remaining); - hexdump(buf, 80); - - int rc = cobs_decode((char *)&packet, sizeof(packet), buf, wpos); - if (rc < 0) { - printf("Framing error: rc=%d\n", rc); - goto it_err; - } - - /* Use zlib to calculate CRC32. The STM32 code calculates the CRC byte-wise, so we emulate this here. */ - uint32_t our_crc = 0; - if (rc > 0) { - uint8_t buf[4] = {0}; - for (int i=4; i<rc; i++) { - buf[3] = ((uint8_t *)&packet)[i]; - our_crc = crc32(our_crc, buf, sizeof(buf)); - } - } - - bool error = false; - /* Check CRC */ - if (our_crc != packet.crc) { - printf("CRC mismatch: seq=%d packet=%08x computed=%08x\n", packet.pid, packet.crc, our_crc); - error = true; - } - - /* Check device sequence number */ - int last_seq = current_seq; - int predicted_seq = (last_seq+1) % 0xffff; - if (!error) - current_seq = packet.seq; - if (last_seq >= 0 && packet.seq != predicted_seq) { - printf("SEQ mismatch: packet=%d computed=%d\n", packet.seq, predicted_seq); - error = true; - } - - if (error) - goto it_err; - - /* Write to database */ - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts)) { - fprintf(stderr, "Error getting current wall-clock time: %s\n", strerror(errno)); - goto loop_err; - } - uint64_t timestamp = ts.tv_sec*1000 + ts.tv_nsec/1000000; - - if (sqlite3_bind_int(insert_stmt, 1, timestamp) != SQLITE_OK) - goto write_err; - - if (sqlite3_bind_int(insert_stmt, 2, packet.seq) != SQLITE_OK) - goto write_err; - - if (sqlite3_bind_int(insert_stmt, 3, local_seq) != SQLITE_OK) - goto write_err; - - if (sqlite3_bind_blob(insert_stmt, 4, packet.data, sizeof(packet.data), SQLITE_STATIC) != SQLITE_OK) - goto write_err; - - while ((rc = sqlite3_step(insert_stmt)) == SQLITE_BUSY) - ; - if (rc != SQLITE_DONE) - goto write_err; - - if (sqlite3_reset(insert_stmt) != SQLITE_OK) - goto write_err; - - if (sqlite3_clear_bindings(insert_stmt) != SQLITE_OK) - goto write_err; - - local_seq++; - - printf("OK: seq=%d crc=%08x\n", current_seq, packet.crc); - - /* send ACK reply */ - wpacket.type = 2; - wpacket.pid = packet.pid; - cobs_encode(wbuf, (char *)&wpacket, sizeof(wpacket)); - write(fd, wbuf, sizeof(wbuf)); - -it_err: - /* Fixup buffer for next iteration */ - if (remaining-1 > 0) { - printf(" ---memmove(buf=%p, first_nul+1=%p, remaining-1=%ld);-->\n", buf, first_nul+1, remaining-1); - memmove(buf, first_nul+1, remaining-1); - } - //hexdump(buf, 80); - fflush(stdout); - printf("--- continuing wpos=%d->%d\n", wpos, (int)(remaining-1)); - wpos = remaining-1; - } - } - - return 0; - -write_err: - fprintf(stderr, "Error writing to database: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return EXIT_FAILURE; - -epoll_err: - fprintf(stderr, "epoll error: %s\n", strerror(errno)); - -loop_err: - sqlite3_close(db); - return EXIT_FAILURE; -} |