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; }
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; }
// 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; }
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; }
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; }
/** * 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; }