Compare commits

...

9 Commits
v1.0 ... master

Author SHA1 Message Date
Sean Cross fc9acfbb65 jig: file.logger: log to permanent storage
Log to the root filesystem, so we have a copy.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:47:40 +08:00
Sean Cross 8e7b41f01a jig: validate-spi: use qspi when validating
That way we can tell early on if there are issues with the SPI lines.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:47:03 +08:00
Sean Cross e98aac8fde jig: led-interface: give better feedback when running
Provide a light pattern when the test is running normally.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:46:30 +08:00
Sean Cross 3bcd5ee328 jig: all-tests: disable spi test
It's having issues, owing to the lack of a proper sensor.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:45:46 +08:00
Sean Cross 2a3c5d352e sw: tester: adjust tester time to 900us/1ms
This is in-line with the datasheet.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:23:27 +08:00
Sean Cross 165cf24bc7 factory-bitstream: rework led to fix pulse counter
Now we count the number of transitions.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 18:19:15 +08:00
Sean Cross 18178e4a71 jig: sync with nearly-final version
This is nearly the final version of the factory test jig.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-26 13:31:36 +08:00
Sean Cross 337e1a370c spi: don't shift into "QPI" mode
Assume we're not running in QPI mode.

There were some issues involving corruption that were observed as a
result of shifting into QPI mode when in SPI mode.  Disable this change.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-25 23:50:20 +08:00
Sean Cross 946c7f8ec1 jig: add jig information
Signed-off-by: Sean Cross <sean@xobs.io>
2019-05-24 19:10:37 +08:00
32 changed files with 880 additions and 18 deletions

View File

@ -343,14 +343,18 @@ class SBLED(Module, AutoCSR):
count = Signal(24)
led_value = Signal()
last_led_value = Signal()
rgb = Signal(3)
sent_pulses = Signal(32)
detected_pulses = Signal(32)
rgba_drv = Signal(3)
last_detected_val = Signal()
self.sync += [
last_led_value.eq(led_value),
If(last_detected_val != detected_pulse,
detected_pulses.eq(detected_pulses + 1),
),
last_detected_val.eq(detected_pulse),
# When the PWM count is updated, reset everything and
# copy the results out.
If(self.pulse.re,
@ -368,18 +372,11 @@ class SBLED(Module, AutoCSR):
count.eq(count + 1),
If(count < self.duty.storage,
led_value.eq(0),
).Elif(count == self.duty.storage,
led_value.eq(1),
sent_pulses.eq(sent_pulses + 1),
).Else(
led_value.eq(1),
# On the transition from 0 > 1, increment the counter
# and see if the LED has changed. If so, increment
# the number of detected pulses.
If(~last_led_value,
sent_pulses.eq(sent_pulses + 1),
If(detected_pulse,
detected_pulses.eq(detected_pulses + 1),
),
),
),
).Else(
# Reset the count once it gets greater than "Pulse"
@ -388,6 +385,47 @@ class SBLED(Module, AutoCSR):
),
]
# last_led_value = Signal()
# self.sync += [
# last_led_value.eq(led_value),
# # When the PWM count is updated, reset everything and
# # copy the results out.
# If(self.pulse.re,
# count.eq(0),
# self.sent_pulses.status.eq(sent_pulses),
# sent_pulses.eq(0),
# self.detected_pulses.status.eq(detected_pulses),
# detected_pulses.eq(0),
# led_value.eq(0),
# ).Elif(count < self.pulse.storage,
# count.eq(count + 1),
# If(count < self.duty.storage,
# led_value.eq(0),
# ).Else(
# led_value.eq(1),
# # On the transition from 0 > 1, increment the counter
# # and see if the LED has changed. If so, increment
# # the number of detected pulses.
# If(~last_led_value,
# sent_pulses.eq(sent_pulses + 1),
# If(detected_pulse,
# detected_pulses.eq(detected_pulses + 1),
# ),
# ),
# ),
# ).Else(
# # Reset the count once it gets greater than "Pulse"
# count.eq(0),
# led_value.eq(0),
# ),
# ]
# Wire up the bypasses
self.comb += [
If(self.bypass.storage[0],
@ -417,6 +455,9 @@ class SBLED(Module, AutoCSR):
o_RGB1 = pads.rgb1,
o_RGB2 = pads.rgb2,
p_CURRENT_MODE = "0b1", # Half current
# p_RGB0_CURRENT = "0b111111", # 12 mA
# p_RGB1_CURRENT = "0b111111", # 12 mA
# p_RGB2_CURRENT = "0b111111", # 12 mA
p_RGB0_CURRENT = "0b000011", # 4 mA
p_RGB1_CURRENT = "0b000011", # 4 mA
p_RGB2_CURRENT = "0b000011", # 4 mA

26
jig/README.md Normal file
View File

@ -0,0 +1,26 @@
Install wiringpi to get the `gpio` command:
```
apt install wiringpi
```
There are five LEDs on the front. The indicate which subsystems work.
1: An error occurred
2: Test Error
3: Test Error
4: Test Error
5: Tester is IDLE (also, tester is READY)
LEDs 2, 3, and 4 form a pattern that indicate which test failed:
Test name | 2 (Green) | 3 (Blue) | 4 (White) | Reason for Failure |
====================+===========+===========+===========+====================+
SPI Valid | | x | x | The SPI flash was not found, or was not the correct model |
USB Communication | x | | | The FPGA isn't assembled correctly, the USB pullup isn't correct, or the crystal is bad |
Load Test Bitstream | | | | The FPGA isn't assembled correctly |
Test SPI | | x | | Not all four wires are connected between the FPGA and the SPI |
Test RGB | x | x | | TOUCH2 or the RGB LED are not assembled correctly |
Test Touch | | x | x | TOUCH1, TOUCH3, or TOUCH4 are not assembled correctly |
Final Bitstream | | | x | The final program could not be loaded |

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);
}

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

@ -0,0 +1,122 @@
#!/bin/sh
led_1=19
led_2=13
led_3=6
led_4=5
led_5=0
all_off() {
gpio -g write ${led_1} 0
gpio -g write ${led_2} 0
gpio -g write ${led_3} 0
gpio -g write ${led_4} 0
gpio -g write ${led_5} 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
}
led_on() {
case $1 in
1) gpio -g write ${led_1} on ;;
2) gpio -g write ${led_2} on ;;
3) gpio -g write ${led_3} on ;;
4) gpio -g write ${led_4} on ;;
5) gpio -g write ${led_5} on ;;
esac
}
led_off() {
case $1 in
1) gpio -g write ${led_1} off ;;
2) gpio -g write ${led_2} off ;;
3) gpio -g write ${led_3} off ;;
4) gpio -g write ${led_4} off ;;
5) gpio -g write ${led_5} off ;;
esac
}
gpio_setup() {
gpio -g mode ${led_1} out
gpio -g mode ${led_2} out
gpio -g mode ${led_3} out
gpio -g mode ${led_4} out
gpio -g mode ${led_5} out
all_off
led_on 5
}
fail_test() {
led_off 2
led_off 3
led_off 4
case $1 in
load-tester-bitstream) ;;
run-all-tests) led_on 2 ;;
validate-spi) led_on 3 ; led_on 4 ;;
test-spi) led_on 3 ;;
test-rgbg) led_on 2 ; led_on 3 ;;
test-rgbb) led_on 2 ; led_on 3 ;;
test-rgbr) led_on 2 ; led_on 3 ;;
test-touch) led_on 3 ; led_on 4 ;;
load-final-bitstream) led_on 4 ;;
verify-final-bitstream) led_on 4 ;;
esac
}
gpio_setup
echo "HELLO bash-ltc-jig 1.0"
while read line
do
if echo "${line}" | grep -iq '^start'
then
all_off
led_on 2
led_on 3
led_on 4
failures=0
elif echo "${line}" | grep -iq '^fail'
then
if [ $failures -ne 1 ]
then
failures=1
fail_test $(echo "${line}" | awk '{print $2}')
fi
led_on 1
elif echo "${line}" | grep -iq '^finish'
then
led_on 5
result=$(echo ${line} | awk '{print $3}')
if [ ${result} -ge 200 -a ${result} -lt 300 ]
then
led_off 2
led_off 3
led_off 4
else
led_on 1
fi
elif echo "${line}" | grep -iq '^exit'
then
all_off
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;
}

41
jig/bin/validate-spi.sh Normal file
View File

@ -0,0 +1,41 @@
#!/bin/sh
infofile=/tmp/spi-info.txt
rm -f $infofile
fomu-flash -t 4 -i | tee $infofile
# Manufacturer ID: Macronix (c2)
# Memory model: MX25R1635F (28)
# Memory size: 16 Mbit (15)
# Device ID: 15
error_count=0
if ! grep -q 'Manufacturer ID: Macronix (c2)' $infofile
then
echo -n "Unrecognized SPI manufacturer: "
grep 'Manufacturer ID: ' $infofile
error_count=$(($error_count+1))
fi
if ! grep -q 'Memory model: MX25R1635F (28)' $infofile
then
echo -n "Unrecognized memory model: "
grep 'Memory model: ' $infofile
error_count=$(($error_count+1))
fi
if ! grep -q 'Memory size: 16 Mbit (15)' $infofile
then
echo -n "Unrecognized memory size: "
grep 'Memory size: ' $infofile
error_count=$(($error_count+1))
fi
if ! grep -q 'Device ID: 15' $infofile
then
echo -n "Unrecognized device id: "
grep 'Device ID: ' $infofile
error_count=$(($error_count+1))
fi
exit $error_count

View File

@ -0,0 +1,7 @@
[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
Requires=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 >> /home/fomu/fomu-test-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,6 @@
[Test]
ExecStart=fomu-flash -f pvt-tester-bitstream.bin
Name=Load Tester Bitstream
Description=Use fomu-flash to load the tester bitstream
Requires=validate-spi
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,5 @@
[Test]
ExecStart=./validate-spi.sh
Name=Validate SPI
Description=Validate that the SPI part number is what we expect
Timeout=1

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.

22
jig/exclave.service Normal file
View File

@ -0,0 +1,22 @@
# copy this file to /etc/systemd/system
# then run:
# sudo systemctl start exclave
# sudo systemctl stop exclave
# sudo systemctl enable exclave
[Unit]
Description=Exclave tester automation framework service
After=network.target
After=systemd-user-sessions.service
[Service]
User=pi
ExecStart=/home/pi/code/netv2-tests/run_exclave.sh
#Restart=always
#TimeoutSec=60 # I have no idea how to tell systemd the script has started...
#RestartSec=10
#StartTimeLimitInterval=60
#StartLimitBurst=10
[Install]
WantedBy=multi-user.target

View File

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (bc90344) & LiteX (3a72688b) on 2019-05-23 14:16:56
// Auto-generated by Migen (bc90344) & LiteX (3a72688b) on 2019-05-26 18:13:05
//--------------------------------------------------------------------------------
#ifndef __GENERATED_CSR_H
#define __GENERATED_CSR_H

View File

@ -640,9 +640,6 @@ int spiBeginWrite(uint32_t addr, const void *v_data, unsigned int count) {
uint8_t spiReset(void) {
// XXX You should check the "Ready" bit before doing this!
// Shift to QPI mode, then back to Single mode, to ensure
// we're actually in Single mode.
spiSetType(ST_QPI);
spiSetType(ST_SINGLE);
spiBegin();

View File

@ -137,8 +137,13 @@ static uint32_t test_one_color(int color)
rgb_bypass_write(1 << color);
rgb_mode_off();
rgb_duty_write(SYSTEM_CLOCK_FREQUENCY / 10000 * 1);
rgb_pulse_write(SYSTEM_CLOCK_FREQUENCY / 1000 * 1);
// Amount of time it's off (900 us)
rgb_duty_write(SYSTEM_CLOCK_FREQUENCY / 10000 * 9);
// Total amount of time for one pulse (1000 us or 1 ms)
rgb_pulse_write(SYSTEM_CLOCK_FREQUENCY / 10000 * 10);
put_string("RGB");
put_char(color_names[color]);
put_string(": ");