diff --git a/jig/README.md b/jig/README.md new file mode 100644 index 0000000..d8e664b --- /dev/null +++ b/jig/README.md @@ -0,0 +1,6 @@ + +Install wiringpi to get the `gpio` command: + +``` +apt install wiringpi +``` diff --git a/jig/bin/get-test-command.sh b/jig/bin/get-test-command.sh new file mode 100644 index 0000000..dd3fa78 --- /dev/null +++ b/jig/bin/get-test-command.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# Remove any existing serial ports +#if [ -e /dev/ttyACM* ] +#then +# rm -f /dev/ttyACM* +#fi + +fomu-flash -f ~/tester/bin/pvt-test-bitstream.bin 2> /dev/null + +# Wait for serial port to appear +while [ ! -e /dev/ttyACM* ] +do + true +done + +sleep .1 +stty -F /dev/ttyACM0 raw +timeout 5 perl -e 'while (<>) { print; last if /^FOMU:/; }' < /dev/ttyACM0 diff --git a/jig/bin/gpiopoll b/jig/bin/gpiopoll new file mode 100644 index 0000000..da26328 Binary files /dev/null and b/jig/bin/gpiopoll differ diff --git a/jig/bin/gpiopoll.c b/jig/bin/gpiopoll.c new file mode 100644 index 0000000..72789c3 --- /dev/null +++ b/jig/bin/gpiopoll.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include "rpi.h" + +#define GPIO 26 + +static int write_file(const char *filename, const char *string) { + int fd = open(filename, O_WRONLY); + if (fd == -1) + return fd; + + write(fd, string, strlen(string)); + close(fd); + return 0; +} + +static int export_gpio(int gpio) { + char filename[512]; + char string[128]; + + snprintf(filename, sizeof(filename)-1, "/sys/class/gpio/export"); + snprintf(string, sizeof(string)-1, "%d", gpio); + if (write_file(filename, string)) + return -1; + + snprintf(filename, sizeof(filename)-1, "/sys/class/gpio/gpio%d/direction", gpio); + snprintf(string, sizeof(string)-1, "in"); + if (write_file(filename, string)) + return -1; + + snprintf(filename, sizeof(filename)-1, "/sys/class/gpio/gpio%d/edge", gpio); + snprintf(string, sizeof(string)-1, "falling"); + if (write_file(filename, string)) + return -1; + + return 0; +} + +int main(int argc, char *argv[]) +{ + char str[256]; + struct pollfd pfd; + int fd, gpio; + char buf[8]; + + if (argc > 1) + gpio = atoi(argv[1]); + else + gpio = GPIO; + + if (gpioInitialise()) { + fprintf(stderr, "Unable to initialize GPIO! Are you running as root?\n"); + return 0; + } + + gpioSetPullUpDown(gpio, PI_PUD_UP); + + if (export_gpio(gpio)) { + perror("Unable to export GPIO"); + return 1; + } + + snprintf(str, sizeof(str)-1, "/sys/class/gpio/gpio%d/value", gpio); + + if ((fd = open(str, O_RDONLY)) < 0) + { + fprintf(stderr, "Failed, gpio %d not exported.\n", gpio); + exit(1); + } + + pfd.fd = fd; + + pfd.events = POLLPRI; + + lseek(fd, 0, SEEK_SET); /* consume any prior interrupt */ + read(fd, buf, sizeof buf); + + while (1) { + poll(&pfd, 1, -1); /* wait for interrupt */ + + lseek(fd, 0, SEEK_SET); /* consume interrupt */ + read(fd, buf, sizeof buf); + //fprintf(stderr, "Delay..."); + usleep(1000); + + /* Read value after brief debounce */ + lseek(fd, 0, SEEK_SET); + //fprintf(stderr, "Re-read..."); + read(fd, buf, sizeof buf); + if (buf[0] != '0') + continue; + printf("START\n"); + fflush(stdout); + usleep(1000); + } + + exit(0); +} diff --git a/jig/bin/led-interface.sh b/jig/bin/led-interface.sh new file mode 100644 index 0000000..067c094 --- /dev/null +++ b/jig/bin/led-interface.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +green_led=11 +yellow_led=9 +red_led=10 + +all_off() { + gpio -g write ${green_led} 0 + gpio -g write ${yellow_led} 0 + gpio -g write ${red_led} 0 +} + +green_on() { + all_off + gpio -g write ${green_led} 1 +} + +yellow_on() { + all_off + gpio -g write ${yellow_led} 1 +} + +red_on() { + all_off + gpio -g write ${red_led} 1 +} + +red_also_on() { + gpio -g write ${red_led} 1 +} + +gpio_setup() { + gpio -g mode ${green_led} out + gpio -g mode ${yellow_led} out + gpio -g mode ${red_led} out + green_on +} + +gpio_setup + +echo "HELLO bash-ltc-jig 1.0" +while read line +do + if echo "${line}" | grep -iq '^start' + then + yellow_on + elif echo "${line}" | grep -iq '^fail' + then + red_also_on + elif echo "${line}" | grep -iq '^finish' + then + result=$(echo ${line} | awk '{print $3}') + if [ ${result} -ge 200 -a ${result} -lt 300 ] + then + green_on + else + red_on + fi + elif echo "${line}" | grep -iq '^exit' + then + exit 0 + fi +done diff --git a/jig/bin/rpi.c b/jig/bin/rpi.c new file mode 100644 index 0000000..f8de633 --- /dev/null +++ b/jig/bin/rpi.c @@ -0,0 +1,281 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile uint32_t piModel = 1; + +static volatile uint32_t piPeriphBase = 0x20000000; +static volatile uint32_t piBusAddr = 0x40000000; + +#define SYST_BASE (piPeriphBase + 0x003000) +#define DMA_BASE (piPeriphBase + 0x007000) +#define CLK_BASE (piPeriphBase + 0x101000) +#define GPIO_BASE (piPeriphBase + 0x200000) +#define UART0_BASE (piPeriphBase + 0x201000) +#define PCM_BASE (piPeriphBase + 0x203000) +#define SPI0_BASE (piPeriphBase + 0x204000) +#define I2C0_BASE (piPeriphBase + 0x205000) +#define PWM_BASE (piPeriphBase + 0x20C000) +#define BSCS_BASE (piPeriphBase + 0x214000) +#define UART1_BASE (piPeriphBase + 0x215000) +#define I2C1_BASE (piPeriphBase + 0x804000) +#define I2C2_BASE (piPeriphBase + 0x805000) +#define DMA15_BASE (piPeriphBase + 0xE05000) + +#define DMA_LEN 0x1000 /* allow access to all channels */ +#define CLK_LEN 0xA8 +#define GPIO_LEN 0xB4 +#define SYST_LEN 0x1C +#define PCM_LEN 0x24 +#define PWM_LEN 0x28 +#define I2C_LEN 0x1C + +#define GPSET0 7 +#define GPSET1 8 + +#define GPCLR0 10 +#define GPCLR1 11 + +#define GPLEV0 13 +#define GPLEV1 14 + +#define GPPUD 37 +#define GPPUDCLK0 38 +#define GPPUDCLK1 39 + +#define SYST_CS 0 +#define SYST_CLO 1 +#define SYST_CHI 2 + +#define CLK_PASSWD (0x5A<<24) + +#define CLK_CTL_MASH(x)((x)<<9) +#define CLK_CTL_BUSY (1 <<7) +#define CLK_CTL_KILL (1 <<5) +#define CLK_CTL_ENAB (1 <<4) +#define CLK_CTL_SRC(x) ((x)<<0) + +#define CLK_SRCS 4 + +#define CLK_CTL_SRC_OSC 1 /* 19.2 MHz */ +#define CLK_CTL_SRC_PLLC 5 /* 1000 MHz */ +#define CLK_CTL_SRC_PLLD 6 /* 500 MHz */ +#define CLK_CTL_SRC_HDMI 7 /* 216 MHz */ + +#define CLK_DIV_DIVI(x) ((x)<<12) +#define CLK_DIV_DIVF(x) ((x)<< 0) + +#define CLK_GP0_CTL 28 +#define CLK_GP0_DIV 29 +#define CLK_GP1_CTL 30 +#define CLK_GP1_DIV 31 +#define CLK_GP2_CTL 32 +#define CLK_GP2_DIV 33 + +#define CLK_PCM_CTL 38 +#define CLK_PCM_DIV 39 + +#define CLK_PWM_CTL 40 +#define CLK_PWM_DIV 41 + + +static volatile uint32_t *gpioReg = MAP_FAILED; +static volatile uint32_t *systReg = MAP_FAILED; +static volatile uint32_t *clkReg = MAP_FAILED; + +#define PI_BANK (gpio>>5) +#define PI_BIT (1<<(gpio&0x1F)) + +/* gpio modes. */ + +#define PI_INPUT 0 +#define PI_OUTPUT 1 +#define PI_ALT0 4 +#define PI_ALT1 5 +#define PI_ALT2 6 +#define PI_ALT3 7 +#define PI_ALT4 3 +#define PI_ALT5 2 + +void gpioSetMode(unsigned gpio, unsigned mode) { + int reg, shift; + + reg = gpio/10; + shift = (gpio%10) * 3; + + gpioReg[reg] = (gpioReg[reg] & ~(7<> shift) & 7; +} + +/* Values for pull-ups/downs off, pull-down and pull-up. */ + +#define PI_PUD_OFF 0 +#define PI_PUD_DOWN 1 +#define PI_PUD_UP 2 + +void gpioSetPullUpDown(unsigned gpio, unsigned pud) { + *(gpioReg + GPPUD) = pud; + + usleep(20); + + *(gpioReg + GPPUDCLK0 + PI_BANK) = PI_BIT; + + usleep(20); + + *(gpioReg + GPPUD) = 0; + + *(gpioReg + GPPUDCLK0 + PI_BANK) = 0; +} + +int gpioRead(unsigned gpio) { + if ((*(gpioReg + GPLEV0 + PI_BANK) & PI_BIT) != 0) return 1; + else return 0; +} + +void gpioWrite(unsigned gpio, unsigned level) { + if (level == 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT; + else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT; +} + +void gpioTrigger(unsigned gpio, unsigned pulseLen, unsigned level) { + if (level == 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT; + else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT; + + usleep(pulseLen); + + if (level != 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT; + else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT; +} + +/* Bit (1< + +/* gpio modes. */ +#define PI_INPUT 0 +#define PI_OUTPUT 1 +#define PI_ALT0 4 +#define PI_ALT1 5 +#define PI_ALT2 6 +#define PI_ALT3 7 +#define PI_ALT4 3 +#define PI_ALT5 2 + +void gpioSetMode(unsigned gpio, unsigned mode); +int gpioGetMode(unsigned gpio); + +/* Values for pull-ups/downs off, pull-down and pull-up. */ +#define PI_PUD_OFF 0 +#define PI_PUD_DOWN 1 +#define PI_PUD_UP 2 +void gpioSetPullUpDown(unsigned gpio, unsigned pud); + +int gpioRead(unsigned gpio); +void gpioWrite(unsigned gpio, unsigned level); +void gpioTrigger(unsigned gpio, unsigned pulseLen, unsigned level); + +/* Bit (1< +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + FILE *log = NULL; + struct termios tty; + int i; + FILE *fd; + + if (argc > 1) { + log = fopen(argv[1], "wb"); + if (!log) { + perror("Couldn't open log"); + return 1; + } + } + + for (i = 0; i < 65536; i++) { + fd = fopen("/dev/ttyACM0", "rb"); + if (fd) { + break; + } + usleep(1); + } + if (!fd) { + fprintf(stderr, "Unable to open after %d tries\n", i); + perror("Couldn't open!"); + return 1; + } + + tcgetattr(fileno(fd), &tty); + cfmakeraw(&tty); + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CRTSCTS; /* no HW flow control */ + tty.c_cflag |= CLOCAL | CREAD; + tcsetattr(fileno(fd), TCSANOW, &tty); + + while (1) { + char in_bfr[1024]; + + memset(in_bfr, 0, sizeof(in_bfr)); + + if (!fgets(in_bfr, sizeof(in_bfr), fd)) { + return 1; + } + + printf("%s", in_bfr); + if (log) + fprintf(log, "%s", in_bfr); + if (!strncmp(in_bfr, "FOMU:", strlen("FOMU:"))) { + break; + } + } + + return 0; +} diff --git a/jig/config/all-tests.test b/jig/config/all-tests.test new file mode 100644 index 0000000..acfd06f --- /dev/null +++ b/jig/config/all-tests.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=/bin/true +Name=Run all tests +Description=Make sure all tests complete successfully +Requires=test-rgbb, test-rgbg, test-rgbr, test-spi, test-touch +Timeout=4 diff --git a/jig/config/complete.scenario b/jig/config/complete.scenario new file mode 100644 index 0000000..a0d1b78 --- /dev/null +++ b/jig/config/complete.scenario @@ -0,0 +1,5 @@ +[Scenario] +Name=Program and test Everything +Description=Load the test bitstream, run tests, then load the final bitstream +Tests=all-tests,load-final-bitstream,verify-final-bitstream +Timeout=5 diff --git a/jig/config/factory-pvt.jig b/jig/config/factory-pvt.jig new file mode 100644 index 0000000..bbab838 --- /dev/null +++ b/jig/config/factory-pvt.jig @@ -0,0 +1,6 @@ +[Jig] +Name=Raspberry Pi Fomu PVT Jig +Description=Fomu factory jig running on a Raspberry Pi, designed to burn and test Fomu PVT +TestFile=/etc +DefaultScenario=complete +DefaultWorkingDirectory=../bin diff --git a/jig/config/file.logger b/jig/config/file.logger new file mode 100644 index 0000000..cb3faca --- /dev/null +++ b/jig/config/file.logger @@ -0,0 +1,5 @@ +[Logger] +Name=File Logger +Description=Write log messages out to a file +ExecStart=/bin/sh -c "cat > /tmp/ltc-log.json" +Format=json diff --git a/jig/config/leds.interface b/jig/config/leds.interface new file mode 100644 index 0000000..e393028 --- /dev/null +++ b/jig/config/leds.interface @@ -0,0 +1,5 @@ +[Interface] +Name=Front panel LEDs +Description=Shows test status on the LEDs +Format=text +ExecStart=./led-interface.sh diff --git a/jig/config/load-final-bitstream.test b/jig/config/load-final-bitstream.test new file mode 100644 index 0000000..c6093ca --- /dev/null +++ b/jig/config/load-final-bitstream.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=fomu-flash -w pvt-top-multiboot.bin +Name=Load Final Bitstream +Description=Use fomu-flash to load the final bitstream +Requires=all-tests +Timeout=3 diff --git a/jig/config/load-tester-bitstream.test b/jig/config/load-tester-bitstream.test new file mode 100644 index 0000000..720d168 --- /dev/null +++ b/jig/config/load-tester-bitstream.test @@ -0,0 +1,5 @@ +[Test] +ExecStart=fomu-flash -f evt-tester-bitstream.bin +Name=Load Tester Bitstream +Description=Use fomu-flash to load the tester bitstream +Timeout=1 diff --git a/jig/config/pi-gpio.trigger b/jig/config/pi-gpio.trigger new file mode 100644 index 0000000..b32093c --- /dev/null +++ b/jig/config/pi-gpio.trigger @@ -0,0 +1,4 @@ +[Trigger] +Name=Start button +Description=A start button on the Raspberry Pi jig, pin 26. Compile with 'gcc gpiopoll.c -o gpiopoll; sudo chown root gpiopoll; sudo chmod u+s gpiopoll' +ExecStart=./gpiopoll 26 diff --git a/jig/config/run-all-tests.test b/jig/config/run-all-tests.test new file mode 100644 index 0000000..8ca6bb0 --- /dev/null +++ b/jig/config/run-all-tests.test @@ -0,0 +1,7 @@ +[Test] +ExecStart=./uart-monitor /tmp/monitor-log.txt +Name=Run all tests +Description=Run all tests and log the output to a file +Requires=load-tester-bitstream +Required=load-tester-bitstream +Timeout=2 diff --git a/jig/config/test-rgbb.test b/jig/config/test-rgbb.test new file mode 100644 index 0000000..645a78d --- /dev/null +++ b/jig/config/test-rgbb.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=grep -c '^RGBB: .*Pass\s*$' /tmp/monitor-log.txt +Name=Verify Blue LED +Description=Look for "RGBB: Pass" in the monitor log +Requires=load-tester-bitstream,run-all-tests +Timeout=1 diff --git a/jig/config/test-rgbg.test b/jig/config/test-rgbg.test new file mode 100644 index 0000000..7fa6a22 --- /dev/null +++ b/jig/config/test-rgbg.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=grep -c '^RGBG: .*Pass\s*$' /tmp/monitor-log.txt +Name=Verify Green LED +Description=Look for "RGBG: Pass" in the monitor log +Requires=load-tester-bitstream,run-all-tests +Timeout=1 diff --git a/jig/config/test-rgbr.test b/jig/config/test-rgbr.test new file mode 100644 index 0000000..bc793d1 --- /dev/null +++ b/jig/config/test-rgbr.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=grep -c '^RGBR: .*Pass\s*$' /tmp/monitor-log.txt +Name=Verify Red LED +Description=Look for "RGBR: Pass" in the monitor log +Requires=load-tester-bitstream,run-all-tests +Timeout=1 diff --git a/jig/config/test-spi.test b/jig/config/test-spi.test new file mode 100644 index 0000000..3acaffd --- /dev/null +++ b/jig/config/test-spi.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=grep -c '^SPI: .*Pass\s*$' /tmp/monitor-log.txt +Name=Verify SPI +Description=Look for "SPI: Pass" in the monitor log +Requires=load-tester-bitstream,run-all-tests +Timeout=1 diff --git a/jig/config/test-touch.test b/jig/config/test-touch.test new file mode 100644 index 0000000..8b161ea --- /dev/null +++ b/jig/config/test-touch.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=grep -c '^TOUCH: .*Pass\s*$' /tmp/monitor-log.txt +Name=Verify Touch Pads +Description=Look for "TOUCH: Pass" in the monitor log +Requires=load-tester-bitstream,run-all-tests +Timeout=3 diff --git a/jig/config/verify-final-bitstream.test b/jig/config/verify-final-bitstream.test new file mode 100644 index 0000000..e9e97bb --- /dev/null +++ b/jig/config/verify-final-bitstream.test @@ -0,0 +1,6 @@ +[Test] +ExecStart=fomu-flash -v pvt-top-multiboot.bin +Name=Verify Final Bitstream +Description=Use fomu-flash to verify the final bitstream +Requires=load-final-bitstream +Timeout=3 diff --git a/jig/exclave b/jig/exclave new file mode 100644 index 0000000..78386b0 Binary files /dev/null and b/jig/exclave differ