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:
Sean Cross 2019-05-23 17:07:55 +08:00
parent 5ff6153b53
commit 6d8875850c
5 changed files with 291 additions and 51 deletions

View File

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

View File

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

View File

@ -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++) {
test_buffer[i] = (i^0x9d) ^ (i<<5);
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();
}
}

View File

@ -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)
{
@ -24,4 +28,71 @@ 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);
}

View File

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