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;
}
示例#2
0
static char* test_cbuffer_value_at_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);
  for (int i = 0; i < 11; ++i) {
    mu_assert_eq("read at", cbuffer_value_at(mybuf, i), test_data[i]);
  }

  cbuffer_free(mybuf);

  return 0;
}
示例#3
0
// read an IPbus transaction from a stream
ipbus_transaction_t ipbus_decode_transaction(const CircularBuffer *buf, int swapbytes) {
  ipbus_transaction_t output = ipbus_decode_transaction_header(buf, swapbytes);

  size_t words_read = 1;

  output.data.words = (uint32_t*)malloc(output.data.size * sizeof(uint32_t));

  for (unsigned int i = 0; i < output.data.size; ++i) {
    uint32_t dataword = network_to_host(cbuffer_value_at(buf, words_read)); 
    words_read += 1;
    if (swapbytes) {
      dataword = __bswap_32(dataword);
    }
    output.data.words[i] = dataword;
  }
  return output;
}
示例#4
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;
}
示例#5
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;
}
示例#6
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;
}