sw: initial commit of mvp test
This version of the test runs end-to-end, and should be mostly feature complete. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
5ff6153b53
commit
6d8875850c
@ -1,5 +1,5 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
// Auto-generated by Migen (bc90344) & LiteX (3a72688b) on 2019-05-22 22:55:33
|
||||
// Auto-generated by Migen (bc90344) & LiteX (3a72688b) on 2019-05-23 14:16:56
|
||||
//--------------------------------------------------------------------------------
|
||||
#ifndef __GENERATED_CSR_H
|
||||
#define __GENERATED_CSR_H
|
||||
@ -188,9 +188,9 @@ static inline unsigned char rgb_bypass_read(void) {
|
||||
static inline void rgb_bypass_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000680cL);
|
||||
}
|
||||
#define CSR_RGB_PWM_COUNT_ADDR 0xe0006810L
|
||||
#define CSR_RGB_PWM_COUNT_SIZE 3
|
||||
static inline unsigned int rgb_pwm_count_read(void) {
|
||||
#define CSR_RGB_PULSE_ADDR 0xe0006810L
|
||||
#define CSR_RGB_PULSE_SIZE 3
|
||||
static inline unsigned int rgb_pulse_read(void) {
|
||||
unsigned int r = csr_readl(0xe0006810L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006814L);
|
||||
@ -198,33 +198,48 @@ static inline unsigned int rgb_pwm_count_read(void) {
|
||||
r |= csr_readl(0xe0006818L);
|
||||
return r;
|
||||
}
|
||||
static inline void rgb_pwm_count_write(unsigned int value) {
|
||||
static inline void rgb_pulse_write(unsigned int value) {
|
||||
csr_writel(value >> 16, 0xe0006810L);
|
||||
csr_writel(value >> 8, 0xe0006814L);
|
||||
csr_writel(value, 0xe0006818L);
|
||||
}
|
||||
#define CSR_RGB_SENT_PULSES_ADDR 0xe000681cL
|
||||
#define CSR_RGB_SENT_PULSES_SIZE 4
|
||||
static inline unsigned int rgb_sent_pulses_read(void) {
|
||||
#define CSR_RGB_DUTY_ADDR 0xe000681cL
|
||||
#define CSR_RGB_DUTY_SIZE 3
|
||||
static inline unsigned int rgb_duty_read(void) {
|
||||
unsigned int r = csr_readl(0xe000681cL);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006820L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006824L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006828L);
|
||||
return r;
|
||||
}
|
||||
#define CSR_RGB_DETECTED_PULSES_ADDR 0xe000682cL
|
||||
#define CSR_RGB_DETECTED_PULSES_SIZE 4
|
||||
static inline unsigned int rgb_detected_pulses_read(void) {
|
||||
unsigned int r = csr_readl(0xe000682cL);
|
||||
static inline void rgb_duty_write(unsigned int value) {
|
||||
csr_writel(value >> 16, 0xe000681cL);
|
||||
csr_writel(value >> 8, 0xe0006820L);
|
||||
csr_writel(value, 0xe0006824L);
|
||||
}
|
||||
#define CSR_RGB_SENT_PULSES_ADDR 0xe0006828L
|
||||
#define CSR_RGB_SENT_PULSES_SIZE 4
|
||||
static inline unsigned int rgb_sent_pulses_read(void) {
|
||||
unsigned int r = csr_readl(0xe0006828L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe000682cL);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006830L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006834L);
|
||||
return r;
|
||||
}
|
||||
#define CSR_RGB_DETECTED_PULSES_ADDR 0xe0006838L
|
||||
#define CSR_RGB_DETECTED_PULSES_SIZE 4
|
||||
static inline unsigned int rgb_detected_pulses_read(void) {
|
||||
unsigned int r = csr_readl(0xe0006838L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006838L);
|
||||
r |= csr_readl(0xe000683cL);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006840L);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0006844L);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -160,6 +160,11 @@ struct usb_cdc_notification {
|
||||
|
||||
int cdc_connected();
|
||||
void cdc_set_connected(int is_connected);
|
||||
void put_hex(uint32_t val);
|
||||
void put_hex_byte(uint8_t val);
|
||||
void put_string(const char *str);
|
||||
void put_char(char character);
|
||||
void flush_serial(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
189
sw/src/tester.c
189
sw/src/tester.c
@ -1,12 +1,12 @@
|
||||
#include <tester.h>
|
||||
#include <printf.h>
|
||||
#include <usb-cdc.h>
|
||||
#include <spi.h>
|
||||
#include <usb.h>
|
||||
#include <fomu/csr.h>
|
||||
#include <time.h>
|
||||
#include <rgb.h>
|
||||
|
||||
int test_spi(void)
|
||||
static uint32_t test_spi(void)
|
||||
{
|
||||
uint8_t test_buffer[64];
|
||||
uint8_t compare_buffer[sizeof(test_buffer)];
|
||||
@ -15,54 +15,193 @@ int test_spi(void)
|
||||
|
||||
struct spi_id id = spiId();
|
||||
spiSetType(ST_QUAD);
|
||||
// printf("SPI Manufacturer: %02x\n", id.manufacturer_id);
|
||||
// printf("SPI Device ID: %02x\n", id.device_id);
|
||||
// printf("SPI Capacity: %02x %02x\n", id.memory_type, id.memory_size);
|
||||
put_string("SPI: Manufacturer ");
|
||||
put_hex_byte(id.manufacturer_id);
|
||||
put_string(" / ");
|
||||
|
||||
for (i = 0; i < sizeof(test_buffer); i++) {
|
||||
put_string("Device ID ");
|
||||
put_hex_byte(id.device_id);
|
||||
put_string(" / ");
|
||||
|
||||
put_string("Capacity ");
|
||||
put_hex_byte(id.memory_type);
|
||||
put_char(' ');
|
||||
put_hex_byte(id.memory_size);
|
||||
put_string(" / ");
|
||||
|
||||
put_string("Serial ");
|
||||
put_hex(*((uint32_t *)id.serial));
|
||||
put_string(" / ");
|
||||
|
||||
for (i = 0; i < sizeof(test_buffer); i++)
|
||||
{
|
||||
test_buffer[i] = (i ^ 0x9d) ^ (i << 5);
|
||||
}
|
||||
spiWrite(0, test_buffer, sizeof(test_buffer)-1);
|
||||
spiWrite(0, test_buffer, sizeof(test_buffer));
|
||||
|
||||
for (i = 0; i < sizeof(compare_buffer); i++) {
|
||||
for (i = 0; i < sizeof(compare_buffer); i++)
|
||||
{
|
||||
compare_buffer[i] = 0;
|
||||
}
|
||||
spiRead(0, compare_buffer, sizeof(compare_buffer));
|
||||
|
||||
for (i = 0; i < sizeof(compare_buffer); i++) {
|
||||
if (test_buffer[i] != compare_buffer[i]) {
|
||||
for (i = 0; i < sizeof(compare_buffer); i++)
|
||||
{
|
||||
if (test_buffer[i] != compare_buffer[i])
|
||||
{
|
||||
put_string("E@");
|
||||
put_hex_byte(i);
|
||||
put_char(':');
|
||||
put_hex_byte(test_buffer[i]);
|
||||
put_char('!');
|
||||
put_hex_byte(compare_buffer[i]);
|
||||
put_char(' ');
|
||||
// printf("SPI: Offset %d Expected %02x Got %02x\n", i, test_buffer[i], compare_buffer[i]);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (!errors)
|
||||
{
|
||||
put_string("Pass\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string("FAIL\n");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int test_led(void) {
|
||||
static uint32_t test_one_pad(uint8_t src, uint8_t dest)
|
||||
{
|
||||
unsigned int loops;
|
||||
unsigned int matches = 0;
|
||||
const unsigned int loop_max = 10;
|
||||
|
||||
put_char('0'+src);
|
||||
put_char('>');
|
||||
put_char('0'+dest);
|
||||
put_char(':');
|
||||
for (loops = 0; loops < loop_max; loops++) {
|
||||
// Set pin 2 as output, and pin 0 as input, and see if it loops back.
|
||||
touch_oe_write((1 << src) | (0 << dest));
|
||||
touch_o_write((loops&1) << src);
|
||||
if ((loops&1) == !!((touch_i_read() & (1 << dest))))
|
||||
matches++;
|
||||
}
|
||||
if (matches == loop_max) {
|
||||
put_string("OK ");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
put_string("FAIL(");
|
||||
put_hex_byte(loop_max);
|
||||
put_char('!');
|
||||
put_hex_byte(matches);
|
||||
put_string(") ");
|
||||
return (loop_max - matches);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t test_touch(void)
|
||||
{
|
||||
uint32_t error_count = 0;
|
||||
|
||||
put_string("Touch: ");
|
||||
|
||||
error_count += test_one_pad(0, 2);
|
||||
error_count += test_one_pad(0, 3);
|
||||
error_count += test_one_pad(2, 0);
|
||||
error_count += test_one_pad(2, 3);
|
||||
error_count += test_one_pad(3, 0);
|
||||
error_count += test_one_pad(3, 2);
|
||||
|
||||
if (error_count)
|
||||
put_string("FAIL\n");
|
||||
else
|
||||
put_string("Pass\n");
|
||||
return error_count;
|
||||
}
|
||||
|
||||
static const char color_names[] = {'B', 'R', 'G'};
|
||||
|
||||
static uint32_t test_one_color(int color)
|
||||
{
|
||||
uint32_t pulses_per_second;
|
||||
uint32_t sent_pulses;
|
||||
uint32_t detected_pulses;
|
||||
uint32_t high_value;
|
||||
|
||||
rgb_bypass_write(1 << color);
|
||||
rgb_mode_off();
|
||||
rgb_duty_write(SYSTEM_CLOCK_FREQUENCY / 10000 * 1);
|
||||
rgb_pulse_write(SYSTEM_CLOCK_FREQUENCY / 1000 * 1);
|
||||
put_string("RGB");
|
||||
put_char(color_names[color]);
|
||||
put_string(": ");
|
||||
msleep(100);
|
||||
|
||||
rgb_pulse_write(SYSTEM_CLOCK_FREQUENCY / 1000 * 1);
|
||||
pulses_per_second = rgb_pulse_read();
|
||||
high_value = rgb_duty_read();
|
||||
sent_pulses = rgb_sent_pulses_read();
|
||||
detected_pulses = rgb_detected_pulses_read();
|
||||
|
||||
put_hex(pulses_per_second);
|
||||
put_string(" / ");
|
||||
put_hex(high_value);
|
||||
put_string(" / ");
|
||||
put_hex(sent_pulses);
|
||||
put_string(" / ");
|
||||
put_hex(detected_pulses);
|
||||
put_string(" / ");
|
||||
rgb_bypass_write(0);
|
||||
|
||||
uint32_t ratio = ((detected_pulses * 100) / sent_pulses);
|
||||
put_string("Ratio: 0x");
|
||||
put_hex(ratio);
|
||||
put_string(" / ");
|
||||
if (ratio > 60)
|
||||
{
|
||||
put_string("Pass\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
put_string("FAIL\n");
|
||||
return 1 + ratio;
|
||||
}
|
||||
|
||||
static uint32_t test_led(void)
|
||||
{
|
||||
uint32_t error_count = 0;
|
||||
|
||||
touch_oe_write(touch_oe_read() & ~(1 << 1));
|
||||
// touch_oe_write(touch_oe_read() | (1 << 1));
|
||||
// touch_o_write(touch_o_read() & ~(1 << 1));
|
||||
rgb_bypass_write(1);
|
||||
rgb_mode_off();
|
||||
rgb_pwm_count_write(SYSTEM_CLOCK_FREQUENCY/1000*125);
|
||||
printf("Blinking: ");
|
||||
msleep(1000);
|
||||
pulses_per_second = rgb_pwm_count_read();
|
||||
rgb_pwm_count_write(SYSTEM_CLOCK_FREQUENCY/1000*125);
|
||||
printf("%08x / %08x / %08x\n", pulses_per_second, rgb_sent_pulses_read(), rgb_detected_pulses_read());
|
||||
return 0;
|
||||
|
||||
error_count += test_one_color(0);
|
||||
error_count += test_one_color(1);
|
||||
error_count += test_one_color(2);
|
||||
return error_count;
|
||||
}
|
||||
|
||||
void tester_poll(void)
|
||||
{
|
||||
int error_count = 0;
|
||||
printf("\nHello, world!\n");
|
||||
// error_count = test_spi();
|
||||
// printf("SPI errors: %d\n", error_count);
|
||||
while (1) {
|
||||
put_string("\nHello, world!\n");
|
||||
error_count += test_spi();
|
||||
error_count += test_led();
|
||||
error_count += test_touch();
|
||||
|
||||
put_string("FOMU: ");
|
||||
put_hex(error_count);
|
||||
put_string(" errors ");
|
||||
if (error_count)
|
||||
put_string("FAIL!\n");
|
||||
else
|
||||
put_string("Pass\n");
|
||||
while (1)
|
||||
{
|
||||
usb_poll();
|
||||
test_led();
|
||||
}
|
||||
}
|
@ -3,6 +3,10 @@
|
||||
#include <fomu/csr.h>
|
||||
|
||||
static int connected = 0;
|
||||
struct str_bfr
|
||||
{
|
||||
uint8_t bfr_contents;
|
||||
} str_bfr;
|
||||
|
||||
int cdc_connected(void)
|
||||
{
|
||||
@ -25,3 +29,70 @@ void _putchar(char character)
|
||||
usb_ep_2_in_ibuf_head_write(character);
|
||||
usb_ep_2_in_respond_write(EPF_ACK);
|
||||
}
|
||||
|
||||
void flush_serial(void)
|
||||
{
|
||||
if (!str_bfr.bfr_contents)
|
||||
return;
|
||||
|
||||
usb_ep_2_in_respond_write(EPF_ACK);
|
||||
// Wait for buffer to be empty
|
||||
while (usb_ep_2_in_respond_read() == EPF_ACK)
|
||||
;
|
||||
str_bfr.bfr_contents = 0;
|
||||
}
|
||||
|
||||
void add_char_to_buffer(char character)
|
||||
{
|
||||
while (usb_ep_2_in_respond_read() == EPF_ACK)
|
||||
;
|
||||
usb_ep_2_in_ibuf_head_write(character);
|
||||
str_bfr.bfr_contents++;
|
||||
if (str_bfr.bfr_contents >= 64)
|
||||
flush_serial();
|
||||
}
|
||||
|
||||
void put_string(const char *str)
|
||||
{
|
||||
while (*str != '\0')
|
||||
{
|
||||
if (*str == '\n')
|
||||
add_char_to_buffer('\r');
|
||||
add_char_to_buffer(*str);
|
||||
str++;
|
||||
}
|
||||
flush_serial();
|
||||
}
|
||||
|
||||
void put_hex(uint32_t val)
|
||||
{
|
||||
int num_nibbles = sizeof(val) * 2;
|
||||
|
||||
do
|
||||
{
|
||||
char v = '0' + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||
if (v > '9')
|
||||
v += 'a' - ('9'+1);
|
||||
put_char(v);
|
||||
} while (--num_nibbles);
|
||||
}
|
||||
|
||||
void put_hex_byte(uint8_t val)
|
||||
{
|
||||
int num_nibbles = sizeof(val) * 2;
|
||||
|
||||
do
|
||||
{
|
||||
char v = '0' + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||
if (v > '9')
|
||||
v += 'a' - ('9'+1);
|
||||
put_char(v);
|
||||
} while (--num_nibbles);
|
||||
}
|
||||
|
||||
void put_char(char character)
|
||||
{
|
||||
if (character == '\n')
|
||||
add_char_to_buffer('\r');
|
||||
add_char_to_buffer(character);
|
||||
}
|
@ -7,16 +7,12 @@
|
||||
|
||||
static const int max_byte_length = 64;
|
||||
|
||||
#define EP0OUT_BUFFERS 4
|
||||
#define EP2OUT_BUFFERS 4
|
||||
__attribute__((aligned(4)))
|
||||
#define EP0OUT_BUFFER_SIZE 256
|
||||
// static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS];
|
||||
static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFER_SIZE];
|
||||
__attribute__((aligned(4)))
|
||||
static uint8_t volatile usb_ep0out_buffer[64 + 2];
|
||||
static int wait_reply;
|
||||
static int wait_type;
|
||||
// static volatile uint8_t usb_ep0out_wr_ptr;
|
||||
// static volatile uint8_t usb_ep0out_rd_ptr;
|
||||
|
||||
#define EP2OUT_BUFFER_SIZE 256
|
||||
static uint8_t volatile usb_ep2out_buffer_len[EP2OUT_BUFFERS];
|
||||
@ -220,21 +216,35 @@ void usb_isr(void) {
|
||||
// and clear the "pending" bit.
|
||||
if (ep0out_pending) {
|
||||
unsigned int byte_count = 0;
|
||||
for (byte_count = 0; byte_count < EP0OUT_BUFFER_SIZE; byte_count++)
|
||||
usb_ep0out_buffer[byte_count] = 0;
|
||||
for (byte_count = 0; byte_count < sizeof(usb_ep0out_buffer); byte_count++)
|
||||
usb_ep0out_buffer[byte_count] = '\0';
|
||||
|
||||
byte_count = 0;
|
||||
while (!usb_ep_0_out_obuf_empty_read()) {
|
||||
usb_ep0out_buffer[byte_count++] = usb_ep_0_out_obuf_head_read();
|
||||
uint8_t byte = usb_ep_0_out_obuf_head_read();
|
||||
usb_ep_0_out_obuf_head_write(0);
|
||||
usb_ep0out_buffer[byte_count++] = byte;
|
||||
}
|
||||
|
||||
if (byte_count >= 2) {
|
||||
volatile void *setup_buffer = usb_ep0out_buffer;
|
||||
usb_ep_0_in_dtb_write(1);
|
||||
data_offset = 0;
|
||||
current_length = 0;
|
||||
current_data = NULL;
|
||||
wait_reply = usb_setup((void *)usb_ep0out_buffer);
|
||||
byte_count -= 2;
|
||||
// XXX TERRIBLE HACK!
|
||||
// Because the epfifo backend doesn't have any concept of packet boundaries,
|
||||
// sometimes one or two of the bytes from the CRC on the "ACK" from the previous
|
||||
// "Get Descriptor" will be stuck on the front of this request.
|
||||
// This can happen if, for example, we get the OUT from that and the OUT from
|
||||
// the subsequent SETUP packet without first handling that.
|
||||
// Since all SETUP packets are 8 bytes (in this tester), we'll simply clamp the
|
||||
// SETUP data packet to be the last 8 bytes received (minus the 2-byte CRC16).
|
||||
// This is horrible and should be fixed in hardware.
|
||||
if (byte_count > 8)
|
||||
setup_buffer += byte_count - 8;
|
||||
wait_reply = usb_setup((const struct usb_setup_request *)setup_buffer);
|
||||
}
|
||||
usb_ep_0_out_ev_pending_write(ep0out_pending);
|
||||
usb_ep_0_out_respond_write(EPF_ACK);
|
||||
|
Loading…
Reference in New Issue
Block a user