示例#1
0
static char* test_cbuffer_pop(void) {
  CircularBuffer* mybuf = cbuffer_new();
  // put us at the end of the buffer
  mybuf->pos = IO_BUFFER_SIZE - 5;
  mybuf->tail = IO_BUFFER_SIZE - 5;
  uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  cbuffer_append(mybuf, test_data, 11);

  Buffer* bucky = cbuffer_pop(mybuf, 5);
  mu_assert_eq("size", cbuffer_size(mybuf), 6);
  mu_assert_eq("content", memcmp(bucky->data, test_data, 
        5*sizeof(uint32_t)), 0);

  Buffer* badger = cbuffer_pop(mybuf, 6);
  mu_assert_eq("size2", cbuffer_size(mybuf), 0);
  mu_assert_eq("content2", 
      memcmp(badger->data, test_data + 5, 6), 0);

  // if we pop an empty collection, we get nothing.
  Buffer* empty = cbuffer_pop(mybuf, 10);
  mu_assert_eq("size3", empty->size, 0);

  cbuffer_free(mybuf);
  buffer_free(bucky);
  buffer_free(badger);
  buffer_free(empty);

  return 0;
}
示例#2
0
static char* test_cbuffer_transfer_data(void) {
  CircularBuffer* src = cbuffer_new();
  CircularBuffer* dst = cbuffer_new();

  for (int i = 0; i < 200; ++i) {
    cbuffer_push_back(src, i);
  }
  mu_assert_eq("Src buffer size", cbuffer_size(src), 200);
  mu_assert_eq("Dst buffer size", cbuffer_size(dst), 0);

  // transfer data from src -> dst
  cbuffer_transfer_data(src, dst);

  mu_assert_eq("Src buffer size post transfer",
      cbuffer_size(src), 0);
  mu_assert_eq("Dst buffer size post transfer",
      cbuffer_size(dst), 200);

  // check content
  for (int i = 0; i < 200; ++i) {
    mu_assert_eq("Dst content",
        cbuffer_pop_front(dst), i);
  }

  cbuffer_free(src);
  cbuffer_free(dst);

  return 0;
}
示例#3
0
int ipbus_stream_state(const CircularBuffer* input_buffer, int* swapbytes) {
  if (!cbuffer_size(input_buffer)) {
    return IPBUS_ISTREAM_EMPTY;
  }
  uint32_t firstword = cbuffer_value_at_net(input_buffer, 0);
  //LOG_DEBUG("Got a word: %"PRIx32, firstword);
  // check if this is a packet header
  int is_pkt = ipbus_detect_packet_header(firstword);
  if (is_pkt) {
    // check if we want to update an endianness flag
    if (swapbytes != NULL) {
      if (is_pkt == IPBUS_ISTREAM_PACKET)
        *swapbytes = 0;
      if (is_pkt == IPBUS_ISTREAM_PACKET_SWP_ORD)
        *swapbytes = 1;
    }
    return is_pkt;
  }
  // Double check if it is reasonable transaction packet
  // header.  We should never have the middle of a transaction
  // at the header of the buffer - we always wait for a 
  // transaction to be in-buffer before reading it out.
  ipbus_transaction_t transaction = ipbus_decode_transaction_header(
      input_buffer, *swapbytes);

  if ((int)cbuffer_size(input_buffer) >= (transaction.data.size + 1)) {
    return IPBUS_ISTREAM_FULL_TRANS;
  }

  //LOG_DEBUG("Partial transaction size: %"PRIx32, cbuffer_size(input_buffer));
  return IPBUS_ISTREAM_PARTIAL_TRANS;
}
示例#4
0
static char* test_cbuffer_append_wraps(void) {
  CircularBuffer* mybuf = cbuffer_new();
  // put us at the end of the buffer
  mybuf->pos = IO_BUFFER_SIZE - 5;
  mybuf->tail = IO_BUFFER_SIZE - 5;
  uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  cbuffer_append(mybuf, test_data, 11);

  mu_assert_eq("pos", mybuf->pos, IO_BUFFER_SIZE - 5);
  mu_assert_eq("size", cbuffer_size(mybuf), 11);
  mu_assert_eq("tail content", memcmp(
        &(mybuf->data[mybuf->pos]),
        test_data, 
        5 * sizeof(uint32_t)), 0);

  // make sure we aren't trashing the memory after the buffer.
  //mu_assert_eq("tail content sanity", mybuf->data[IO_BUFFER_SIZE-1], 4);

  mu_assert_eq("head content", memcmp(
        mybuf->data, 
        test_data + 5, 
        6 * sizeof(uint32_t)), 0);

  uint32_t test_data2[3] = {11, 12, 13};
  cbuffer_append(mybuf, test_data2, 3);
  mu_assert_eq("size", cbuffer_size(mybuf), 14);
  mu_assert_eq("content", memcmp(&(mybuf->data[6]), test_data2, 3), 0);

  cbuffer_free(mybuf);

  return 0;
}
static char* test_ram2()
{
    // --------------
    // Setup
    // --------------
    CircularBuffer* pc_input    = cbuffer_new();
    CircularBuffer* pc_output   = cbuffer_new();
    CircularBuffer* orsc_input  = cbuffer_new();
    CircularBuffer* orsc_output = cbuffer_new();

    VMEStream *pc_stream = vmestream_initialize_heap(pc_input, pc_output, 2);

    VMEStream *orsc_stream = malloc(sizeof(VMEStream));
    orsc_stream->input              = orsc_input;
    orsc_stream->output             = orsc_output;
    orsc_stream->local_send_size    = pc_stream->remote_send_size;
    orsc_stream->local_recv_size    = pc_stream->remote_recv_size;
    orsc_stream->remote_send_size   = pc_stream->local_send_size;
    orsc_stream->remote_recv_size   = pc_stream->local_recv_size;
    orsc_stream->recv_data          = pc_stream->send_data;
    orsc_stream->send_data          = pc_stream->recv_data;
    orsc_stream->MAXRAM             = pc_stream->MAXRAM;


    cbuffer_push_back(pc_input, 0xDEADBEEF);
    cbuffer_push_back(orsc_input, 0xBEEFCAFE);

    vmestream_transfer_data(pc_stream);

    vmestream_transfer_data(orsc_stream);
    vmestream_transfer_data(pc_stream);

    mu_assert("Error: pc_input not empty", cbuffer_size(pc_input) == 0);
    mu_assert("Error: orsc_input not empty", cbuffer_size(orsc_input) == 0);

    mu_assert("Error: orsc_output.pop != DEADBEEF", cbuffer_pop_front(orsc_output));
    mu_assert("Error: pc_output.pop != BEEFCAFE", cbuffer_pop_front(pc_output));

    mu_assert("Error: pc_output not empty", cbuffer_size(pc_output) == 0);
    mu_assert("Error: orsc_output not empty", cbuffer_size(orsc_output) == 0);

    // --------------
    // Tear-Down
    // --------------
    vmestream_destroy_heap(pc_stream);
    free(orsc_stream);
    cbuffer_free(pc_input);
    cbuffer_free(orsc_input);
    cbuffer_free(pc_output);
    cbuffer_free(orsc_output);

    return 0;
}
示例#6
0
static char* test_cbuffer_size(void) {
  CircularBuffer* mybuf = cbuffer_new();
  mybuf->pos = IO_BUFFER_SIZE - 5;
  mybuf->tail = IO_BUFFER_SIZE - 5;
  mu_assert_eq("size0", cbuffer_size(mybuf), 0);
  for (int i = 0; i < 15; ++i) {
    cbuffer_push_back(mybuf, i);
    mu_assert_eq("size", cbuffer_size(mybuf), i + 1);
  }

  cbuffer_free(mybuf);

  return 0;
}
示例#7
0
/**
 * Push less data to the buffers than we have RAM available
 */
static char *test_ram2()
{
    // local application buffers
    CircularBuffer *tx1 = cbuffer_new();
    CircularBuffer *rx1 = cbuffer_new();
    CircularBuffer *tx2 = cbuffer_new();
    CircularBuffer *rx2 = cbuffer_new();

    VMEStream *test1 = vmestream_initialize(tx1, rx1, 2);
    VMEStream *test2 = malloc(sizeof(VMEStream));
    test2->input = tx2;
    test2->output = rx2;

    test2->rx_size = test1->tx_size;
    test2->tx_size = test1->rx_size;
    test2->rx_data = test1->tx_data;
    test2->tx_data = test1->rx_data;
    test2->MAXRAM  = test1->MAXRAM;

    // place only one word on the buffers
    cbuffer_push_back(tx1, 0xDEADBEEF);
    // put some output data on host #2
    cbuffer_push_back(tx2, 0xBEEFCAFE);

    vmestream_transfer_data(test1);
    vmestream_transfer_data(test2);
    vmestream_transfer_data(test1);

    mu_assert("Error: tx1 not empty", 0 == cbuffer_size(tx1));
    mu_assert("Error: tx2 not empty", 0 == cbuffer_size(tx2));

    mu_assert("Error: 0xDEADBEEF != rx2.pop", 0xDEADBEEF == cbuffer_pop_front(rx2));
    mu_assert("Error: 0xBEEFCAFE != rx1.pop", 0xBEEFCAFE == cbuffer_pop_front(rx1));

    mu_assert("Error: rx2 not empty", 0 == cbuffer_size(rx2));
    mu_assert("Error: rx1 not empty", 0 == cbuffer_size(rx1));


    // free memory
    vmestream_destroy(test1);
    free(test2);
    cbuffer_free(tx1);
    cbuffer_free(rx1);
    cbuffer_free(tx2);
    cbuffer_free(rx2);

    return 0;
}
int main() {
  xil_printf("Master SPI oRSC echo test\n");
  // initialize stdout.
  init_platform();

  tx_buffer = cbuffer_new();
  rx_buffer = cbuffer_new();

  vme_stream = vmestream_initialize_mem(
          rx_buffer, tx_buffer, 
          (uint32_t*)ORSC_2_PC_SIZE,
          (uint32_t*)PC_2_ORSC_SIZE,
          (uint32_t*)ORSC_2_PC_DATA,
          (uint32_t*)PC_2_ORSC_DATA,
          VMERAMSIZE);

  //printf("Master SPI oRSC echo test\n");

  while (1) {
      // transfer data
      vmestream_transfer_data(vme_stream);
      // now echo the data
      while (cbuffer_size(rx_buffer) && cbuffer_freespace(tx_buffer)) {
          cbuffer_push_back(tx_buffer, cbuffer_pop_front(rx_buffer));
      }
  }

  return 0;
}
示例#9
0
// Test decoding + re-encoding a transaction stream
static char* test_ipbus_decode_encode_transaction(void) {
  CircularBuffer* packet = cbuffer_new();
  // a read request.
  uint32_t header = ipbus_transaction_header(
      2, // protocol
      0xACE, // transaction id
      5, // number of words to read
      IPBUS_READ,
      IPBUS_INFO_REQUEST);
  uint32_t payload = 0xBEEFFACE;

  cbuffer_push_back_net(packet, header);
  cbuffer_push_back_net(packet, payload);

  ipbus_transaction_t decoded = ipbus_decode_transaction(packet, 0);

  CircularBuffer* encoded = cbuffer_new();
  ipbus_encode_transaction(encoded, &decoded, 0);

  mu_assert_eq("encode-decode length", cbuffer_size(encoded), 2);

  mu_assert("encode-decode", memcmp(encoded->data, packet->data, 8)==0);

  return 0;
}
示例#10
0
static char* test_ipbus_decode_encode_write_transaction(void) {
  CircularBuffer* packet = cbuffer_new();
  // a read request.
  uint32_t header = ipbus_transaction_header(
      2, // protocol
      0xACE, // transaction id
      5, // number of words to write
      IPBUS_WRITE,
      IPBUS_INFO_REQUEST);
  uint32_t baseaddr = 0xBEEFFACE;

  cbuffer_push_back_net(packet, header);
  cbuffer_push_back_net(packet, baseaddr);
  for (size_t i = 0; i < 5; ++i) {
    cbuffer_push_back_net(packet, i);
  }

  ipbus_transaction_t decoded = ipbus_decode_transaction(packet, 0);

  CircularBuffer* encoded = cbuffer_new();
  ipbus_encode_transaction(encoded, &decoded, 0);

  mu_assert_eq("encode-decode length", cbuffer_size(encoded), 1 + 1 + 1 * 5);

  mu_assert("encode-decode", memcmp(encoded->data, packet->data, 7*4)==0);

  return 0;
}
static char * test_forwardingtransaction_handle_one_transaction(void) {
  // make two pipes to simulate the forwarding serial port.
  int txpipefd[2];
  pipe(txpipefd);

  int rxpipefd[2];
  pipe(rxpipefd);

  // make txpipe nonblocking, so we can check if it's empty.
  fcntl(txpipefd[0], F_SETFL, fcntl(txpipefd[0], F_GETFL) | O_NONBLOCK);

  initialize_fowarding_fds(txpipefd[1], rxpipefd[0]);

  CircularBuffer* input = cbuffer_new();
  cbuffer_push_back_net(input, ipbus_transaction_header(2, 0xCAB, 1, IPBUS_RMW, IPBUS_INFO_REQUEST));
  cbuffer_push_back_net(input, 0xBEEFCAFE);
  cbuffer_push_back_net(input, 0xDEAFBEEF);
  cbuffer_push_back_net(input, 0xFACEBEEF);
  // RMW expects 1+1 words back
  cbuffer_push_back_net(input, ipbus_transaction_header(2, 0xBAD, 5, IPBUS_READ, IPBUS_INFO_REQUEST));
  cbuffer_push_back_net(input, 0xBEEFCAFE);
  // READ expects 1+5 words back
  
  // write some junk onto the receiving pipe so we can check
  // we are reading the correct amount of return bytes.
  uint32_t junkwords[8] = {
    0xDEADBEEF, 0xBEEFCAFE, 
    0xFACEBEEF, 0x12345678, 0xDEADFACE, 0xBADEBEEF, 0x87654321, 0xABABABAB};
  write(rxpipefd[1], junkwords, 8 * sizeof(uint32_t));

  CircularBuffer* input_copy = cbuffer_copy(input);

  CircularBuffer* output = cbuffer_new();
  int words_consumed = handle_transaction_stream(input, 0, output);
  // should eat both transactions
  mu_assert_eq("ate everything i should", words_consumed, 6);

  // Make sure it passed it along the TX pipe
  ByteBuffer outputbuf = bytebuffer_ctor(NULL, 10 * sizeof(uint32_t));
  // should pass along only 6 words.
  read(txpipefd[0], outputbuf.buf, 10 * sizeof(uint32_t));
  mu_assert("forwarded trans", memcmp(outputbuf.buf, input_copy->data, 6*sizeof(uint32_t)) == 0);
  // there should no more data on the pipe
  mu_assert_eq("output pipe empty", read(txpipefd[0], outputbuf.buf, sizeof(uint32_t)), -1);

  // we expect header word + 1 payload word to be read from a RMW, 
  // 1 header + 5 data words from the READ
  mu_assert_eq("output size", cbuffer_size(output), 8);
  mu_assert_eq("output content header",  cbuffer_value_at(output, 0), 0xDEADBEEF);
  mu_assert_eq("output content payload", cbuffer_value_at(output, 1), 0xBEEFCAFE);
  mu_assert_eq("output content header 2", cbuffer_value_at(output, 2), 0xFACEBEEF);
  mu_assert_eq("output content payload 2", cbuffer_value_at(output, 3), 0x12345678);

  return 0;
}
示例#12
0
static char* test_cbuffer_new(void) {
  CircularBuffer* mybuf = cbuffer_new();
  mu_assert_eq("size", cbuffer_size(mybuf), 0);
  mu_assert_eq("pos", mybuf->pos, 0);
  mu_assert_eq("freespace", cbuffer_freespace(mybuf), IO_BUFFER_SIZE - 1);
  mu_assert_eq("init is zero", (mybuf->data[0]), 0);

  cbuffer_free(mybuf);

  return 0;
}
示例#13
0
static char* test_cbuffer_append(void) {
  CircularBuffer* mybuf = cbuffer_new();
  uint32_t test_data[5] = {0, 1, 2, 3, 4};
  cbuffer_append(mybuf, test_data, 5);
  mu_assert_eq("pos", mybuf->pos, 0);
  mu_assert_eq("size", cbuffer_size(mybuf), 5);
  mu_assert_eq("content", memcmp(mybuf->data, test_data, 5 * sizeof(uint32_t)), 0);

  uint32_t test_data2[3] = {6, 7, 8};
  cbuffer_append(mybuf, test_data2, 3);
  mu_assert_eq("pos", mybuf->pos, 0);
  mu_assert_eq("size", cbuffer_size(mybuf), 8);
  mu_assert_eq("content2", memcmp(mybuf->data, test_data, 5 * sizeof(uint32_t)), 0);

  mu_assert_eq("content3", memcmp(&(mybuf->data[5]), 
        test_data2, 3 * sizeof(uint32_t)), 0);

  cbuffer_free(mybuf);

  return 0;
}
示例#14
0
static char* test_spi_stream_construct_tx_packet(void) {
  
  uint32_t my_data[5] = {1, 2, 3, 4, 5};
  CircularBuffer* mybuf = cbuffer_new();
  cbuffer_append(mybuf, my_data, 5);

  uint32_t my_pkt_expected[10] = {0xBEEF, 5, 1, 2, 3, 4, 5, 0xDEADBEEF, 0xDEADBEEF, -1};
  add_checksum(my_pkt_expected, 10);
  int checksum_err = -1;
  spi_stream_verify_packet(my_pkt_expected, 10, &checksum_err);
  mu_assert_eq("no cksum err", checksum_err, 0);

  uint32_t my_pkt[10];
  spi_stream_construct_tx_packet(0xBEEF, my_pkt, 10, mybuf);

//  for (int i = 0; i < 10; ++i) {
//    printf("%i %lx %lx\n", i, my_pkt_expected[i], my_pkt[i]);
//  }

  mu_assert_eq("packet", memcmp(my_pkt_expected, my_pkt, 10 * sizeof(uint32_t)), 0);
  mu_assert_eq("consumed", cbuffer_size(mybuf), 0);

  // put more in the buffer than we can consume at once
  cbuffer_append(mybuf, my_data, 5);
  cbuffer_append(mybuf, my_data, 5);
  cbuffer_append(mybuf, my_data, 5);

  uint32_t my_pkt_expected_2[10] = {0xBEEF, 7, 1, 2, 3, 4, 5, 1, 2, -1};
  add_checksum(my_pkt_expected_2, 10);
  spi_stream_verify_packet(my_pkt_expected_2, 10, &checksum_err);
  mu_assert_eq("no cksum err 2", checksum_err, 0);

  spi_stream_construct_tx_packet(0xBEEF, my_pkt, 10, mybuf);
  mu_assert_eq("packet", memcmp(my_pkt_expected_2, my_pkt, 10 * sizeof(uint32_t)), 0);
  mu_assert_eq("consumed", cbuffer_size(mybuf), 8);

  spi_stream_verify_packet(my_pkt, 10, &checksum_err);
  mu_assert_eq("no cksum actual", checksum_err, 0);
  return 0;
}
示例#15
0
static char* test_cbuffer_delete_front_wraps(void) {
  CircularBuffer* mybuf = cbuffer_new();
  uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  // put us at the end of the buffer
  mybuf->pos = IO_BUFFER_SIZE - 5;
  mybuf->tail = IO_BUFFER_SIZE - 5;
  cbuffer_append(mybuf, test_data, 11);
  mu_assert_eq("content", memcmp(&(mybuf->data[mybuf->pos]), 
        test_data, 5 * sizeof(uint32_t)), 0);
  int deleted = cbuffer_deletefront(mybuf, 5);
  mu_assert_eq("deleted", deleted, 5);
  mu_assert_eq("pos", mybuf->pos, 0);
  mu_assert_eq("size", cbuffer_size(mybuf), 6);

  mu_assert_eq("item0", mybuf->data[mybuf->pos], 5);
  mu_assert_eq("item1", mybuf->data[mybuf->pos+1], 6);
  mu_assert_eq("item2", mybuf->data[mybuf->pos+2], 7);

  mu_assert_eq("remaining content in cbuffer", memcmp(
        &(mybuf->data[0]), 
        test_data + 5, 6 * sizeof(uint32_t)), 0);

  Buffer* readout = buffer_new(NULL, 6);
  cbuffer_read(mybuf, readout->data, 6);
  mu_assert_eq("remaining content", memcmp(
        readout->data, 
        (test_data + 5), 
        6 * sizeof(uint32_t)), 0);

  // if we ask to delete everything, just return what was actually deleted.
  int deleted_just_to_end = cbuffer_deletefront(mybuf, 100);
  mu_assert_eq("deleted just to end", deleted_just_to_end, 6);
  mu_assert_eq("pos2", mybuf->pos, 6);
  mu_assert_eq("size2", cbuffer_size(mybuf), 0);

  cbuffer_free(mybuf);
  buffer_free(readout);

  return 0;
}
示例#16
0
static char* test_cbuffer_freespace(void) {
  CircularBuffer* mybuf = cbuffer_new();
  mybuf->tail = IO_BUFFER_SIZE - 5;
  mu_assert_eq("freespace", cbuffer_freespace(mybuf), 4);
  mu_assert_eq("size", cbuffer_size(mybuf), IO_BUFFER_SIZE - 5);
  for (int i = 1; i < 5; ++i) {
    cbuffer_push_back(mybuf, i);
    mu_assert_eq("freespace", cbuffer_freespace(mybuf), 4 - i);
  }

  cbuffer_free(mybuf);

  return 0;
}
示例#17
0
static char* test_cbuffer_fd_full(void) {
  // make sure we can stop reading if our read buffer is full
  // make pipes 
  int pipefd[2];
  pipe(pipefd);

  // make txpipe nonblocking, so we can check if it's empty.
  fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);

  int in = pipefd[1];
  int out = pipefd[0];

  CircularBuffer* frombuf = cbuffer_new();
  for (int i = 0; i < 200; ++i) {
    cbuffer_push_back(frombuf, i);
  }
  mu_assert_eq("from size", cbuffer_size(frombuf), 200);

  CircularBuffer* tobuf = cbuffer_new();
  tobuf->pos = IO_BUFFER_SIZE - 100;
  tobuf->tail = IO_BUFFER_SIZE - 100;

  ssize_t written = cbuffer_write_fd(frombuf, in, 200);
  mu_assert_eq("wrote to pipe", written, 200);
  mu_assert_eq("from size after", cbuffer_size(frombuf), 0);
  tobuf->tail += IO_BUFFER_SIZE - 100;
  mu_assert_eq("to freespace", cbuffer_freespace(tobuf), 99);
  ssize_t read = cbuffer_read_fd(tobuf, out, 200);
  ssize_t exp = 99;
  mu_assert_eq("read from pipe", (int)read, (int)exp);

  cbuffer_free(frombuf);
  cbuffer_free(tobuf);

  return 0;
}
示例#18
0
static char* test_cbuffer_fd_features(void) {
  // make pipes 
  int pipefd[2];
  pipe(pipefd);

  // make txpipe nonblocking, so we can check if it's empty.
  fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);

  int in = pipefd[1];
  int out = pipefd[0];

  CircularBuffer* frombuf = cbuffer_new();
  for (int i = 0; i < 200; ++i) {
    cbuffer_push_back(frombuf, i);
  }
  mu_assert_eq("from size", cbuffer_size(frombuf), 200);

  CircularBuffer* tobuf = cbuffer_new();
  tobuf->pos = IO_BUFFER_SIZE - 100;
  tobuf->tail = IO_BUFFER_SIZE - 100;

  ssize_t written = cbuffer_write_fd(frombuf, in, 200);
  mu_assert_eq("wrote to pipe", written, 200);
  mu_assert_eq("from size after", cbuffer_size(frombuf), 0);
  ssize_t read = cbuffer_read_fd(tobuf, out, 200);
  mu_assert_eq("read from pipe", read, 200);

  for (int i = 0; i < 200; ++i) {
    mu_assert_eq("fd closure value", cbuffer_value_at(tobuf, i), i);
  }

  cbuffer_free(frombuf);
  cbuffer_free(tobuf);

  return 0;
}
示例#19
0
void SendHandler(void *CallBackRef, unsigned int EventData) {
  // delete the bytes which were sent previously
  if (EventData % sizeof(uint32_t)) {
    LOG_DEBUG("ERROR: sent data not word aligned!!!\n");
  }
  cbuffer_deletefront(tx_buffer, EventData / sizeof(uint32_t));
  if (cbuffer_size(tx_buffer)) {
    unsigned int to_send = cbuffer_contiguous_data_size(tx_buffer) * sizeof(uint32_t);
    XUartLite_Send(&UartLite, (u8*)&(tx_buffer->data[tx_buffer->pos]), to_send);
    LOG_DEBUG("SendHandler _Send  %x\n", to_send);
    currently_sending = 1;
  } else {
    LOG_DEBUG("SendHandler Idling\n");
    currently_sending = 0;
  }
  LOG_DEBUG("SendHandler SENT INTR %x\n", EventData);
}
示例#20
0
static char* test_cbuffer_copy(void) {
  CircularBuffer* mybuf = cbuffer_new();
  mu_assert_eq("size", cbuffer_size(mybuf), 0);
  mu_assert_eq("pos", mybuf->pos, 0);
  mu_assert_eq("tail", mybuf->tail, 0);
  for (uint32_t i = 0; i < IO_BUFFER_SIZE - 2; ++i) {
    cbuffer_push_back(mybuf, i);
  }
  mu_assert_eq("tail", mybuf->tail, IO_BUFFER_SIZE - 2);
  CircularBuffer* copy = cbuffer_copy(mybuf);
  mu_assert_eq("content", memcmp(mybuf->data, copy->data, 
        IO_BUFFER_SIZE * sizeof(uint32_t)), 0);
  mu_assert_eq("pos copy", mybuf->pos, copy->pos);
  mu_assert_eq("tail copy", mybuf->tail, copy->tail);

  cbuffer_free(mybuf);
  cbuffer_free(copy);

  return 0;
}
示例#21
0
static char* test_cbuffer_push_back(void) {
  CircularBuffer* mybuf = cbuffer_new();
  // put us at the end of the buffer
  mybuf->pos = IO_BUFFER_SIZE - 2;
  mybuf->tail = IO_BUFFER_SIZE - 2;
  cbuffer_push_back(mybuf, 0xDEADBEEF);
  cbuffer_push_back(mybuf, 0xBEEFFACE);
  cbuffer_push_back(mybuf, 0xDEADFACE);

  mu_assert_eq("size", cbuffer_size(mybuf), 3);
  mu_assert_eq("pos", mybuf->pos, IO_BUFFER_SIZE-2);

  mu_assert_eq("item0", mybuf->data[mybuf->pos], 0xDEADBEEF);
  mu_assert_eq("item1", mybuf->data[mybuf->pos + 1], 0xBEEFFACE);
  mu_assert_eq("item2", mybuf->data[0], 0xDEADFACE);

  cbuffer_free(mybuf);

  return 0;
}
示例#22
0
static char* test_cbuffer_pop_front(void) {
  CircularBuffer* mybuf = cbuffer_new();
  // put us at the end of the buffer
  mybuf->pos = IO_BUFFER_SIZE - 5;
  mybuf->tail = IO_BUFFER_SIZE - 5;
  uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  cbuffer_append(mybuf, test_data, 11);

  for (int i = 0; i < 11; i++) {
    mu_assert_eq("pre-pop size", cbuffer_size(mybuf), 11 - i);
    uint32_t value = cbuffer_pop_front(mybuf);
    mu_assert_eq("popped_content", (int)value, i);
  }

  // if we pop an empty collection, we get dead beef.
  uint32_t empty = cbuffer_pop_front(mybuf);
  mu_assert_eq("empty", empty, 0xDEADBEEF);

  cbuffer_free(mybuf);

  return 0;
}
示例#23
0
/*
 * Make sure cbuffer_fd_read handles the edge case where cbuffer->tail returns
 * to the front of buffer->data
 */
static char* test_cbuffer_fd_read_edge(void) {
  int pipefd[2];
  pipe(pipefd);

  fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);

  int in = pipefd[1];
  int out = pipefd[0];

  CircularBuffer* mybuf = cbuffer_new();

  // completely fill buffer
  while (cbuffer_freespace(mybuf) > 0) {
    mu_assert_eq("mybuf overflow", cbuffer_push_back(mybuf, 0xDEADBEEF), 0);
  }
  mu_assert_eq("mybuf still has free space", cbuffer_freespace(mybuf), 0);

  // clear a single space in the cbuffer
  // free space should be at the front of cbuffer->data
  cbuffer_deletefront(mybuf, 1);

  uint32_t inbuf[] = {0xCAFEBABE};
  write(in, inbuf, sizeof(uint32_t));

  // read a single word into the free slot in the buffer
  mu_assert_eq("Could not read data", cbuffer_read_fd(mybuf, out, 1), 1);

  // check the content of the cbuffer
  while (cbuffer_size(mybuf) > 1) {
    mu_assert_eq("Content should be 0xDEADBEEF",
        cbuffer_pop_front(mybuf), 0xDEADBEEF);
  }
  mu_assert_eq("Content should be 0xCAFEBABE",
      cbuffer_pop_front(mybuf), 0xCAFEBABE);

  cbuffer_free(mybuf);
  return 0;
}
示例#24
0
int main(void) {

  LOG_INFO("UART CTP FE echo test\n");

  init_platform();

  tx_buffer = cbuffer_new();
  rx_buffer = cbuffer_new();

  int Status;
  u16 DeviceId = UARTLITE_DEVICE_ID;     

  /*
   * Initialize the UartLite driver so that it's ready to use.
   */
  Status = XUartLite_Initialize(&UartLite, DeviceId);
  if (Status != XST_SUCCESS) {
    LOG_ERROR ("Error: could not initialize UART\n");
      return XST_FAILURE;
  }

  XUartLite_ResetFifos(&UartLite);

  /*
   * Perform a self-test to ensure that the hardware was built correctly.
   */
  Status = XUartLite_SelfTest(&UartLite);
  if (Status != XST_SUCCESS) {
    LOG_ERROR ("Error: self test failed\n");
      return XST_FAILURE;
  }

  /*
   * Connect the UartLite to the interrupt subsystem such that interrupts can
   * occur. This function is application specific.
   */
  Status = SetupInterruptSystem(&UartLite);
  if (Status != XST_SUCCESS) {
    LOG_ERROR ("Error: could not setup interrupts\n");
      return XST_FAILURE;
  }

  /*
   * Setup the handlers for the UartLite that will be called from the
   * interrupt context when data has been sent and received, specify a
   * pointer to the UartLite driver instance as the callback reference so
   * that the handlers are able to access the instance data.
   */
  XUartLite_SetSendHandler(&UartLite, SendHandler, &UartLite);
  XUartLite_SetRecvHandler(&UartLite, RecvHandler, &UartLite);

  /*
   * Enable the interrupt of the UartLite so that interrupts will occur.
   */
  XUartLite_EnableInterrupt(&UartLite);

  // bootstrap the READ
  LOG_DEBUG("Bootstrapping READ\n");
  XUartLite_Recv(&UartLite, (u8*)&rx_tmp_buffer, sizeof(uint32_t));

  LOG_INFO("Starting loop\n");

  /*  
  LOG_DEBUG("Sending 'wtf!'\n");
  currently_sending = 1;
  char help[4] = "wtf!";
  unsigned int ret = XUartLite_Send(&UartLite, (u8*)help, 4);
  LOG_DEBUG("WTF send complete return: %x\n", ret);
  */

  /* echo received data forever */
  unsigned int heartbeat = 0;
  while (1) {
    if (heartbeat++ % (1 << 8)) {
      //LOG_DEBUG("bump %x\n", heartbeat);
    }
    while (cbuffer_size(rx_buffer) && cbuffer_freespace(tx_buffer)) {
      uint32_t data = cbuffer_pop_front(rx_buffer);
      //LOG_DEBUG("Echoing data word %x\n", data);
      cbuffer_push_back(tx_buffer, data);
    }
    if (!currently_sending && cbuffer_size(tx_buffer)) {
      LOG_DEBUG("\nREINT SEND\n");
      currently_sending = 1;

      /* 
      if (XUartLite_IsSending(&UartLite)) {
        LOG_DEBUG("UART STAT: sending\n");
      } else {
        LOG_DEBUG("UART STAT: idle\n");
      }
      */

      unsigned int to_send = cbuffer_contiguous_data_size(tx_buffer) * sizeof(uint32_t);
      u8* output_ptr = (u8*)&(tx_buffer->data[tx_buffer->pos]);
      //LOG_DEBUG("REINIT %x\n", to_send);
      //LOG_DEBUG("SENDADDR %x\n", output_ptr);
      XUartLite_Send(&UartLite, output_ptr, to_send);
    }
  }

}
示例#25
0
int main(int argc, char *argv[]) {
  caught_termination = 0;
  if (signal(SIGINT, sig_handler) == SIG_ERR) {
    LOG_ERROR("Can't catch SIGINT");
  }
  if (signal(SIGTERM, sig_handler) == SIG_ERR) {
    LOG_ERROR("Can't catch SIGTERM");
  }
  if (argc < 3) {
    LOG_ERROR("Usage: %s /dev/input /dev/output", argv[0]);
    return 1;
  }
  char * inputdevice = argv[1];
  char * outputdevice = argv[2];

  // initialize mapped memory block
  membase_init();

  LOG_INFO("serving memory @ %016" PRIxPTR " via %s-> ->%s", 
      (uintptr_t)membase, inputdevice, outputdevice);

  int inputdevicefd = open(inputdevice, O_RDWR | O_NONBLOCK);
  // in general these are probably the same.
  int outputdevicefd = inputdevicefd;
  // but maybe not.
  if (strcmp(inputdevice, outputdevice) != 0) {
    outputdevicefd = open(outputdevice, O_RDWR | O_NONBLOCK);
  }

  Client client;
  client.inputstream = cbuffer_new();
  client.outputstream = cbuffer_new();
  client.inputfd = inputdevicefd;
  client.outputfd = outputdevicefd;
  client.byte2word = bytebuffer_ctor(NULL, 0);
  client.swapbytes = 0;

  while (1) {
    if (caught_termination) {
      break;
    }

    bytebuffer_read_fd(
        &(client.byte2word), client.inputfd, MAX_REQ_LEN);
    if (client.byte2word.bufsize > 0) {
      LOG_DEBUG("Processing %i bytes", client.byte2word.bufsize);
      // Data available!  Process the request.
      CircularBuffer *clibuf = client.inputstream;
      ByteBuffer* byte2word = &(client.byte2word);
      size_t nwords = byte2word->bufsize / sizeof(uint32_t);
      int append_ret = cbuffer_append(clibuf, byte2word->buf, nwords);
      if (append_ret == 0) {
        bytebuffer_del_front(byte2word, nwords * sizeof(uint32_t));
      }
      ipbus_process_input_stream(&client);
      // write out any response
      cbuffer_write_fd(client.outputstream,
          client.outputfd,
          cbuffer_size(client.outputstream));
    }
  }

  if (inputdevicefd != outputdevicefd) {
    close(outputdevicefd);
  }
  close(inputdevicefd);
  membase_close();
  LOG_INFO("goodbye!\n");
  return 0; 
}
示例#26
0
/* Returns number of free elements*/
uint64_t cbuffer_available(CircularBuffer *cb)
{
    return (cbuffer_size(cb) - cbuffer_used(cb));
}
示例#27
0
int main() {

  xil_printf("Master SPI oRSC echo test\n");

  // initialize stdout.
  init_platform();

  tx_buffer = cbuffer_new();
  rx_buffer = cbuffer_new();

  spi_stream = spi_stream_init(
      tx_buffer, rx_buffer, 
      DoSpiTransfer, // callback which triggers a SPI transfer
      0);

  int Status;
  XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */

  /*
   * Initialize the SPI driver so that it is  ready to use.
   */
  ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
  if (ConfigPtr == NULL) {
    xil_printf ("Error: could not lookup SPI configuration\n");
    return XST_DEVICE_NOT_FOUND;
  }

  Status = XSpi_CfgInitialize(&SpiInstance, ConfigPtr,
      ConfigPtr->BaseAddress);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: could not initialize the SPI device\n");
    return XST_FAILURE;
  }

  Status = XSpi_SelfTest(&SpiInstance);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: The SPI self test failed.\n");
    return XST_FAILURE;
  }

  /*
   * Connect the Spi device to the interrupt subsystem such that
   * interrupts can occur. This function is application specific.
   */
  Status = SpiSetupIntrSystem(&IntcInstance, &SpiInstance, SPI_IRPT_INTR);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: Could not setup interrupt system.\n");
    return XST_FAILURE;
  }

  /*
   * Set the Spi device as a master.
   */
  Status = XSpi_SetOptions(&SpiInstance, XSP_MASTER_OPTION);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: Could not set as master\n");
    return XST_FAILURE;
  }

  // Go!
  XSpi_Start(&SpiInstance);

  // Note: to disable interrupt, do: XIntc_Disconnect(&IntcInstance,
  // SPI_IRPT_INTR);

  u32 expected_rx = 0;
  u32 current_tx = 0;

  while (1) {
    // fill up the transmit buffer
    while (cbuffer_freespace(tx_buffer)) {
      cbuffer_push_back(tx_buffer, current_tx++);
    }
    // check to make sure the received buffer is what we expect
    while (cbuffer_size(rx_buffer)) {
      u32 front = cbuffer_value_at(rx_buffer, 0);
      if (front != expected_rx) {
        //xil_printf("Error: expected %lx, got %lx!\n", expected_rx, front);
        xil_printf("Error: data value\n");
      }
      expected_rx++;
      cbuffer_deletefront(rx_buffer, 1);
    }
  }

  return 0;
}
示例#28
0
static char* test_ram1()
{
    CircularBuffer* pc_input    = cbuffer_new();
    CircularBuffer* pc_output   = cbuffer_new();
    CircularBuffer* orsc_input  = cbuffer_new();
    CircularBuffer* orsc_output = cbuffer_new();

    VMEStream *pc_stream = vmestream_initialize_heap(pc_input, pc_output, 1);

    VMEStream *orsc_stream = malloc(sizeof(VMEStream));
    orsc_stream->input              = orsc_input;
    orsc_stream->output             = orsc_output;
    orsc_stream->local_send_size    = pc_stream->remote_send_size;
    orsc_stream->local_recv_size    = pc_stream->remote_recv_size;
    orsc_stream->remote_send_size   = pc_stream->local_send_size;
    orsc_stream->remote_recv_size   = pc_stream->local_recv_size;
    orsc_stream->recv_data          = pc_stream->send_data;
    orsc_stream->send_data          = pc_stream->recv_data;
    orsc_stream->MAXRAM             = pc_stream->MAXRAM;

    for (uint32_t i = 0; i < 20; ++i) {
        cbuffer_push_back(pc_input, 0xDEADBEEF + i);
        cbuffer_push_back(orsc_input, 0xBEEFCAFE + i);
    }

    // initial transfer
    vmestream_transfer_data(pc_stream);

    // transfer data
    vmestream_transfer_data(orsc_stream);
    vmestream_transfer_data(pc_stream);

    mu_assert("Error: orsc_output.pop != DEADBEEF", cbuffer_pop_front(orsc_output) == 0xDEADBEEF);
    mu_assert("Error: pc_output.pop != BEEFCAFE", cbuffer_pop_front(pc_output) == 0xBEEFCAFE);

    // extra transfer is needed to reset the size registers
    // to zero to prepare for another transfer
    vmestream_transfer_data(orsc_stream);
    vmestream_transfer_data(pc_stream);

    // transfer data
    vmestream_transfer_data(orsc_stream);
    vmestream_transfer_data(pc_stream);

    mu_assert("Error: orsc_output.pop != DEADBEEF + 1", cbuffer_pop_front(orsc_output) == 0xDEADBEEF + 1);
    mu_assert("Error: pc_output.pop != BEEFCAFE + 1", cbuffer_pop_front(pc_output) == 0xBEEFCAFE + 1);

    /*
    printf("pc_output.size: %d\n", cbuffer_size(pc_output));
    printf("orsc_output.size: %d\n", cbuffer_size(orsc_output));
    printf("pc_input.size: %d\n", cbuffer_size(pc_input));
    printf("orsc_input.size: %d\n", cbuffer_size(orsc_input));
    */

    mu_assert("Error: pc_output.size != 0", cbuffer_size(pc_output) == 0);
    mu_assert("Error: orsc_output.size != 0", cbuffer_size(orsc_output) == 0);
    mu_assert("Error: pc_input.size != 18", cbuffer_size(pc_input) == 18);
    mu_assert("Error: orsc_input.size != 18", cbuffer_size(orsc_input) == 18);

    // transfer on pc_stream 2x in a row. Nothing should happen.
    vmestream_transfer_data(pc_stream);
    mu_assert("Error: pc_output.size != 0", cbuffer_size(pc_output) == 0);
    mu_assert("Error: orsc_output.size != 0", cbuffer_size(orsc_output) == 0);
    mu_assert("Error: pc_input.size != 18", cbuffer_size(pc_input) == 18);
    mu_assert("Error: orsc_input.size != 18", cbuffer_size(orsc_input) == 18);

    // reset
    vmestream_transfer_data(orsc_stream);
    vmestream_transfer_data(pc_stream);

    vmestream_transfer_data(orsc_stream);
    mu_assert("Error: pc_output.size != 0", cbuffer_size(pc_output) == 0);
    mu_assert("Error: orsc_output.size != 1", cbuffer_size(orsc_output) == 1);
    mu_assert("Error: pc_input.size != 17", cbuffer_size(pc_input) == 17);
    mu_assert("Error: orsc_input.size != 17", cbuffer_size(orsc_input) == 17);

    vmestream_destroy_heap(pc_stream);
    free(orsc_stream);
    cbuffer_free(pc_input);
    cbuffer_free(orsc_input);
    cbuffer_free(pc_output);
    cbuffer_free(orsc_output);

    return 0;
}
示例#29
0
static char *test_ram1()
{
    // local application buffers
    CircularBuffer *tx1 = cbuffer_new();
    CircularBuffer *rx1 = cbuffer_new();
    CircularBuffer *tx2 = cbuffer_new();
    CircularBuffer *rx2 = cbuffer_new();

    VMEStream *test1 = vmestream_initialize(tx1, rx1, 1);
    VMEStream *test2 = malloc(sizeof(VMEStream));
    test2->input = tx2;
    test2->output = rx2;

    test2->rx_size = test1->tx_size;
    test2->tx_size = test1->rx_size;
    test2->rx_data = test1->tx_data;
    test2->tx_data = test1->rx_data;
    test2->MAXRAM  = test1->MAXRAM;

    for (unsigned int i = 0; i < 20; ++i) {
        // put some output data on host #1
        cbuffer_push_back(tx1, 0xDEADBEEF + i);
        // put some output data on host #2
        cbuffer_push_back(tx2, 0xBEEFCAFE + i);
    }

    // do a transfer
    vmestream_transfer_data(test1); // step 1 
    vmestream_transfer_data(test2); // step 2

    // host #2 has received data, since host #1 filled it's TX buffer in step 1
    // and host #2 can read it out in step 2
    mu_assert("Error: 0xDEADBEEF != rx2.pop", 0xDEADBEEF == cbuffer_pop_front(rx2));

    vmestream_transfer_data(test1); // step 3
    // now host #1 can read the data loaded by host #2 in step 2
    mu_assert("Error: 0xBEEFCAFE != rx1.pop", 0xBEEFCAFE == cbuffer_pop_front(rx1));

    // do another transfer
    vmestream_transfer_data(test2);
    vmestream_transfer_data(test1);

    mu_assert("Error: 0xBEEFCAFE+1 != rx1.pop", 0xBEEFCAFE + 1 == cbuffer_pop_front(rx1));
    mu_assert("Error: 0xDEADBEEF+1 != rx2.pop", 0xDEADBEEF + 1 == cbuffer_pop_front(rx2));

    // We have consumed all received data (via pop).  There is a word of 
    // data in limbo for host #1
    mu_assert("Error: 0 != rx1.size", 0 == cbuffer_size(rx1));
    mu_assert("Error: 0 != rx2.size", 0 == cbuffer_size(rx2));
    mu_assert("Error: 17 != tx1.size", 17 == cbuffer_size(tx1));
    mu_assert("Error: 18 != tx2.size", 18 == cbuffer_size(tx2));

    // call transfer on #1 twice in a row.  Since it's still waiting for
    // #2 to read the data, nothing happens.
    vmestream_transfer_data(test1);
    mu_assert("Error: 0 != rx1.size", 0 == cbuffer_size(rx1));
    mu_assert("Error: 0 != rx2.size", 0 == cbuffer_size(rx2));
    mu_assert("Error: 17 != tx1.size", 17 == cbuffer_size(tx1));
    mu_assert("Error: 18 != tx2.size", 18 == cbuffer_size(tx2));

    // #2 receives limbo data, puts one of it's words in limbo.
    vmestream_transfer_data(test2);
    mu_assert("Error: 0 != rx1.size", 0 == cbuffer_size(rx1));
    mu_assert("Error: 1 != rx2.size", 1 == cbuffer_size(rx2));
    mu_assert("Error: 17 != tx1.size", 17 == cbuffer_size(tx1));
    mu_assert("Error: 17 != tx2.size", 17 == cbuffer_size(tx2));


    // free memory
    vmestream_destroy(test1);
    free(test2);
    cbuffer_free(tx1);
    cbuffer_free(rx1);
    cbuffer_free(tx2);
    cbuffer_free(rx2);

    return 0;
}
示例#30
0
/**
 * Overload buffer test
 */
static char *test_buf()
{
    // local application buffers
    CircularBuffer *tx1 = cbuffer_new();
    CircularBuffer *rx1 = cbuffer_new();
    CircularBuffer *tx2 = cbuffer_new();
    CircularBuffer *rx2 = cbuffer_new();

    VMEStream *test1 = vmestream_initialize(tx1, rx1, 32);
    VMEStream *test2 = malloc(sizeof(VMEStream));
    test2->input = tx2;
    test2->output = rx2;

    test2->rx_size = test1->tx_size;
    test2->tx_size = test1->rx_size;
    test2->rx_data = test1->tx_data;
    test2->tx_data = test1->rx_data;
    test2->MAXRAM  = test1->MAXRAM;


    cbuffer_push_back(rx2, 0xDEADBEEF);
    for (int i = 0; i < 510; i++) {
        cbuffer_push_back(rx2, 0xBEEFCAFE);
    }
    cbuffer_push_back(tx1, 0xBEEFCAFE + 1);
    cbuffer_push_back(tx1, 0xBEEFCAFE + 2);
    cbuffer_push_back(tx1, 0xBEEFCAFE + 3);
    cbuffer_push_back(tx1, 0xBEEFCAFE + 4);

    mu_assert("Error: rx2 should have no space left", 
        cbuffer_freespace(rx2) == 0);
    // sanity check
    mu_assert_eq("Error: output size != 4", cbuffer_size(tx1), 4);

    // do several transfers
    vmestream_transfer_data(test1);
    vmestream_transfer_data(test2);
    vmestream_transfer_data(test1);
    vmestream_transfer_data(test2);

    // no data should have been transferred
    mu_assert_eq("Error: tx_size != 4", *(test1->tx_size), 4);
    mu_assert("Error: rx2.pop != 0xDEADBEEF", 0xDEADBEEF == cbuffer_pop_front(rx2));
    cbuffer_pop_front(rx2);
    cbuffer_pop_front(rx2);

    // popping off rx2 should have freed 3 words, but not enough to transfer all
    // four
    vmestream_transfer_data(test1);
    vmestream_transfer_data(test2);

    mu_assert_eq("Error: tx_size != 4", *(test1->tx_size), 4);
    mu_assert("Errrr: rx2.pop not 0xBEEFCAFE", 0xBEEFCAFE == cbuffer_pop_front(rx2));

    cbuffer_pop_front(rx2);
    // now there is enough room for all the limbo data to be transferred to rx2
    vmestream_transfer_data(test1);
    vmestream_transfer_data(test2);

    mu_assert("Error: tx_size != 0", *(test1->tx_size) == 0);
    mu_assert("Error: tx1 not empty", 0 == cbuffer_size(tx1));
    for (int i = 0; i < 4; ++i) {
      mu_assert_eq("Unexpected data transferred", 
          cbuffer_value_at(rx2, cbuffer_size(rx2) - 4 + i), 0xBEEFCAFE + i + 1);
    }


    // free memory
    vmestream_destroy(test1);
    free(test2);
    cbuffer_free(tx1);
    cbuffer_free(rx1);
    cbuffer_free(tx2);
    cbuffer_free(rx2);

    return 0;
}