public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
From: "oliver munz @ s p e a g" <munz@speag.ch>
To: <ecos-discuss@sourceware.org>
Subject: [ECOS] How to debug synchronisation in the usbs.c in a new usb-driver for the ARM at91sam7s...
Date: Thu, 16 Feb 2006 02:56:00 -0000	[thread overview]
Message-ID: <012801c632a4$c8b5c9a0$5a188481@haus.hellmutstrasse.ch> (raw)

[-- Attachment #1: Type: text/plain, Size: 2382 bytes --]

I need a hint, what can go wrong in the usbs.c, or how to debug 
condition-variables...

My problem is, that my code works reliable, if i use it whitout 
kernel-objects, and that it works only a while in the usbs.c infrastructur, 
and then blocks for ever...

When the usbs_devtab_cwrite() blocks, i see, that the complete-function is 
called, but the thread never leave cyg_drv_cond_wait(&wait.signal);...

Beacuse the blocking is random after 5..20 transmissions, i can't set a 
breake point on a interessting point, if i halt the system in the gdb i see 
the empty thread...

what can be the reason for not realeasing the thread?

/* THIS WORKS FOR AT LEAST 24H RESTLESS TRANSMISSION */

static void usbs_callback(void *arg, int result){

    *(int *) arg = result;

    if (!result){
        *(int *) arg = -EIO;
    }
}

void usb_write_wo_io(cyg_addrword_t data){

    int retcode;
    const char str[] = "configuration points supported by eCos resulted in 
systems that were faster to build (all"
            "the hard work was coded into the configuration rules) and 
resulted in smaller systems than manual"
            "methods could produce (because the automated rules were more 
all-seeing and all-knowing";

    while (true){

        if (usbs_sam7_ep0.state == USBS_STATE_CONFIGURED){

            retcode = 0;
            usbs_sam7_ep2.buffer = str;
            usbs_sam7_ep2.buffer_size = sizeof(str);
            usbs_sam7_ep2.complete_fn = usbs_callback;
            usbs_sam7_ep2.complete_data = (void *) &retcode;

            usbs_sam7_ep2.start_rx_fn(&usbs_sam7_ep2);

            while (!retcode){
            }
        }
    }
}


/* THIS BLOCKS AFTER A FEW TRANSMISSIONS */

void usb_write(cyg_addrword_t data){

    Cyg_ErrNo retcode;
    cyg_uint32 n;
    const char str[] = "configuration points supported by eCos resulted in 
systems that were faster to build (all"
            "the hard work was coded into the configuration rules) and 
resulted in smaller systems than manual"
            "methods could produce (because the automated rules were more 
all-seeing and all-knowing";

    while (true){

        if (usbs_sam7_ep0.state == USBS_STATE_CONFIGURED){

            n = sizeof(str);
            retcode = cyg_io_write(husbs[2], (void *) str, &n); /* handle to 
the usbs-write-endpoint */
        }
    }
}


Thanks for any hint...
Oliver Munz 

[-- Attachment #2: usbs_at91sam7s.c --]
[-- Type: text/plain, Size: 40984 bytes --]

#include <pkgconf/devs_usb_at91sam7s.h>
#include <cyg/io/usb/usbs_at91sam7s.h>
#include <cyg/hal/AT91SAM7S_REG.h>

#include <cyg/hal/drv_api.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/hal_platform_ints.h>

#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/diag.h>

#include <cyg/error/codes.h>

#include <cyg/io/usb/usb.h>
#include <cyg/io/usb/usbs.h>

// For memcpy()
#include <string.h>
#include <stdio.h>



#define AT91_UDP_CSR0 (AT91_UDP_CSR)
#define AT91_UDP_FDR0 (AT91_UDP_FDR)

#define pIER (AT91C_BASE_UDP + AT91_UDP_IER)
#define pIDR (AT91C_BASE_UDP + AT91_UDP_IDR)
#define pISR (AT91C_BASE_UDP + AT91_UDP_ISR)
#define pIMR (AT91C_BASE_UDP + AT91_UDP_IMR)
#define pICR (AT91C_BASE_UDP + AT91_UDP_ICR)

#define pCSR0 (AT91C_BASE_UDP + AT91_UDP_CSR0)
#define pFDR0 (AT91C_BASE_UDP + AT91_UDP_FDR0)

#define AT91C_UDP_ALLOWED_IRQs (AT91C_UDP_WAKEUP | AT91C_UDP_ENDBUSRES | AT91C_UDP_EXTRSM | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP | AT91C_UDP_EPINT0  | AT91C_UDP_EPINT1 | AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3)

#define THERE_IS_A_NEW_PACKET_IN_THE_UDP 0xffff

static const cyg_uint16 usbs_sam7_endpoint_fifo_size[AT91SAM7S_USB_ENDPOINTS] = {
    8,
    64,
    64,
    8
};
static const bool usbs_sam7_endpoint_pingpong[AT91SAM7S_USB_ENDPOINTS] = {
    false,
    true,
    true,
    false
};
static cyg_uint8 *usbs_sam7_endpoint_pbegin[AT91SAM7S_USB_ENDPOINTS] = {0};
static cyg_uint8 *usbs_sam7_endpoint_pend[AT91SAM7S_USB_ENDPOINTS] = {0};
static bool      usbs_sam7_endpoint_bank1[AT91SAM7S_USB_ENDPOINTS] = {false};
//static bool      usbs_sam7_endpoint_send_zero_packet[AT91SAM7S_USB_ENDPOINTS] = {false};
static bool      usbs_sam7_endpoint_transfer[AT91SAM7S_USB_ENDPOINTS] = {false};
static cyg_uint16 usbs_sam7_endpoint_bytes_in_fifo[AT91SAM7S_USB_ENDPOINTS] = {0};
static cyg_uint16 usbs_sam7_endpoint_bytes_recived[AT91SAM7S_USB_ENDPOINTS] = {THERE_IS_A_NEW_PACKET_IN_THE_UDP};



static cyg_interrupt usbs_sam7_intr_data;
static cyg_handle_t  usbs_sam7_intr_handle;

static void usbs_sam7_ep0_start(usbs_control_endpoint*);
static void usbs_sam7_poll(usbs_control_endpoint*);

static void usbs_sam7_endpoint_start(cyg_uint8 epn);
static void usbs_sam7_set_halted(cyg_bool new_value, cyg_uint8 epn);
static void usbs_sam7_endpoint_init(cyg_uint8 epn, cyg_uint8 endpoint_type, cyg_bool enable);


void usbs_start_dummy(usbs_rx_endpoint* ep){
    
    CYG_ASSERT(0, "usbs_start_dummy()");
}

void set_halted_dummy(usbs_rx_endpoint* ep, cyg_bool b){
    
    CYG_ASSERT(0, "set_halted_dummy()");
}


void usbs_sam7_ep1_start(usbs_rx_endpoint *pep){
    usbs_sam7_endpoint_start(1);
}

void usbs_sam7_ep2_start(usbs_rx_endpoint *pep){
    usbs_sam7_endpoint_start(2);
}

void usbs_sam7_ep3_start(usbs_rx_endpoint *pep){
    usbs_sam7_endpoint_start(3);
}



void usbs_sam7_ep1_set_halted(usbs_rx_endpoint *pep, cyg_bool new_value){
    usbs_sam7_set_halted(new_value, 1);
}

void usbs_sam7_ep2_set_halted(usbs_rx_endpoint *pep, cyg_bool new_value){
    usbs_sam7_set_halted(new_value, 2);
}

void usbs_sam7_ep3_set_halted(usbs_rx_endpoint *pep, cyg_bool new_value){
    usbs_sam7_set_halted(new_value, 3);
}



void usbs_sam7_ep1_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable){
    usbs_sam7_endpoint_init(1, endpoint_type, enable);
}

void usbs_sam7_ep2_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable){
    usbs_sam7_endpoint_init(2, endpoint_type, enable);
}

void usbs_sam7_ep3_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable){
    usbs_sam7_endpoint_init(3, endpoint_type, enable);
}


usbs_control_endpoint usbs_sam7_ep0 = {
    state:                  USBS_STATE_POWERED, // The hardware does not distinguish  between detached, attached and powered.
    enumeration_data:       (usbs_enumeration_data*) 0,
    start_fn:               usbs_sam7_ep0_start,
    poll_fn:                usbs_sam7_poll,
    interrupt_vector:       CYGNUM_HAL_INTERRUPT_UDP,
    control_buffer:         { 0, 0, 0, 0, 0, 0, 0, 0 },
    state_change_fn:        (void (*)(usbs_control_endpoint*, void*, usbs_state_change, int)) 0,
    state_change_data:      (void*) 0,
    standard_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
    standard_control_data:  (void*) 0,
    class_control_fn:       (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
    class_control_data:     (void*) 0,
    vendor_control_fn:      (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
    vendor_control_data:    (void*) 0,
    reserved_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
    reserved_control_data:  (void*) 0,
    buffer:                 (unsigned char*) 0,
    buffer_size:            0,
    fill_buffer_fn:         (void (*)(usbs_control_endpoint*)) 0,
    fill_data:              (void*) 0,
    fill_index:             0,
    complete_fn:            (usbs_control_return (*)(usbs_control_endpoint*, int)) 0
};


usbs_rx_endpoint usbs_sam7_ep1 = {
    start_rx_fn:        usbs_sam7_ep1_start,
    set_halted_fn:      usbs_sam7_ep1_set_halted,
    complete_fn:        (void (*)(void*, int)) 0,
    complete_data:      (void*) 0,
    buffer:             (const unsigned char*) 0,
    buffer_size:        0,
    halted:             0,
};


usbs_rx_endpoint usbs_sam7_ep2 = {
    start_rx_fn:        usbs_sam7_ep2_start,
    set_halted_fn:      usbs_sam7_ep2_set_halted,
    complete_fn:        (void (*)(void*, int)) 0,
    complete_data:      (void*) 0,
    buffer:             (const unsigned char*) 0,
    buffer_size:        0,
    halted:             0,
};


usbs_rx_endpoint usbs_sam7_ep3 = {
    start_rx_fn:        usbs_sam7_ep3_start,
    set_halted_fn:      usbs_sam7_ep3_set_halted,
    complete_fn:        (void (*)(void*, int)) 0,
    complete_data:      (void*) 0,
    buffer:             (const unsigned char*) 0,
    buffer_size:        0,
    halted:             0,
};




const void *usbs_sam7_enpoints[AT91SAM7S_USB_ENDPOINTS] = {
    
    (void *) &usbs_sam7_ep0,
    (void *) &usbs_sam7_ep1,
    (void *) &usbs_sam7_ep2,
    (void *) &usbs_sam7_ep3
};








typedef enum ep0_low_level_status_t {
    
    EP0_LL_IDLE = 0,
    EP0_LL_REQUEST,
    EP0_LL_SEND_READY,
    EP0_LL_ACK,
    EP0_LL_RECIVE_READY,
    EP0_LL_ISOERROR,
    EP0_LL_STALL,
    EP0_LL_SET_ADDRESS,
} ep0_low_level_status_t;

#ifndef _BV
    #define _BV(_bit_) (1 << _bit_)
#endif

#ifndef MIN
    #define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif





// DEBUG CHÄS
#define MAXPRINTBUFSIZE 3000
cyg_uint32 printbuf_size = MAXPRINTBUFSIZE;
char printbuf[MAXPRINTBUFSIZE];
cyg_uint32 printbuf_next = 0;



#define debug_line_and_funcion debug_printf("%d: %s(); ", __LINE__, __FUNCTION__);


void buf_printf(char *fmt, ...){
    
    va_list argp;
    va_start(argp, fmt);
    printbuf_next = printbuf_next + vsnprintf((char *)((cyg_uint32) printbuf + printbuf_next), printbuf_size - printbuf_next, fmt, argp);
//    diag_vprintf(fmt, argp);
    va_end(argp);
}

#define debug_printf buf_printf



void debug_dump(cyg_uint8 *pbegin, cyg_uint8 *pend){
    
    //debug_line_and_funcion
    
    debug_printf("[%d] ", (cyg_uint32) pend - (cyg_uint32) pbegin);
    
    do {
        debug_printf("%02x ", *pbegin);
        pbegin++;
    }
    while (pbegin < pend);
    
    debug_printf("\n");
}

//#define diag_ //

#if 1
    #define dbg debug_line_and_funcion 
#else
    #define dbg // 
#endif

#if 1
    #define dbgdsr debug_line_and_funcion 
#else
    #define dbgdsr 
#endif

#define dbgf 



void diag_status(usbs_control_endpoint cep, ep0_low_level_status_t s){
    
    cyg_uint32 isr;
    cyg_uint32 csr0;
    
    HAL_READ_UINT32(pISR, isr);
    HAL_READ_UINT32(pCSR0, csr0);
    
    debug_printf("i%08x; c%08x; state: ", isr, csr0);
    switch(cep.state){
        case USBS_STATE_DETACHED:  debug_printf("USBS_STATE_DETACHED"); break;
        case USBS_STATE_ATTACHED:  debug_printf("USBS_STATE_ATTACHED"); break;
        case USBS_STATE_POWERED:   debug_printf("USBS_STATE_POWERED"); break;
        case USBS_STATE_DEFAULT:   debug_printf("USBS_STATE_DEFAULT"); break;
        case USBS_STATE_ADDRESSED: debug_printf("USBS_STATE_ADDRESSED"); break;
        case USBS_STATE_CONFIGURED:debug_printf("USBS_STATE_CONFIGURED"); break;
        case USBS_STATE_MASK:      debug_printf("USBS_STATE_MASK"); break;
        case USBS_STATE_SUSPENDED: debug_printf("USBS_STATE_SUSPENDED"); break;
        default:                   debug_printf("USBS_STATE_ERROR"); break;
    }
    debug_printf("; ll: ");
	switch(s){
    	case EP0_LL_IDLE:         debug_printf("EP0_LL_IDLE"); break;
		case EP0_LL_REQUEST:      debug_printf("EP0_LL_REQUEST"); break;
		case EP0_LL_SEND_READY:   debug_printf("EP0_LL_SEND_READY"); break;
		case EP0_LL_ACK:          debug_printf("EP0_LL_ACK"); break;
		case EP0_LL_RECIVE_READY: debug_printf("EP0_LL_RECIVE_READY"); break;
        case EP0_LL_ISOERROR:     debug_printf("EP0_LL_ISOERROR"); break;
        case EP0_LL_STALL:        debug_printf("EP0_LL_STALL"); break;
		case EP0_LL_SET_ADDRESS:  debug_printf("EP0_LL_SET_ADDRESS"); break;
		default:                  debug_printf("EP0_LL_ERROR"); break;
	}
    debug_printf(";\n");
}


















void usbs_sam7_endpoint_interrupt_enable(cyg_uint8 epn, bool enable){
    
    CYG_ASSERT(epn < 4, "");
    
    if (enable){
        HAL_WRITE_UINT32(pIER, 1 << epn);
    }else{
        HAL_WRITE_UINT32(pIDR, 1 << epn);
    }
}


inline cyg_uint32 hal_get_2_bytes(cyg_addrword_t addr){
	
	cyg_uint32 	temp1, temp2;
		
	HAL_READ_UINT8(addr, temp1);
	HAL_READ_UINT8(addr, temp2);
	
	return temp1 | (temp2 << 8);
}


inline cyg_uint8 hal_get_byte(cyg_addrword_t addr){
	
	cyg_uint8 	temp1;
		
	HAL_READ_UINT32(addr, temp1);
	
	return temp1;
}


inline cyg_uint32 hal_get_uint32(cyg_addrword_t addr){
	
	cyg_uint32 	temp1;
		
	HAL_READ_UINT32(addr, temp1);
	
	return temp1;
}



cyg_uint8 *hal_read_fifo_uint8(cyg_uint8 *pdest, cyg_uint8 *psource, cyg_uint32 size){
    
    cyg_uint8 *preqbyte = pdest;
    cyg_uint8 reqbyte;

    while (preqbyte < (cyg_uint8 *)((cyg_uint32) size + pdest)){
        
        HAL_READ_UINT8(psource, reqbyte);
        *preqbyte = reqbyte;
        preqbyte++;
    }
    
    return preqbyte;
}



cyg_uint8 *hal_write_fifo_uint8(cyg_uint8 *pdest, cyg_uint8 *psource, cyg_uint8 *psource_end){
    
    cyg_uint8 *preqbyte;
    
    for (preqbyte = psource; preqbyte < psource_end; preqbyte++){
        
        HAL_WRITE_UINT8(pdest, (*preqbyte));
    }
    
    return preqbyte;
}


void set_bits(cyg_addrword_t addr, cyg_uint32 set){
    
    cyg_uint32 read;

    HAL_READ_UINT32(addr, read);
    HAL_WRITE_UINT32(addr, read | set);
}


void clear_bits(cyg_addrword_t addr, cyg_uint32 clear){
    
    cyg_uint32 read;

    HAL_READ_UINT32(addr, read);
    HAL_WRITE_UINT32(addr, read & ~clear);
}


cyg_uint32 bits_are_set(cyg_addrword_t addr, cyg_uint32 set){
    
    cyg_uint32 read;

    HAL_READ_UINT32(addr, read);
    
    return (read & set) == set;
}


cyg_uint32 bits_are_cleared(cyg_addrword_t addr, cyg_uint32 clear){
    
    cyg_uint32 read;

    HAL_READ_UINT32(addr, read);
    
    return (read | ~clear) == ~clear;
}




void usbs_change_state(usbs_control_endpoint *pcep, usbs_state_change new_state){
    
    int old_state = pcep->state;
    
    pcep->state = new_state;
    if (pcep->state_change_fn){
        (*pcep->state_change_fn)(pcep, 0, new_state, old_state);
    }
}


void usbs_end_all_transfers(usbs_control_return returncode){
    
    cyg_uint32 epn;
    usbs_rx_endpoint *pep;

    for (epn = 1; epn < AT91SAM7S_USB_ENDPOINTS; epn++){
        
        if (usbs_sam7_endpoint_transfer[epn]){ /* Ready to transmit ? */
    
            pep = (usbs_rx_endpoint *) usbs_sam7_enpoints[epn];
            
            if (pep->complete_fn){
                (*pep->complete_fn)(pep->complete_data, returncode);
            }
            
            usbs_sam7_endpoint_interrupt_enable(epn, false);
            usbs_sam7_endpoint_transfer[epn] = false;
        }
    }    
}


void usbs_state_notify(usbs_control_endpoint *pcep){
    
    static int old_state = USBS_STATE_CHANGE_POWERED;
    int state = pcep->state & USBS_STATE_MASK;
    
    if (pcep->state != old_state){
        
diag_printf(" <state: %x> ", pcep->state);
        
        usbs_end_all_transfers(-EPIPE);

        if (pcep->state & USBS_STATE_MASK == USBS_STATE_DETACHED){
        } else if (state == USBS_STATE_DETACHED){
        } else if (state == USBS_STATE_ATTACHED){
        } else if (state == USBS_STATE_POWERED){
        } else if (state == USBS_STATE_DEFAULT){
            
            HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_GLBSTATE, 0);
            
        } else if (state == USBS_STATE_ADDRESSED){

            HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_GLBSTATE, AT91C_UDP_FADDEN);
            
        } else if (state == USBS_STATE_CONFIGURED){

            HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_GLBSTATE, AT91C_UDP_CONFG);
            
        } else {
            /* ERROR */
        }
        
        if (pcep->state & USBS_STATE_SUSPENDED){
        } else {
        }
        
        if (pcep->state_change_fn){
            (*pcep->state_change_fn)(pcep, 0, pcep->state, old_state);
        }
        
        old_state = pcep->state;
    }
}


usbs_control_return usbs_parse_host_get_command(usbs_control_endpoint *pcep){
    
    usbs_control_return retcode;
    cyg_uint8 dev_req_type = (((usb_devreq *) pcep->control_buffer)->type) & USB_DEVREQ_TYPE_MASK;
    
    pcep->buffer_size = 0;
    pcep->fill_buffer_fn = 0;
    
    if (dev_req_type == USB_DEVREQ_TYPE_STANDARD){
        
        if (!pcep->standard_control_fn){
            return usbs_handle_standard_control(pcep);
        }
        retcode = (*pcep->standard_control_fn)(pcep, pcep->standard_control_data);
        if (retcode == USBS_CONTROL_RETURN_UNKNOWN){
            
            return usbs_handle_standard_control(pcep);
        }
        return retcode;
    }
    else if (dev_req_type == USB_DEVREQ_TYPE_CLASS){
        
        if (!pcep->class_control_fn){
            return USBS_CONTROL_RETURN_STALL;
        }
        return (*pcep->class_control_fn)(pcep, pcep->class_control_data);
    }
    else if (dev_req_type == USB_DEVREQ_TYPE_VENDOR){
        if (!pcep->class_control_fn){
            return USBS_CONTROL_RETURN_STALL;
        }
        return (*pcep->class_control_fn)(pcep, pcep->vendor_control_data);
    }
    else if (dev_req_type == USB_DEVREQ_TYPE_RESERVED){
        if (!pcep->reserved_control_fn){
            return USBS_CONTROL_RETURN_STALL;
        }
        return (*pcep->reserved_control_fn)(pcep, pcep->reserved_control_data);
    }
    
    return USBS_CONTROL_RETURN_STALL;
}













static void usbs_sam7_set_halted(cyg_bool new_value, cyg_uint8 epn){
    
    usbs_rx_endpoint *pep = (usbs_rx_endpoint *) usbs_sam7_enpoints[epn];
    cyg_uint32 *pbegin = usbs_sam7_endpoint_pbegin[epn];
    cyg_uint32 *pend = usbs_sam7_endpoint_pend[epn];

    if (pep->halted != new_value){ /* If somting is to do */
        
//        cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_UDP);
        
        pep->halted = new_value;
        
        pbegin = pep->buffer;
        pend = pbegin;
        
        if (new_value && usbs_sam7_endpoint_transfer[epn]){
            if (pep->complete_fn && usbs_sam7_endpoint_transfer[epn]){
                (*pep->complete_fn)(pep->complete_data, -EAGAIN);
            }
            usbs_sam7_endpoint_transfer[epn] = false;
        }
        
//        cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_UDP);
    }
}





static void usbs_sam7_endpoint_init(cyg_uint8 epn, cyg_uint8 endpoint_type, cyg_bool enable){
    
    usbs_rx_endpoint *pep = (usbs_rx_endpoint *) usbs_sam7_enpoints[epn];
    cyg_uint32 *pCSR = (cyg_uint32 *)((cyg_uint32) pCSR0 + 4 * epn);
//    cyg_uint32 *pFDR = (cyg_uint32 *)((cyg_uint32) pFDR0 + 4 * epn);
//    cyg_uint32 endpoint_size = usbs_sam7_endpoint_fifo_size[epn];
//    cyg_uint32 *pbegin = usbs_sam7_endpoint_pbegin[epn];
//    cyg_uint32 *pend = usbs_sam7_endpoint_pend[epn];
    
    CYG_ASSERT(AT91SAM7S_USB_ENDPOINTS > epn && epn, "Wrong epn");
 
    usbs_sam7_endpoint_interrupt_enable(epn, false);
    
    HAL_WRITE_UINT32(pCSR, ((((cyg_uint32) endpoint_type) & 0x03) << 8) | ((((cyg_uint32) endpoint_type) & 0x80) << 3)); /* Type | In */
//    CYG_ASSERT(bits_are_set(pCSR, 1 << 9), "Wrong enpoint type");

    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_RSTEP, 1 << epn); /* Reset endpoint */
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_RSTEP, 0);

    pep->halted = false;
    usbs_sam7_endpoint_transfer[epn] = false;
    usbs_sam7_endpoint_bytes_in_fifo[epn] = 0;
    usbs_sam7_endpoint_bytes_recived[epn] = THERE_IS_A_NEW_PACKET_IN_THE_UDP;
    usbs_sam7_endpoint_bank1[epn] = false;
    usbs_sam7_endpoint_transfer[epn] = false;
    
    if (enable){
        set_bits(pCSR, AT91C_UDP_EPEDS);
    }
}


static void usbs_sam7_handle_reset(void){
    
    dbg debug_printf("\n");
      
    usbs_end_all_transfers(-EPIPE);

    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_IDR,     0xffffffff);
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_ICR,     0xffffffff);
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_RSTEP,   0xffffffff);
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_RSTEP,   0x00000000);
    
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_FADDR,   AT91C_UDP_FEN);
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_CSR0,    AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_IER,     AT91C_UDP_ALLOWED_IRQs);

#if 1       
    usbs_sam7_endpoint_init(1, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, true);
    usbs_sam7_endpoint_init(2, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK | USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, true);
    usbs_sam7_endpoint_init(3, USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT | USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, true);
#else
    usbs_sam7_endpoint_init(1, 0, false);
    usbs_sam7_endpoint_init(2, 0, false);
    usbs_sam7_endpoint_init(3, 0, false);
#endif
}






static void usbs_sam7_ep0_start(usbs_control_endpoint* endpoint){
    
    dbg debug_printf("\n");
    
    usbs_sam7_handle_reset();
   
    // If there is additional platform-specific initialization to
    // perform, do it now. This macro can come from the platform HAL,
    // but may not be available on all platforms.
#ifdef AT91SAM7S_USB_PLATFORM_INIT
    AT91SAM7S_USB_PLATFORM_INIT();
#else
    HAL_WRITE_UINT32(AT91C_BASE_PIOA + AT91_PIO_CODR, AT91C_PIO_PA4);
#endif
}
 


static void usbs_sam7_endpoint_start(cyg_uint8 epn){
    
    usbs_rx_endpoint *pep = (usbs_rx_endpoint *) usbs_sam7_enpoints[epn];
    cyg_uint32 *pCSR = (cyg_uint32 *)((cyg_uint32) pCSR0 + 4 * epn);
    cyg_uint32 *pFDR = (cyg_uint32 *)((cyg_uint32) pFDR0 + 4 * epn);
    cyg_uint16 space = 0;
    cyg_uint16 endpoint_size = usbs_sam7_endpoint_fifo_size[epn];
    cyg_uint16 *pinfifo = &usbs_sam7_endpoint_bytes_in_fifo[epn];
    cyg_uint8  **ppbegin = &usbs_sam7_endpoint_pbegin[epn];
    cyg_uint8  **ppend = &usbs_sam7_endpoint_pend[epn];
    
    CYG_ASSERT(AT91SAM7S_USB_ENDPOINTS > epn && epn, "Wrong epn");
    CYG_ASSERT(bits_are_set(pCSR, 1 << 9), "Wrong enpoint type");
//    CYG_ASSERT(pep->complete_fn, "No complete_fn()");

    if (usbs_sam7_ep0.state != USBS_STATE_CONFIGURED){ /* Halted means nothing to do */
diag_printf("*1");        

        if (pep->complete_fn){
            (*pep->complete_fn)(pep->complete_data, -EPIPE);
        }
        
        return;
    }
    
    if (pep->halted){ /* Halted means nothing to do */
diag_printf("*2");        
        
        if (pep->complete_fn){
            (*pep->complete_fn)(pep->complete_data, -EAGAIN);
        }
        
        return;
    }
    
    if (usbs_sam7_endpoint_transfer[epn]){ /* Transfer in progress */
diag_printf("*3");        
        
        if (pep->complete_fn){
            (*pep->complete_fn)(pep->complete_data, -EIO);
        }
        
        return;
    }
    
    *ppbegin = pep->buffer; /* Set the working pointers */
    *ppend = (cyg_uint32 *)((cyg_uint32) pep->buffer + pep->buffer_size);
    
    if (bits_are_set(pCSR, 0x400)){ /* IN: tx_endpoint */
        
        space = (cyg_uint32) *ppend - (cyg_uint32) *ppbegin;
        if (space == endpoint_size){
            *ppend = *ppbegin; /* Send zero-packet */
        }
        
        *ppbegin = hal_write_fifo_uint8(pFDR, *ppbegin, (cyg_uint32 *)((cyg_uint32) *ppbegin + MIN(space, endpoint_size)));
        set_bits(pCSR, AT91C_UDP_TXPKTRDY);

        if (*ppend == *ppbegin){ /* Last packet ? */
            *ppend = *ppbegin - 1; /* The packet isn't sent yet */
        }
    }

    usbs_sam7_endpoint_transfer[epn] = true;
    usbs_sam7_endpoint_interrupt_enable(epn, true);
}



static bool usbs_sam7_endpoint_isr(cyg_uint8 epn){ /* Move the datas in ISR for high bandwidth */
    
    cyg_uint32      *pCSR = (cyg_uint32 *)((cyg_uint32) pCSR0 + 4 * epn);
    cyg_uint32      *pFDR = (cyg_uint32 *)((cyg_uint32) pFDR0 + 4 * epn);
    cyg_uint16      endpoint_size = usbs_sam7_endpoint_fifo_size[epn];
    cyg_uint32      space = 0;
    cyg_uint8       **ppbegin = &usbs_sam7_endpoint_pbegin[epn];
    cyg_uint8       **ppend = &usbs_sam7_endpoint_pend[epn];
    cyg_uint16      *pinfifo = &usbs_sam7_endpoint_bytes_in_fifo[epn];
    cyg_uint16      *precived = &usbs_sam7_endpoint_bytes_recived[epn];
    
    CYG_ASSERT(AT91SAM7S_USB_ENDPOINTS > epn && epn, "Wrong epn");
    
//diag_printf(" i%d ", epn);

    if (bits_are_set(pCSR, 0x400)){ /* IN: tx_endpoint */

        clear_bits(pCSR, AT91C_UDP_TXCOMP);

        if (bits_are_cleared(pCSR, AT91C_UDP_TXPKTRDY)){ /* Ready to transmit ? */
            
            if (*ppend > *ppbegin){ /* Somthing to send ? */

                space = (cyg_uint32) *ppend - (cyg_uint32) *ppbegin;
                if (space == endpoint_size){
                    *ppend = *ppbegin; /* Send zero-packet */
                }
                
                *ppbegin = hal_write_fifo_uint8(pFDR, *ppbegin, (cyg_uint32 *)((cyg_uint32) *ppbegin + MIN(space, endpoint_size)));
                set_bits(pCSR, AT91C_UDP_TXPKTRDY);
                
                if (*ppend == *ppbegin){ /* Last packet ? */
                    *ppend = *ppbegin - 1; /* The packet isn't sent yet */
                }
                
            } else {
                
                if (*ppend + 1 == *ppbegin){
                    
                    *ppend = *ppbegin; /* Flag for DSR */
                    
                    return true;
                    
                } else {

                    *ppend = *ppbegin - 1; /* Flag for zero-packet */
                    set_bits(pCSR, AT91C_UDP_TXPKTRDY); /* Send no data */
                }
            }
        }

        clear_bits(pCSR, AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR);
        
    } else { /* OUT: rx_endpoint */
  
        if (!bits_are_cleared(pCSR, AT91C_UDP_RX_DATA_BK0) || AT91C_UDP_RX_DATA_BK1){ /* Sometime something recived ? */
            
            if (*precived == THERE_IS_A_NEW_PACKET_IN_THE_UDP){ /* If there is a new... */
                
                *precived = ((*pCSR) >> 16) & 0x7ff; /* How many bytes ? */
                *pinfifo = *precived; /* FIFO hold datas */
            }
            
            while ((*ppbegin < *ppend) && *pinfifo){ /* If we have buffer-space AND datas in the FIFO */ 
                
                **ppbegin = *pFDR;
                
                (*ppbegin)++;
                (*pinfifo)--;
            }
            
            if (*ppbegin == *ppend){ /* The buffer is full... call the DSR */
    
                return true; /* We can call the complet-function in the DSR */
                    
            }
            
            if (*pinfifo == 0){ /* If the FIFO is empty, then we can release it */
        
                if (usbs_sam7_endpoint_pingpong[epn]){ /* Time to clear the interrupt flag */
                    
                    if (usbs_sam7_endpoint_bank1[epn]){
                        clear_bits(pCSR, AT91C_UDP_RX_DATA_BK1);
                    } else {
                        clear_bits(pCSR, AT91C_UDP_RX_DATA_BK0);
                    }
                    usbs_sam7_endpoint_bank1[epn] = !usbs_sam7_endpoint_bank1[epn];
                    
                } else {
                    clear_bits(pCSR, AT91C_UDP_RX_DATA_BK0);
                } 
                
                if (*precived < endpoint_size){ /* If the last packet was smaller then the endpoint-size... */
                    
                    *ppend = *ppbegin;
                    *precived = THERE_IS_A_NEW_PACKET_IN_THE_UDP; /* Set flag */
    
                    return true; /* We can call the complet-function in the DSR */
                    
                }
                
                *precived = THERE_IS_A_NEW_PACKET_IN_THE_UDP; /* Set flag */
            }
        }
        
        clear_bits(pCSR, AT91C_UDP_TXCOMP | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR);
    }
    
    return false;
}


static void usbs_sam7_endpoint_dsr(cyg_uint8 epn){
    
    usbs_rx_endpoint *pep = (usbs_rx_endpoint *) usbs_sam7_enpoints[epn];
    cyg_uint32      *pCSR = (cyg_uint32 *)((cyg_uint32) pCSR0 + 4 * epn);
    cyg_uint8       **ppbegin = &usbs_sam7_endpoint_pbegin[epn];
    cyg_uint8       **ppend = &usbs_sam7_endpoint_pend[epn];
    
    CYG_ASSERT(AT91SAM7S_USB_ENDPOINTS > epn && epn, "Wrong epn");
    CYG_ASSERT(bits_are_set(pCSR, 1 << 9), "Wrong enpoint type");
    CYG_ASSERT(pep->complete_fn, "No complete_fn()");
    
//diag_printf(" d%d ", epn);

    if (usbs_sam7_endpoint_transfer[epn]){ /* Transmiting ? */

        if (*ppend == *ppbegin){ /* Transmitted ? */
            
            pep->buffer_size = (cyg_uint32) *ppbegin - (cyg_uint32) pep->buffer;
            
            if (pep->complete_fn){
                if (!pep->halted){
                    (*pep->complete_fn)(pep->complete_data, pep->buffer_size);
                } else {
                    (*pep->complete_fn)(pep->complete_data, -EAGAIN);
                }
            }
            
            usbs_sam7_endpoint_interrupt_enable(epn, false);
            usbs_sam7_endpoint_transfer[epn] = false;
        }
    }
}






static void usbs_sam7_control_dsr(){
    
    usb_devreq *req = usbs_sam7_ep0.control_buffer; /*  */
    static ep0_low_level_status_t status = EP0_LL_IDLE;
    bool   dev_to_host; /* IN */
    usbs_control_return  usbcode;
    
    static cyg_uint16   length;
        
    static cyg_uint8    *pbuffer = 0;
    static cyg_uint8    *pbuffer_end = 0;
    static cyg_uint32   bytes_to_write = 0;

    static cyg_uint32   address;

    static cyg_uint8    configaddress ;
    
    //dbgdsr debug_printf("BEGIN: "); diag_status(usbs_sam7_ep0, status);
    //diag_printf("o");
    
    while (!bits_are_cleared(pCSR0, AT91C_UDP_TXCOMP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR | AT91C_UDP_RX_DATA_BK1)){
    
        /* ERROR-HANDLING */
        /******************/

        if (bits_are_set(pCSR0, AT91C_UDP_ISOERROR)){ /* ERROR? */
            
//            clear_bits(pCSR0, AT91C_UDP_FORCESTALL); /* We recived the host-request */
            clear_bits(pCSR0, AT91C_UDP_ISOERROR | AT91C_UDP_FORCESTALL); /* We recived the host-request */
            
            pbuffer = usbs_sam7_ep0.buffer;
            pbuffer_end = pbuffer;
            
            if (status == EP0_LL_IDLE){
                
                if (usbs_sam7_ep0.complete_fn){
                    (*usbs_sam7_ep0.complete_fn)(&usbs_sam7_ep0, USBS_CONTROL_RETURN_STALL);
                }
            }

            status = EP0_LL_IDLE;
            
            //dbgdsr debug_printf("AT91C_UDP_ISOERROR "); diag_status(usbs_sam7_ep0, status);
        }

        /* HOSTREQUEST-PARSING */
        /***********************/

        if (bits_are_set(pCSR0, AT91C_UDP_RXSETUP)){ /* wenn wir auf ein request warten */
            
            /* host request */
            
            hal_read_fifo_uint8(req, pFDR0, sizeof(usb_devreq));
    
            length = (req->length_hi << 8) | req->length_lo;
            //value  = req->value_hi;    //value  = (req->value_hi << 8) | req->value_lo;
            usbs_sam7_ep0.buffer_size = 0;
            
            status = EP0_LL_REQUEST;
            
            dev_to_host = req->type & USB_DEVREQ_DIRECTION_IN;
            if (dev_to_host){ /* if next transfer is IN: "host <- dev" ? */
                set_bits(pCSR0, AT91C_UDP_DIR); /* Set IN direction */
            } else {
                clear_bits(pCSR0, AT91C_UDP_DIR); /* Set OUT direction */
            }

            if (req->request == USB_DEVREQ_GET_STATUS && dev_to_host){
                
                //diag_printf("s");

                pbuffer = &usbs_sam7_ep0.state;
                pbuffer_end = pbuffer + sizeof(usbs_sam7_ep0.state);
                
                status = EP0_LL_SEND_READY;

            } else if (req->request == USB_DEVREQ_SET_ADDRESS && !dev_to_host){ /* Special-processing */
                
                //diag_printf("a");
                
                pbuffer = usbs_sam7_ep0.buffer;/* Send ACK */
                pbuffer_end = pbuffer;
                
                status = EP0_LL_SEND_READY; 

            } else {
 
                usbcode = usbs_parse_host_get_command(&usbs_sam7_ep0);
                
                usbs_sam7_ep0.buffer_size = MIN(usbs_sam7_ep0.buffer_size, length);
                length = length - usbs_sam7_ep0.buffer_size;

                pbuffer = usbs_sam7_ep0.buffer;
                pbuffer_end = pbuffer + usbs_sam7_ep0.buffer_size; /* Ready to send... */
    
                if (usbcode == USBS_CONTROL_RETURN_HANDLED){ /* OK */
                    
                    if (dev_to_host){ /* if next transfer is IN: "host <- dev" ? */
                        status = EP0_LL_SEND_READY; 
                    } else {
                        status = EP0_LL_RECIVE_READY; 
                    }
                    
                } else {
                    //diag_printf(" <S0> ");
                    clear_bits(pCSR0, 0x7f);
                    set_bits(pCSR0, AT91C_UDP_FORCESTALL);
                    status = EP0_LL_STALL;
                }
            }
            
            clear_bits(pCSR0, AT91C_UDP_RXSETUP); /* We recived the host-request */
//            while(!bits_are_cleared(pCSR0, AT91C_UDP_RXSETUP)){ /* Test like Atmel USB AN */
//            }
        }
        
        
        
        
        /* INTERRUPT-HANDLING clear flags and do the work and update the state-machine */
        /*******************************************************************************/

        if (bits_are_set(pCSR0, AT91C_UDP_TXCOMP)){  //received an ACK packet
            
            clear_bits(pCSR0, AT91C_UDP_TXCOMP); // Clear corresponding interrupt 
            
//            while(!bits_are_cleared(pCSR0, AT91C_UDP_TXCOMP)){ // Test like Atmel USB AN 
//            }
        }
        
        if (bits_are_cleared(pCSR0, AT91C_UDP_TXPKTRDY)){
            
            if (status == EP0_LL_SEND_READY){
            
                if (pbuffer == pbuffer_end){ // All bytes are sent, send ACK
    
                    status = EP0_LL_ACK;
                    
                    set_bits(pCSR0, AT91C_UDP_TXPKTRDY); // Signal FIFO loaded 
                } else {
                    
                    bytes_to_write = MIN(pbuffer_end - pbuffer, usbs_sam7_endpoint_fifo_size[0]);
                    pbuffer = hal_write_fifo_uint8(pFDR0, pbuffer, (cyg_uint8 *)((cyg_uint32) pbuffer + bytes_to_write)); // Send next few bytes 
                    
                    if (pbuffer == pbuffer_end){ /* Control-Endoints don't need ACK's */
                        
                        if (usbs_sam7_ep0.fill_buffer_fn){ /* More Records ? */
                            
                            //diag_printf(" f ");

                            (*usbs_sam7_ep0.fill_buffer_fn)(&usbs_sam7_ep0);
              
                            pbuffer = usbs_sam7_ep0.buffer;
                            pbuffer_end = pbuffer + usbs_sam7_ep0.buffer_size; /* Ready to send... */
    
                            bytes_to_write = MIN(pbuffer_end - pbuffer, usbs_sam7_endpoint_fifo_size[0] - bytes_to_write);
                            
                            pbuffer = hal_write_fifo_uint8(pFDR0, pbuffer, (cyg_uint8 *)((cyg_uint32) pbuffer + bytes_to_write)); // Send next few bytes 
         
                        } else {
                            
                            status = EP0_LL_IDLE;
                        }
                    }
                    
                    set_bits(pCSR0, AT91C_UDP_TXPKTRDY); // Signal FIFO loaded 
                }
                
            } else if (status == EP0_LL_RECIVE_READY){ /* Maybe we have to send an ACK */
             
                if (pbuffer == pbuffer_end){ // All bytes are recived, send ACK
    
                    status = EP0_LL_ACK;
                    
                    set_bits(pCSR0, AT91C_UDP_TXPKTRDY); // Signal FIFO loaded 
                }
                
            } else if (status == EP0_LL_ACK){

                dbgdsr debug_printf("confirmed ACK "); diag_status(usbs_sam7_ep0, status); 
                
                if (req->request == USB_DEVREQ_SET_ADDRESS){ /* Special-processing */
                    
                    //diag_printf("b");

                    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_FADDR, req->value_lo | AT91C_UDP_FEN);
//                    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_GLBSTATE, 0x00000001);
                    
                    usbs_sam7_ep0.state = USBS_STATE_ADDRESSED;
                    
                }
                
                if (usbs_sam7_ep0.complete_fn){
                    (*usbs_sam7_ep0.complete_fn)(&usbs_sam7_ep0, USBS_CONTROL_RETURN_HANDLED);
                }
                
                status = EP0_LL_IDLE;
                
                usbs_state_notify(&usbs_sam7_ep0);
            }
        }

        if (bits_are_set(pCSR0, AT91C_UDP_RX_DATA_BK0)){

            /* TODO READ FIFO OR SEND ACK */
            
            pbuffer = usbs_sam7_ep0.buffer;
            pbuffer_end = pbuffer; /* Ready to send... */
            
            status = EP0_LL_SEND_READY;

            clear_bits(pCSR0, AT91C_UDP_RX_DATA_BK0);
        }
    }
}



static void usbs_sam7_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){
    
    cyg_uint8 n;
    
	CYG_ASSERT(CYGNUM_HAL_INTERRUPT_UDP == vector, "Wrong interrupts");
	CYG_ASSERT(0 == data, "DSR needs no data");
	
    //diag_printf(".");
	
    clear_bits(AT91C_BASE_UDP + AT91_UDP_GLBSTATE, 0x10);

    if (bits_are_set(pISR, AT91C_UDP_WAKEUP)){

        usbs_sam7_ep0.state = USBS_STATE_DEFAULT;
        usbs_state_notify(&usbs_sam7_ep0);
        
        HAL_WRITE_UINT32(pICR, AT91C_UDP_WAKEUP);     		
    }
	if (bits_are_set(pISR, AT91C_UDP_ENDBUSRES)){ // RESET UDP 

        //diag_printf("R");

        usbs_sam7_ep0.state = USBS_STATE_POWERED;
        usbs_state_notify(&usbs_sam7_ep0);
        usbs_sam7_handle_reset();

        HAL_WRITE_UINT32(pCSR0, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
        HAL_WRITE_UINT32(pIER, AT91C_UDP_EPINT0);     
        
        usbs_sam7_ep0.state = USBS_STATE_DEFAULT;
        usbs_state_notify(&usbs_sam7_ep0);
        
        HAL_WRITE_UINT32(pICR, AT91C_UDP_ENDBUSRES);     
	}
	if (bits_are_set(pISR, AT91C_UDP_SOFINT)){
        HAL_WRITE_UINT32(pICR, AT91C_UDP_SOFINT);     		
	}
	if (bits_are_set(pISR, AT91C_UDP_EXTRSM)){
        usbs_sam7_ep0.state = usbs_sam7_ep0.state & ~USBS_STATE_SUSPENDED;
        usbs_state_notify(&usbs_sam7_ep0);
        HAL_WRITE_UINT32(pICR, AT91C_UDP_EXTRSM);     		
	}
	if (bits_are_set(pISR, AT91C_UDP_RXRSM)){
        usbs_sam7_ep0.state = usbs_sam7_ep0.state & ~USBS_STATE_SUSPENDED;
        usbs_state_notify(&usbs_sam7_ep0);
        HAL_WRITE_UINT32(pICR, AT91C_UDP_RXRSM);     		
	}
	if (bits_are_set(pISR, AT91C_UDP_RXSUSP)){
        usbs_sam7_ep0.state = usbs_sam7_ep0.state | USBS_STATE_SUSPENDED;
        usbs_state_notify(&usbs_sam7_ep0);
        HAL_WRITE_UINT32(pICR, AT91C_UDP_RXSUSP);     		
	}
	if (bits_are_set(pISR, AT91C_UDP_EPINT0)){
        usbs_sam7_control_dsr();
    }
    for (n = 1; n < AT91SAM7S_USB_ENDPOINTS; n++){
        
        if (usbs_sam7_endpoint_transfer[n]){
            
            usbs_sam7_endpoint_dsr(n);
        }
    }

    cyg_drv_interrupt_unmask(vector);
}



static cyg_uint32 usbs_sam7_isr(cyg_vector_t vector, cyg_addrword_t data){
	
    cyg_uint8 n;
    bool need_dsr = false;
	
    CYG_ASSERT(CYGNUM_HAL_INTERRUPT_UDP == vector, "Wrong interrupts");
    CYG_ASSERT(0 == data, "ISR needs no data");
    
//diag_printf("<<iirq: %x>>\n", *(cyg_uint32 *) pISR & AT91C_UDP_ALLOWED_IRQs);

    for (n = 1; n < AT91SAM7S_USB_ENDPOINTS; n++){ /* Need any data endpoint a data transfer ? */

        if (bits_are_set(pISR, 1 << n)){

            need_dsr = need_dsr || usbs_sam7_endpoint_isr(n); /* Move the datas */
        }
    }
    
    if (bits_are_cleared(pISR, AT91C_UDP_ALLOWED_IRQs & 0xffffff01) && !need_dsr){ /* If we don't need any DSR */
diag_printf("-");	
		cyg_drv_interrupt_acknowledge(vector);
		
		return CYG_ISR_HANDLED;
    }

    cyg_drv_interrupt_mask(vector); /* Call the DSR */
    cyg_drv_interrupt_acknowledge(vector);

diag_printf("+");   
    return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
}



// ----------------------------------------------------------------------------
// Polling support. It is not clear that this is going to work particularly
// well since according to the documentation the hardware does not generate
// NAKs automatically - instead the ISR has to set the appropriate bits
// sufficiently quickly to avoid confusing the host.
//
// Calling the isr directly avoids duplicating code, but means that
// cyg_drv_interrupt_acknowledge() will get called when not inside a
// real interrupt handler. This should be harmless.

static void usbs_sam7_poll(usbs_control_endpoint* endpoint){
	
	dbg debug_printf("\n");

    CYG_ASSERT(endpoint == &usbs_sam7_ep0, "Wrong endpoint");
    if (CYG_ISR_CALL_DSR == usbs_sam7_isr(CYGNUM_HAL_INTERRUPT_UDP, 0)) {
        usbs_sam7_dsr(CYGNUM_HAL_INTERRUPT_UDP, 0, 0);
    }
}

// ----------------------------------------------------------------------------
// Initialization
//
// This routine gets called from a prioritized static constructor during
// eCos startup.


void usbs_sam7_init(void){
    
//    return;

    HAL_WRITE_UINT32(AT91C_BASE_PIOA + AT91_PIO_SODR, AT91C_PIO_PA4);
    HAL_WRITE_UINT32(AT91C_BASE_PIOA + AT91_PIO_PER, AT91C_PIO_PA3 | AT91C_PIO_PA3);
    HAL_WRITE_UINT32(AT91C_BASE_PIOA + AT91_PIO_OER, AT91C_PIO_PA4);
    
    usbs_sam7_handle_reset();
    
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_UDP,
        6,        // priority
        0,         // data
        &usbs_sam7_isr,
        &usbs_sam7_dsr,
        &usbs_sam7_intr_handle,
        &usbs_sam7_intr_data);
    
    cyg_drv_interrupt_attach(usbs_sam7_intr_handle);    
    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_UDP);
    
    HAL_WRITE_UINT32(AT91C_BASE_UDP + AT91_UDP_TXVC, 0);
    
    usbs_sam7_ep0.state = USBS_STATE_POWERED;
    usbs_state_notify(&usbs_sam7_ep0);
}



[-- Attachment #3: usbs_at91sam7s_data.cxx --]
[-- Type: text/plain, Size: 4292 bytes --]

#include <cyg/infra/diag.h>
#include <cyg/io/devtab.h>
#include <cyg/io/usb/usbs_at91sam7s.h>
#include <pkgconf/devs_usb_at91sam7s.h>

// ----------------------------------------------------------------------------
// Initialization. The goal here is to call usbs_sam7_init()
// early on during system startup, to take care of things like
// registering interrupt handlers etc. which are best done
// during system init.
//
// If the endpoint 0 devtab entry is available then its init()
// function can be used to take care of this. However the devtab
// entries are optional so an alternative mechanism must be
// provided. Unfortunately although it is possible to give
// a C function the constructor attribute, it cannot be given
// an initpri attribute. Instead it is necessary to define a
// dummy C++ class.

extern "C" void usbs_sam7_init(void);

#ifndef CYGVAR_DEVS_USB_AT91SAM7S_EP0_DEVTAB_ENTRY
	#error /* In Moment will ich einen /dev/...-Eintrag */
	
class usbs_sam7_initialization {
	public:
		usbs_sam7_initialization() {
		usbs_sam7_init();
	}
};

static usbs_sam7_initialization usbs_sam7_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);
#endif



// ----------------------------------------------------------------------------
// The devtab entries. Each of these is optional, many applications
// will want to use the lower-level API rather than go via
// open/read/write/ioctl.

#ifdef CYGVAR_DEVS_USB_AT91SAM7S_EP0_DEVTAB_ENTRY

// For endpoint 0 the only legal operations are get_config() and
// set_config(), and these are provided by the common package.

static bool usbs_sam7_devtab_ep0_init(struct cyg_devtab_entry* tab){
	
    CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab);
    
    usbs_sam7_init();
    
    return true;
}

CHAR_DEVIO_TABLE(usbs_sam7_ep0_devtab_functions,
        &cyg_devio_cwrite,
        &cyg_devio_cread,
        &cyg_devio_select,
        &usbs_devtab_get_config,
        &usbs_devtab_set_config);
        
CHAR_DEVTAB_ENTRY(usbs_sam7_ep0_devtab_entry,
        CYGDAT_DEVS_USB_AT91SAM7S_DEVTAB_BASENAME "0",
        0,
        &usbs_sam7_ep0_devtab_functions,
        &usbs_sam7_devtab_ep0_init,
        0,
        (void*) &usbs_sam7_ep0);
#else
	#error /* In Moment will ich einen /dev/...-Eintrag */
#endif

// ----------------------------------------------------------------------------
// Common routines for ep1..3


#if defined(CYGVAR_DEVS_USB_AT91SAM7S_EP1_DEVTAB_ENTRY) || defined(CYGVAR_DEVS_USB_AT91SAM7S_EP2_DEVTAB_ENTRY) || defined(CYGVAR_DEVS_USB_AT91SAM7S_EP3_DEVTAB_ENTRY)

static bool usbs_sam7_devtab_dummy_init(struct cyg_devtab_entry* tab){
	
    CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab);
    
    return true;
}

#endif









CHAR_DEVIO_TABLE(usbs_sam7_ep1_devtab_functions,
        &usbs_devtab_cwrite,
        &usbs_devtab_cread,
        &cyg_devio_select,
        &usbs_devtab_get_config,
        &usbs_devtab_set_config);

CHAR_DEVTAB_ENTRY(usbs_sam7_ep1_devtab_entry,
        CYGDAT_DEVS_USB_AT91SAM7S_DEVTAB_BASENAME "1",
        0,
        &usbs_sam7_ep1_devtab_functions,
        &usbs_sam7_devtab_dummy_init,
        0,
        (void*) &usbs_sam7_ep1);
         
         
                         
CHAR_DEVIO_TABLE(usbs_sam7_ep2_devtab_functions,
        &usbs_devtab_cwrite,
        &usbs_devtab_cread,
        &cyg_devio_select,
        &usbs_devtab_get_config,
        &usbs_devtab_set_config);

CHAR_DEVTAB_ENTRY(usbs_sam7_ep2_devtab_entry,
        CYGDAT_DEVS_USB_AT91SAM7S_DEVTAB_BASENAME "2",
        0,
        &usbs_sam7_ep2_devtab_functions,
        &usbs_sam7_devtab_dummy_init,
        0,
        (void*) &usbs_sam7_ep2);
  
  
                         
CHAR_DEVIO_TABLE(usbs_sam7_ep3_devtab_functions,
        &usbs_devtab_cwrite,
        &usbs_devtab_cread,
        &cyg_devio_select,
        &usbs_devtab_get_config,
        &usbs_devtab_set_config);

CHAR_DEVTAB_ENTRY(usbs_sam7_ep3_devtab_entry,
        CYGDAT_DEVS_USB_AT91SAM7S_DEVTAB_BASENAME "3",
        0,
        &usbs_sam7_ep3_devtab_functions,
        &usbs_sam7_devtab_dummy_init,
        0,
        (void*) &usbs_sam7_ep3);
                         
                         

[-- Attachment #4: usbs_at91sam7s.h --]
[-- Type: text/plain, Size: 745 bytes --]

#ifndef CYGONCE_USBS_AT91SAM7S_H
#define CYGONCE_USBS_AT91SAM7S_H


#include <cyg/io/usb/usbs.h>
#include <pkgconf/devs_usb_at91sam7s.h>

 
 
 
#define AT91SAM7S_USB_ENDPOINTS 4
 
extern usbs_control_endpoint    usbs_sam7_ep0;
extern usbs_rx_endpoint         usbs_sam7_ep1;
extern usbs_rx_endpoint         usbs_sam7_ep2;
extern usbs_rx_endpoint         usbs_sam7_ep3;


extern void usbs_sam7_ep1_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable);
extern void usbs_sam7_ep2_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable);
extern void usbs_sam7_ep3_init(usbs_rx_endpoint *pep, cyg_uint8 endpoint_type, cyg_bool enable);











#endif /* CYGONCE_USBS_AT91SAM7S_H */


[-- Attachment #5: Type: text/plain, Size: 148 bytes --]

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

             reply	other threads:[~2006-02-16  2:56 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-16  2:56 oliver munz @ s p e a g [this message]
2006-02-16  8:28 ` Andrew Lunn
2006-02-16 16:15 Derek Bouius
2006-02-16 16:26 ` Andrew Lunn
2006-02-16 16:31   ` Gary Thomas
2006-02-16 22:57     ` Bart Veer
2006-02-20  9:38       ` Nick Garnett
2006-02-20 11:49         ` Bart Veer
2006-02-20 14:30           ` Nick Garnett
2006-02-20 16:02             ` Bart Veer
2006-02-16 16:43   ` oliver munz @ s p e a g
2006-02-16 16:54   ` Derek Bouius
2006-02-20 13:42     ` Bart Veer
2006-02-20 17:35       ` Derek Bouius
2006-02-20 18:09         ` Bart Veer
2006-02-20 19:21           ` Derek Bouius
2006-02-16 16:45 ` oliver munz @ s p e a g
2006-02-16 20:07   ` Derek Bouius
2006-02-16 20:20     ` oliver munz @ s p e a g
     [not found] <000e01c63669$092c4500$6500a8c0@Burnt>
2006-02-21  9:55 ` Nick Garnett
2006-02-21 18:57   ` Robert Bryce
2006-02-21 20:35     ` Bart Veer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='012801c632a4$c8b5c9a0$5a188481@haus.hellmutstrasse.ch' \
    --to=munz@speag.ch \
    --cc=ecos-discuss@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).