X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/blobdiff_plain/bc6e060953d52e4aa7e57954f2833168e9d8d795..467e092776691683b297e1328281cded11717298:/latester/latester.c diff --git a/latester/latester.c b/latester/latester.c index f58086a..0906760 100644 --- a/latester/latester.c +++ b/latester/latester.c @@ -1,6 +1,6 @@ /**************************************************************************/ /* CAN latency tester */ -/* Copyright (C) 2010, 2011 Michal Sojka, DCE FEE CTU Prague */ +/* Copyright (C) 2010, 2011, 2012, 2013 Michal Sojka, DCE FEE CTU Prague */ /* License: GPLv2 */ /**************************************************************************/ @@ -67,6 +67,7 @@ struct options { /* Temporary variables */ FILE *f_msgs; FILE *f_hist; + FILE *f_hist_gw; FILE *f_stat; }; @@ -98,12 +99,13 @@ struct msg_info { struct timespec ts_rx_onwire, ts_rx_onwire_kern; struct timespec ts_rx_final, ts_rx_final_kern; struct can_frame sent, received; + unsigned lat_measured_us, tx_time_us; }; #define MAX_INFOS 10000 struct msg_info msg_infos[MAX_INFOS]; -struct histogram histogram; +struct histogram histogram, histogram_gw; void sprint_canframe(char *buf , struct can_frame *cf, int sep) { /* documentation see lib.h */ @@ -158,39 +160,118 @@ static inline char *tstamp_str(const void *ctx, struct timespec *tstamp) tstamp->tv_sec, tstamp->tv_nsec/1000); } +/* Functions and types for CRC checks. + * + * Generated on Wed Sep 21 22:30:11 2011, + * by pycrc v0.7.8, http://www.tty1.net/pycrc/ + * using the configuration: + * Width = 15 + * Poly = 0x4599 + * XorIn = 0x0000 + * ReflectIn = False + * XorOut = 0x0000 + * ReflectOut = False + * Algorithm = table-driven + *****************************************************************************/ +typedef uint16_t crc_t; + +static const crc_t crc_table[2] = { + 0x0000, 0x4599 +}; + +crc_t crc_update(crc_t crc, uint32_t data, size_t bit_len) +{ + unsigned int tbl_idx; +/* crc_t bc = crc; */ +/* uint32_t bd = data; */ +/* size_t bl = bit_len; */ + + while (bit_len--) { + tbl_idx = (crc >> 14) ^ (data >> 31); + crc = crc_table[tbl_idx & 0x01] ^ (crc << 1); + data <<= 1; + } + crc = crc & 0x7fff; +/* printf("crc: 0x%04x -> 0x%04x data: 0x%08x len: %d\n", */ +/* bc, crc, bd, bl); */ + return crc; +} + +uint32_t calc_bitmap_crc(uint32_t *bitmap, unsigned start, unsigned end) +{ + crc_t crc = 0; + crc = crc_update(crc, bitmap[0] << start, 32 - start); + crc = crc_update(crc, bitmap[1], 32); + crc = crc_update(crc, bitmap[2], end - 64 > 32 ? 32 : end - 64); /* FIXME: This seems to be broken for end < 64 */ + crc = crc_update(crc, bitmap[3], end > 96 ? end - 96 : 0); + return (uint32_t)htons(crc << 17); +} + +void write_crc_to_bitmap(uint32_t crc, uint32_t *bitmap, struct can_frame *frame) +{ + unsigned index = frame->can_id & CAN_EFF_FLAG ? 2 : 1; + if (frame->can_dlc < 4) + bitmap[index] |= crc >> (frame->can_dlc*8); + if (frame->can_dlc == 3) + bitmap[index + 1] |= crc << 8; + if (frame->can_dlc >= 4 && frame->can_dlc < 8) + { + bitmap[index + 1] |= crc >> (frame->can_dlc*8); + if (frame->can_dlc == 7) + bitmap[index + 2] = crc << 8; + } + else if (frame->can_dlc == 8) + bitmap[index + 2] = crc; +} + unsigned calc_stuff_bits(struct can_frame *frame) { uint32_t bitmap[4]; unsigned start = 0, end; - uint32_t mask, ones = 0, basemask = 0xf0000000; + uint32_t mask, ones = 0, basemask = 0xf8000000; unsigned stuffed = 0; memset(bitmap, 0, sizeof(bitmap)); + uint32_t crc; +/* char received[64]; */ +/* sprint_canframe(received, frame, true); */ +/* printf("Frame: %s\n", received); */ + if (frame->can_id & CAN_EFF_FLAG) { + // bit 31 0 + // [0] |...........................sBBBB| s = SOF, B = Base ID (11 bits) + // [1] |BBBBBBBSIEEEEEEEEEEEEEEEEEER10DLC4| S = SRR, I = IDE, E = Extended ID (18 bits), DLC4 = DLC + // [2] |00000000111111112222222233333333| Data bytes, MSB first + // [3] |44444444555555556666666677777777| bitmap[0] = - (frame->can_id >> 25); + ((frame->can_id & CAN_EFF_MASK) >> 25); bitmap[1] = - (frame->can_id >> 18) << 25 | - 3 << 23 | - (frame->can_id & 0x3ffff) << 7 | - (!!(frame->can_id & CAN_RTR_FLAG)) << 6 | - 0 << 4 | + ((frame->can_id & CAN_EFF_MASK) >> 18) << 25 | + 3 << 23 | + ((frame->can_id & CAN_EFF_MASK) & 0x3ffff) << 7 | + (!!(frame->can_id & CAN_RTR_FLAG)) << 6 | + 0 << 4 | frame->can_dlc & 0xf; - bitmap[2] = htonl(((uint32_t*)frame->data)[0]); - bitmap[3] = htonl(((uint32_t*)frame->data)[1]); - start = 28; + memcpy(&bitmap[2], &frame->data, frame->can_dlc); + start = 27; end = 64 + 8*frame->can_dlc; } else { + // bit 31 0 + // [0] |.............sIIIIIIIIIIIRE0DLC4| s = SOF, I = ID (11 bits), R = RTR, E = IDE, DLC4 = DLC + // [1] |00000000111111112222222233333333| Data bytes, MSB first + // [2] |44444444555555556666666677777777| bitmap[0] = (frame->can_id << 7) | (!!(frame->can_id & CAN_RTR_FLAG)) << 6 | 0 << 4 | frame->can_dlc & 0xf; - bitmap[1] = htonl(((uint32_t*)frame->data)[0]); - bitmap[2] = htonl(((uint32_t*)frame->data)[1]); - start = 14; + memcpy(&bitmap[1], &frame->data, frame->can_dlc); + start = 13; end = 32 + 8*frame->can_dlc; } - /* TODO: Calc stuff bits in CRC */ + crc = calc_bitmap_crc(bitmap, start, end); + write_crc_to_bitmap(crc, bitmap, frame); + end += 15; + while (start < end) { mask = basemask >> (start & 0x1f); while (1) { @@ -219,9 +300,10 @@ unsigned calc_stuff_bits(struct can_frame *frame) { ones = !ones; } //printf ("STUFFED %d BITS\n", stuffed); + return stuffed; } -unsigned calc_frame_txtime(struct can_frame *frame) { +unsigned calc_frame_txtime_us(struct can_frame *frame) { return calc_stuff_bits(frame) + 1 + /* SOF */ 11 + /* ID A */ @@ -248,6 +330,9 @@ void msg_info_print(FILE *f, struct msg_info *mi) static long num = 0; char sent[64], received[64]; + if (!f) + return; + sprint_canframe(sent, &mi->sent, true); sprint_canframe(received, &mi->received, true); @@ -260,7 +345,7 @@ void msg_info_print(FILE *f, struct msg_info *mi) num, S(mi->ts_sent), sent, S(mi->ts_rx_final_kern), S(mi->ts_rx_final), received, DIFF(mi->ts_sent, mi->ts_rx_final_kern), DIFF(mi->ts_sent, mi->ts_rx_final), - calc_frame_txtime(&mi->received)); + mi->tx_time_us); break; case 3: fprintf(f, "%ld: %s %s -> %s (%s) -> %s (%s) %s = %s (%s), %s (%s) %d\n", @@ -271,7 +356,7 @@ void msg_info_print(FILE *f, struct msg_info *mi) DIFF(mi->ts_sent, mi->ts_rx_onwire), DIFF(mi->ts_rx_onwire_kern, mi->ts_rx_final_kern), DIFF(mi->ts_rx_onwire, mi->ts_rx_final), - calc_frame_txtime(&mi->received)); + mi->tx_time_us); break; } #undef S @@ -313,7 +398,7 @@ void dbg_print_timespec(char *msg, struct timespec *tv) printf("%s sec=%ld nsec=%ld\n", msg, tv->tv_sec, tv->tv_nsec); } -static inline unsigned get_msg_latency_us(struct msg_info *mi) +static inline void calc_msg_latencies(struct msg_info *mi) { struct timespec diff; switch (num_interfaces) { @@ -330,9 +415,10 @@ static inline unsigned get_msg_latency_us(struct msg_info *mi) timespec_subtract(&diff, &mi->ts_rx_final_kern, &mi->ts_sent); break; default: - return 0; + return; } - return diff.tv_sec * 1000000 + diff.tv_nsec/1000; + mi->lat_measured_us = diff.tv_sec * 1000000 + diff.tv_nsec/1000; + mi->tx_time_us = calc_frame_txtime_us(&mi->received); } void set_sched_policy_and_prio(int policy, int rtprio) @@ -596,7 +682,10 @@ void process_final_rx(int s) mi->ts_rx_final = ts_user; mi->received = frame; - histogram_add(&histogram, get_msg_latency_us(mi)); + calc_msg_latencies(mi); + + histogram_add(&histogram, mi->lat_measured_us); + histogram_add(&histogram_gw, mi->lat_measured_us - mi->tx_time_us); ret = write(completion_pipe[1], &mi, sizeof(mi)); if (ret == -1) @@ -779,12 +868,19 @@ int parse_options(int argc, const char *argv[]) } if (opt.name) { - char *f = talloc_asprintf(local, "%s-hist.txt", opt.name); + char *f = talloc_asprintf(local, "%s-hist-raw.txt", opt.name); opt.f_hist = fopen(f, "w"); if (!opt.f_hist) error(1, errno, "fopen: %s", f); } + if (opt.name) { + char *f = talloc_asprintf(local, "%s-hist.txt", opt.name); + opt.f_hist_gw = fopen(f, "w"); + if (!opt.f_hist_gw) + error(1, errno, "fopen: %s", f); + } + if (opt.name) { char *f = talloc_asprintf(local, "%s-stat.txt", opt.name); opt.f_stat = fopen(f, "w"); @@ -825,6 +921,7 @@ int main(int argc, const char *argv[]) msg_infos[i].id = -1; histogram_init(&histogram, 5000000, 1); + histogram_init(&histogram_gw, 5000000, 1); ret = pipe(completion_pipe); if (ret == -1) @@ -834,6 +931,13 @@ int main(int argc, const char *argv[]) error(1, errno, "pipe fcntl"); init_ftrace(); + if (getenv("LATESTER_CONTROL_HACKBENCH")) { + char cmd[1000]; + sprintf(cmd, "ssh -x -a -S $HOME/.ssh/cangw-connection root@192.168.2.3 'kill -CONT -%s'", + getenv("LATESTER_CONTROL_HACKBENCH")); + printf("Running: %s\n", cmd); + system(cmd); + } pthread_create(&thread, 0, measure_thread, NULL); @@ -883,40 +987,54 @@ int main(int argc, const char *argv[]) pthread_join(thread, NULL); + if (getenv("LATESTER_CONTROL_HACKBENCH")) { + char cmd[1000]; + sprintf(cmd, "ssh -x -a -S $HOME/.ssh/cangw-connection root@192.168.2.3 'kill -STOP -%s'", + getenv("LATESTER_CONTROL_HACKBENCH")); + printf("Running: %s\n", cmd); + system(cmd); + } + close(completion_pipe[0]); close(completion_pipe[1]); histogram_fprint(&histogram, opt.f_hist); - fclose(opt.f_hist); - fclose(opt.f_msgs); - - - fprintf(opt.f_stat, "cmdline='"); - for (i=0; i