From f9560f62dd58bba896195a3e198fd131a52b0ee4 Mon Sep 17 00:00:00 2001 From: ultraembedded Date: Sun, 31 May 2015 17:49:57 +0100 Subject: [PATCH] Add some test SW for verifying FTDI Async interface --- ftdi_async_bridge/sw/ftdi_hw.c | 275 +++++++++++++++++++++++++++++++++ ftdi_async_bridge/sw/ftdi_hw.h | 26 ++++ ftdi_async_bridge/sw/makefile | 31 ++++ ftdi_async_bridge/sw/test.c | 141 +++++++++++++++++ 4 files changed, 473 insertions(+) create mode 100644 ftdi_async_bridge/sw/ftdi_hw.c create mode 100644 ftdi_async_bridge/sw/ftdi_hw.h create mode 100644 ftdi_async_bridge/sw/makefile create mode 100644 ftdi_async_bridge/sw/test.c diff --git a/ftdi_async_bridge/sw/ftdi_hw.c b/ftdi_async_bridge/sw/ftdi_hw.c new file mode 100644 index 0000000..551bc1e --- /dev/null +++ b/ftdi_async_bridge/sw/ftdi_hw.c @@ -0,0 +1,275 @@ +#include +#include + +#include "ftdi_hw.h" + +//----------------------------------------------------------------- +// Defines: +//----------------------------------------------------------------- +#define CMD_NOP 0x0 +#define CMD_WR 0x1 +#define CMD_RD 0x2 +#define CMD_GP_WR 0x3 +#define CMD_GP_RD 0x4 + +#define MAX_TX_SIZE 2048 +#define HDR_SIZE 6 + +#define FTDI_PID 0x0403 +#define FTDI_VID 0x6010 + +//----------------------------------------------------------------- +// Locals: +//----------------------------------------------------------------- +static struct ftdi_context *_handle; + +//----------------------------------------------------------------- +// ftdi_hw_init: +//----------------------------------------------------------------- +int ftdi_hw_init(int interface) +{ + int status; + + _handle = ftdi_new(); + if (!_handle) + return -1; + + // Open channel + ftdi_set_interface(_handle, interface ? INTERFACE_B : INTERFACE_A); + status = ftdi_usb_open(_handle, FTDI_PID, FTDI_VID); + if (status != 0) + { + ftdi_free(_handle); + _handle = NULL; + return -1; + } + + // Reset FTDI + status = ftdi_usb_reset(_handle); + if (status != 0) + { + ftdi_usb_close(_handle); + ftdi_free(_handle); + _handle = NULL; + return -1; + } + + // Flush buffers + status = ftdi_usb_purge_buffers(_handle); + if (status != 0) + { + ftdi_usb_close(_handle); + ftdi_free(_handle); + _handle = NULL; + return -1; + } + + // Set transfer mode + status = ftdi_set_bitmode(_handle, 0xFF, BITMODE_RESET); + if (status != 0) + { + ftdi_usb_close(_handle); + ftdi_free(_handle); + _handle = NULL; + return -1; + } + + return 0; +} +//----------------------------------------------------------------- +// ftdi_hw_close: +//----------------------------------------------------------------- +int ftdi_hw_close(void) +{ + if (_handle) + { + ftdi_usb_close(_handle); + ftdi_free(_handle); + _handle = NULL; + } + + return 0; +} +//----------------------------------------------------------------- +// ftdi_hw_mem_write: +//----------------------------------------------------------------- +int ftdi_hw_mem_write(uint32_t addr, uint8_t *data, int length) +{ + int i; + int sent = 0; + int size = length; + int res; + uint8_t buffer[MAX_TX_SIZE + HDR_SIZE]; + uint8_t *p; + + while (sent < length) + { + size = (length - sent); + if (size > MAX_TX_SIZE) + size = MAX_TX_SIZE; + + // Build packet header + p = buffer; + *p++ = (((size >> 8) & 0xF) << 4) | CMD_WR; + *p++ = (size & 0xFF); + + *p++ = (addr >> 24); + *p++ = (addr >> 16); + *p++ = (addr >> 8); + *p++ = (addr >> 0); + + // Fill packet payload + for (i=0;i MAX_TX_SIZE) + size = MAX_TX_SIZE; + + // Round up to nearest 4 byte multiple + size = (size + 3) & ~3; + + // Build packet header + p = buffer; + *p++ = (((size >> 8) & 0xF) << 4) | CMD_RD; + *p++ = (size & 0xFF); + + *p++ = (addr >> 24); + *p++ = (addr >> 16); + *p++ = (addr >> 8); + *p++ = (addr >> 0); + + // Write request to FTDI device + res = ftdi_write_data(_handle, buffer, HDR_SIZE); + if (res != HDR_SIZE) + { + fprintf(stderr, "ftdi_hw_mem_read: Failed to send request\n"); + return -1; + } + + remain = size; + do + { + res = ftdi_read_data(_handle, data, remain); + if (res < 0) + { + fprintf(stderr, "ftdi_hw_mem_read: Failed to read data\n"); + return -1; + } + + remain -= res; + data += res; + } + while (remain > 0); + + received += size; + addr += size; + } + + return received; +} +//----------------------------------------------------------------- +// ftdi_hw_mem_write_word: +//----------------------------------------------------------------- +int ftdi_hw_mem_write_word(uint32_t addr, uint32_t data) +{ + uint8_t buffer[4]; + + buffer[3] = (data >> 24); + buffer[2] = (data >> 16); + buffer[1] = (data >> 8); + buffer[0] = (data >> 0); + + return ftdi_hw_mem_write(addr, buffer, 4); +} +//----------------------------------------------------------------- +// ftdi_hw_mem_read_word: +//----------------------------------------------------------------- +int ftdi_hw_mem_read_word(uint32_t addr, uint32_t *data) +{ + uint8_t buffer[4]; + + int res = ftdi_hw_mem_read(addr, buffer, 4); + if (res > 0) + { + (*data) = ((uint32_t)buffer[3]) << 24; + (*data)|= ((uint32_t)buffer[2]) << 16; + (*data)|= ((uint32_t)buffer[1]) << 8; + (*data)|= ((uint32_t)buffer[0]) << 0; + } + return res; +} +//----------------------------------------------------------------- +// ftdi_hw_gpio_write: +//----------------------------------------------------------------- +int ftdi_hw_gpio_write(uint8_t value) +{ + uint8_t buffer[2] = { CMD_GP_WR, value }; + + // Write request to FTDI device + int res = ftdi_write_data(_handle, buffer, sizeof(buffer)); + if (res != sizeof(buffer)) + { + fprintf(stderr, "ftdi_hw_mem_write: Failed to send\n"); + return -1; + } + + return 0; +} +//----------------------------------------------------------------- +// ftdi_hw_gpio_read: +//----------------------------------------------------------------- +int ftdi_hw_gpio_read(uint8_t *value) +{ + // Write request to FTDI device + uint8_t request = CMD_GP_RD; + int res = ftdi_write_data(_handle, &request, 1); + if (res != 1) + { + fprintf(stderr, "ftdi_hw_mem_write: Failed to send\n"); + return -1; + } + + // Poll for response + do + { + res = ftdi_read_data(_handle, value, 1); + if (res < 0) + { + fprintf(stderr, "ftdi_hw_mem_read: Failed to read data\n"); + return -1; + } + } + while (res != 1); + + return 0; +} diff --git a/ftdi_async_bridge/sw/ftdi_hw.h b/ftdi_async_bridge/sw/ftdi_hw.h new file mode 100644 index 0000000..c995b61 --- /dev/null +++ b/ftdi_async_bridge/sw/ftdi_hw.h @@ -0,0 +1,26 @@ +#ifndef _FTDI_HW_H_ +#define _FTDI_HW_H_ + +#include + +//----------------------------------------------------------------- +// Defines: +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Prototypes: +//----------------------------------------------------------------- +int ftdi_hw_init(int interface); +int ftdi_hw_close(void); + +// Memory Access +int ftdi_hw_mem_write(uint32_t addr, uint8_t *data, int length); +int ftdi_hw_mem_read(uint32_t addr, uint8_t *data, int length); +int ftdi_hw_mem_write_word(uint32_t addr, uint32_t data); +int ftdi_hw_mem_read_word(uint32_t addr, uint32_t *data); + +// GPIO +int ftdi_hw_gpio_write(uint8_t value); +int ftdi_hw_gpio_read(uint8_t *value); + +#endif diff --git a/ftdi_async_bridge/sw/makefile b/ftdi_async_bridge/sw/makefile new file mode 100644 index 0000000..c740308 --- /dev/null +++ b/ftdi_async_bridge/sw/makefile @@ -0,0 +1,31 @@ +############################################################################### +## Makefile +############################################################################### + +# Target +TARGET ?= test + +# Options +CFLAGS = -g +LDFLAGS = +LIBS = -lftdi + +# Source Files +OBJ = ftdi_hw.o $(TARGET).o + +############################################################################### +# Rules +############################################################################### +all: $(TARGET) + +clean: + -rm *.o $(TARGET) + +%.o : %.c + gcc -c $(CFLAGS) $< -o $@ + +%.o : %.cpp + g++ -c $(CFLAGS) $< -o $@ + +$(TARGET): $(OBJ) + g++ $(LDFLAGS) $(OBJ) $(LIBS) -o $@ diff --git a/ftdi_async_bridge/sw/test.c b/ftdi_async_bridge/sw/test.c new file mode 100644 index 0000000..17b9ef1 --- /dev/null +++ b/ftdi_async_bridge/sw/test.c @@ -0,0 +1,141 @@ +#include +#include + +#include "ftdi_hw.h" + +#define BLOCK_SIZE 2048 + +#define MEM_SIZE ((16 * 1024) / 4) + +static uint32_t mem[MEM_SIZE]; + +//----------------------------------------------------------------- +// main +//----------------------------------------------------------------- +int main(void) +{ + uint32_t buffer[16384]; + uint32_t req; + uint32_t resp; + uint32_t addr; + uint8_t gpio; + int res; + int i; + + if (ftdi_hw_init(1) != 0) + { + fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing\n"); + return 0; + } + + addr = 0x00000000; + req = 0x12345678; + ftdi_hw_mem_write_word(addr, req); + ftdi_hw_mem_read_word(addr, &resp); + + if (req != resp) + { + printf("ERR0: %x != %x\n", req, resp); + } + + addr = 0x00000004; + req = 0xcafebabe; + ftdi_hw_mem_write_word(addr, req); + ftdi_hw_mem_read_word(addr, &resp); + + if (req != resp) + { + printf("ERR1: %x != %x\n", req, resp); + } + + addr = 0x00000000; + req = 0x12345678; + ftdi_hw_mem_read_word(addr, &resp); + + if (req != resp) + { + printf("ERR2: %x != %x\n", req, resp); + } + + struct timeval t1, t2; + double elapsedTime; + + // start timer + gettimeofday(&t1, NULL); + + for (i=0;i= 1000) + { + printf("%dKB/s\n", sent / 1024); + + gettimeofday(&t1, NULL); + sent = 0; + } + } + + ftdi_hw_close(); + return 0; +}