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:
		@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										191
									
								
								sw/src/tester.c
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								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++) {
 | 
			
		||||
        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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user