jig: add jig information

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2019-05-24 19:10:37 +08:00
parent 372ab22b10
commit 946c7f8ec1
25 changed files with 670 additions and 0 deletions

6
jig/README.md Normal file
View File

@ -0,0 +1,6 @@
Install wiringpi to get the `gpio` command:
```
apt install wiringpi
```

View File

@ -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

BIN
jig/bin/gpiopoll Normal file

Binary file not shown.

103
jig/bin/gpiopoll.c Normal file
View File

@ -0,0 +1,103 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <poll.h>
#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);
}

63
jig/bin/led-interface.sh Normal file
View File

@ -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

281
jig/bin/rpi.c Normal file
View File

@ -0,0 +1,281 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
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)) | (mode<<shift);
}
int gpioGetMode(unsigned gpio) {
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
return (*(gpioReg + reg) >> 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<<x) will be set if gpio x is high. */
uint32_t gpioReadBank1(void) { return (*(gpioReg + GPLEV0)); }
uint32_t gpioReadBank2(void) { return (*(gpioReg + GPLEV1)); }
/* To clear gpio x bit or in (1<<x). */
void gpioClearBank1(uint32_t bits) { *(gpioReg + GPCLR0) = bits; }
void gpioClearBank2(uint32_t bits) { *(gpioReg + GPCLR1) = bits; }
/* To set gpio x bit or in (1<<x). */
void gpioSetBank1(uint32_t bits) { *(gpioReg + GPSET0) = bits; }
void gpioSetBank2(uint32_t bits) { *(gpioReg + GPSET1) = bits; }
unsigned gpioHardwareRevision(void) {
static unsigned rev = 0;
FILE * filp;
char buf[512];
char term;
int chars=4; /* number of chars in revision string */
if (rev) return rev;
piModel = 0;
filp = fopen ("/proc/cpuinfo", "r");
if (filp != NULL)
{
while (fgets(buf, sizeof(buf), filp) != NULL)
{
if (piModel == 0)
{
if (!strncasecmp("model name", buf, 10))
{
if (strstr (buf, "ARMv6") != NULL)
{
piModel = 1;
chars = 4;
piPeriphBase = 0x20000000;
piBusAddr = 0x40000000;
}
else if (strstr (buf, "ARMv7") != NULL)
{
piModel = 2;
chars = 6;
piPeriphBase = 0x3F000000;
piBusAddr = 0xC0000000;
}
}
}
if (!strncasecmp("revision", buf, 8))
{
if (sscanf(buf+strlen(buf)-(chars+1),
"%x%c", &rev, &term) == 2)
{
if (term != '\n') rev = 0;
}
}
}
fclose(filp);
}
return rev;
}
/* Returns the number of microseconds after system boot. Wraps around
after 1 hour 11 minutes 35 seconds.
*/
uint32_t gpioTick(void) {
return systReg[SYST_CLO];
}
/* Map in registers. */
static uint32_t *initMapMem(int fd, uint32_t addr, uint32_t len) {
return (uint32_t *) mmap(0, len,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_LOCKED,
fd, addr);
}
int gpioInitialise(void) {
int fd;
gpioHardwareRevision(); /* sets piModel, needed for peripherals address */
fd = open("/dev/mem", O_RDWR | O_SYNC) ;
if (fd < 0)
{
fprintf(stderr,
"This program needs root privileges. Try using sudo\n");
return -1;
}
gpioReg = initMapMem(fd, GPIO_BASE, GPIO_LEN);
systReg = initMapMem(fd, SYST_BASE, SYST_LEN);
clkReg = initMapMem(fd, CLK_BASE, CLK_LEN);
close(fd);
if ((gpioReg == MAP_FAILED) ||
(systReg == MAP_FAILED) ||
(clkReg == MAP_FAILED))
{
fprintf(stderr,
"Bad, mmap failed\n");
return -1;
}
return 0;
}

50
jig/bin/rpi.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef RPI_H_
#define RPI_H_
#include <stdint.h>
/* 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<<x) will be set if gpio x is high. */
uint32_t gpioReadBank1(void);
uint32_t gpioReadBank2(void);
/* To clear gpio x bit or in (1<<x). */
void gpioClearBank1(uint32_t bits);
void gpioClearBank2(uint32_t bits);
/* To set gpio x bit or in (1<<x). */
void gpioSetBank1(uint32_t bits);
void gpioSetBank2(uint32_t bits);
unsigned gpioHardwareRevision(void);
/* Returns the number of microseconds after system boot. Wraps around
after 1 hour 11 minutes 35 seconds.
*/
uint32_t gpioTick(void);
int gpioInitialise(void);
#endif /* RPI_H_ */

BIN
jig/bin/uart-monitor Normal file

Binary file not shown.

63
jig/bin/uart-monitor.c Normal file
View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
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;
}

View File

@ -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

View File

@ -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

View File

@ -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

5
jig/config/file.logger Normal file
View File

@ -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

View File

@ -0,0 +1,5 @@
[Interface]
Name=Front panel LEDs
Description=Shows test status on the LEDs
Format=text
ExecStart=./led-interface.sh

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

6
jig/config/test-spi.test Normal file
View File

@ -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

View File

@ -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

View File

@ -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

BIN
jig/exclave Normal file

Binary file not shown.