diff options
Diffstat (limited to 'firmware/src')
| -rw-r--r-- | firmware/src/os/dbgu.c | 309 | ||||
| -rw-r--r-- | firmware/src/os/dbgu.h | 7 | ||||
| -rw-r--r-- | firmware/src/os/main.c | 1 | ||||
| -rw-r--r-- | firmware/src/os/pcd_enumerate.c | 75 | ||||
| -rw-r--r-- | firmware/src/os/req_ctx.c | 164 | ||||
| -rw-r--r-- | firmware/src/os/req_ctx.h | 46 | ||||
| -rw-r--r-- | firmware/src/os/system_irq.c | 18 | ||||
| -rw-r--r-- | firmware/src/os/usbcmd_generic.c | 2 | ||||
| -rw-r--r-- | firmware/src/os/wdt.c | 4 | ||||
| -rw-r--r-- | firmware/src/simtrace/iso7816_uart.c | 40 | ||||
| -rw-r--r-- | firmware/src/simtrace/iso7816_uart.h | 7 | ||||
| -rw-r--r-- | firmware/src/simtrace/main_simtrace.c | 43 | ||||
| -rw-r--r-- | firmware/src/simtrace/sim_switch.c | 7 | 
13 files changed, 509 insertions, 214 deletions
diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c index 113208e..72eaa88 100644 --- a/firmware/src/os/dbgu.c +++ b/firmware/src/os/dbgu.c @@ -45,18 +45,17 @@  #include <asm/system.h>  #include <compile.h> -//#define DEBUG_UNBUFFERED +/* In case we find that while (); is non interruptible, we may need to + * uncommend this line: */ +// #define ALLOW_INTERRUPT_LOOP asm("nop;nop;nop;nop;nop;nop;nop;nop;") + +#define ALLOW_INTERRUPT_LOOP + +/* DEBUG_BUFFER_SIZE MUST BE A POWER OF 2 */ +#define DEBUG_BUFFER_SIZE     (1 << 10) +#define DEBUG_BUFFER_MASK     (DEBUG_BUFFER_SIZE - 1) -#define USART_SYS_LEVEL 4  /*---------------------------- Global Variable ------------------------------*/ -//*--------------------------1-------------------------------------------------- -//* \fn    AT91F_DBGU_Printk -//* \brief This function is used to send a string through the DBGU channel -//*---------------------------------------------------------------------------- -void AT91F_DBGU_Ready(void) -{ -	while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY)) ; -}  //*----------------------------------------------------------------------------  //* Function Name       : Send_reset @@ -69,7 +68,7 @@ static void Send_reset(void)  	// Acknoledge the interrupt  	// Mark the End of Interrupt on the AIC  	AT91C_BASE_AIC->AIC_EOICR = 0; -	AT91F_DBGU_Ready(); +	while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY)) ;  	// Jump in reset  	pfct();  } @@ -92,26 +91,26 @@ static void DBGU_irq_handler(u_int32_t sr)  		break;  	case '1':		//* info  		udp_pullup_off(); -		AT91F_DBGU_Printk("Set Pull up\n\r"); +		AT91F_DBGU_Frame("Set Pull up\n\r");  		// Reset Application  		Send_reset();  		break;  	case '2': -		AT91F_DBGU_Printk("Toggling LED 1\n\r"); +		AT91F_DBGU_Frame("Toggling LED 1\n\r");  		led_toggle(1);  		break;  	case '3': -		AT91F_DBGU_Printk("Toggling LED 2\n\r"); +		AT91F_DBGU_Frame("Toggling LED 2\n\r");  		led_toggle(2);  		break;  	case '9': -		AT91F_DBGU_Printk("Resetting SAM7\n\r"); +		AT91F_DBGU_Frame("Resetting SAM7\n\r");  		AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|  				   AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);  		break;  	default:  		if (_main_dbgu(value) < 0) -			AT91F_DBGU_Printk("\n\r"); +			AT91F_DBGU_Frame("\n\r");  		break;  	}			// end switch  } @@ -148,17 +147,17 @@ void AT91F_DBGU_Init(void)  	//* open interrupt  	sysirq_register(AT91SAM7_SYSIRQ_DBGU, &DBGU_irq_handler); -	AT91F_DBGU_Printk("\n\r"); -	AT91F_DBGU_Printk("(C) 2006-2011 by Harald Welte <hwelte@hmw-consulting.de>\n\r" +	debugp("\n\r"); +	debugp("(C) 2006-2011 by Harald Welte <hwelte@hmw-consulting.de>\n\r"  			  "This software is FREE SOFTWARE licensed under GNU GPL\n\r"); -	AT91F_DBGU_Printk("Version " COMPILE_SVNREV +	debugp("Version " COMPILE_SVNREV  			  " compiled " COMPILE_DATE  			  " by " COMPILE_BY "\n\r\n\r"); -	AT91F_DBGU_Printk("\n\rDEBUG Interface:\n\r" +	debugp("\n\rDEBUG Interface:\n\r"  			  "0) Set Pull-up 1) Clear Pull-up 2) Toggle LED1 3) "  			  "Toggle LED2\r\n9) Reset\n\r"); -	debugp("RSTC_SR=0x%08x\n", rst_status); +	debugp("RSTC_SR=0x%08x\n\r", rst_status);  }  /* @@ -173,31 +172,36 @@ void AT91F_DBGU_Fini(void)  }  //*---------------------------------------------------------------------------- -//* \fn    AT91F_DBGU_Printk -//* \brief This function is used to send a string through the DBGU channel (Very low level debugging) -//*---------------------------------------------------------------------------- -void AT91F_DBGU_Printk(char *buffer) -{ -	while (*buffer != '\0') { -		while (!AT91F_US_TxReady((AT91PS_USART) AT91C_BASE_DBGU)) ; -		AT91F_US_PutChar((AT91PS_USART) AT91C_BASE_DBGU, *buffer++); -	} -} - -//*----------------------------------------------------------------------------  //* \fn    AT91F_DBGU_Frame -//* \brief This function is used to send a string through the DBGU channel +//* \brief This function is used to send a string through the DBGU channel (Very low level debugging)  //*----------------------------------------------------------------------------  void AT91F_DBGU_Frame(char *buffer)  { -	unsigned char len; - -	for (len = 0; buffer[len] != '\0'; len++) { +	unsigned long intcFlags; +	unsigned int len = 0; +	while (buffer[len++]) ALLOW_INTERRUPT_LOOP; +	len--; +	local_irq_save(intcFlags); +	AT91C_BASE_DBGU->DBGU_PTCR = 1 << 9; // Disable transfer +	if (AT91C_BASE_DBGU->DBGU_TNCR) { +		AT91C_BASE_DBGU->DBGU_PTCR = 1 << 8;  // Resume transfer +		local_irq_restore(intcFlags); +		while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0) ALLOW_INTERRUPT_LOOP; +		local_irq_save(intcFlags); +		AT91C_BASE_DBGU->DBGU_PTCR = 1 << 9; // Disable transfer +		AT91C_BASE_DBGU->DBGU_TPR = (unsigned)buffer; +		AT91C_BASE_DBGU->DBGU_TCR = len; +	} else if (AT91C_BASE_DBGU->DBGU_TCR) { +		AT91C_BASE_DBGU->DBGU_TNPR = (unsigned)buffer; +		AT91C_BASE_DBGU->DBGU_TNCR = len; +	} else { +		AT91C_BASE_DBGU->DBGU_TPR = (unsigned)buffer; +		AT91C_BASE_DBGU->DBGU_TCR = len;  	} - -	AT91F_US_SendFrame((AT91PS_USART) AT91C_BASE_DBGU,  -			   (unsigned char *)buffer, len, 0, 0); - +	AT91C_BASE_DBGU->DBGU_PTCR = 1 << 8;  // Resume transfer +	local_irq_restore(intcFlags); +	/* Return ONLY after we complete Transfer */ +	while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0) ALLOW_INTERRUPT_LOOP;  }  //*---------------------------------------------------------------------------- @@ -239,105 +243,180 @@ hexdump(const void *data, unsigned int len)  }  struct dbgu { -	char buf[4096]; -	char *next_inbyte; -	char *next_outbyte; +	char buf[DEBUG_BUFFER_SIZE]; +	/* Since debugp appears to require to be re-entrant, we need a +	 * bit more state variables +	 * in_head	Position where incoming *append* characters have +	 * 		finished copy to buffer +	 * in_tail	Position where NEW incoming *append* characters +	 * 		should COPY to +	 * out_head	Position where the LAST *possibly incomplete* +	 * 		dbgu_rb_flush started from +	 * out_tail	Position where the NEXT dbug_rb_flush should +	 * 		start from +	 * The position in the RING should be in this order: +	 * --> out_tail --> in_head --> in_tail --> out_head --> +	 */ +	volatile unsigned int in_head, in_tail, out_head, out_tail; + +	/* flush_stack is to indicate rb_flush is being executed, NOT to +	 * execute again */ +	volatile unsigned int flush_stack; + +	/* append_stack is to indicate the re-entrack stack order of the +	 * current dbgu_append call */ +	volatile unsigned int append_stack;  }; +  static struct dbgu dbgu;  void dbgu_rb_init(void)  { -	memset(dbgu.buf, 0, sizeof(dbgu.buf)); -	dbgu.next_inbyte = &dbgu.buf[0]; -	dbgu.next_outbyte = &dbgu.buf[0]; -} - -/* pull one char out of debug ring buffer */ -static int dbgu_rb_pull(char *ret) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	if (dbgu.next_outbyte == dbgu.next_inbyte) { -		local_irq_restore(flags); -		return -1; -	} - -	*ret = *dbgu.next_outbyte; - -	dbgu.next_outbyte++; -	if (dbgu.next_outbyte == &dbgu.buf[0]+sizeof(dbgu.buf)) { -		//AT91F_DBGU_Printk("WRAP DURING PULL\r\n"); -		dbgu.next_outbyte = &dbgu.buf[0]; -	} else if (dbgu.next_outbyte > &dbgu.buf[0]+sizeof(dbgu.buf)) { -		//AT91F_DBGU_Printk("OUTBYTE > END_OF_BUF!!\r\n"); -		dbgu.next_outbyte -= sizeof(dbgu.buf); -	} - -	local_irq_restore(flags); - -	return 0; -} - -static void __rb_flush(void) -{ -	char ch; -	while (dbgu_rb_pull(&ch) >= 0) { -		while (!AT91F_US_TxReady((AT91PS_USART) AT91C_BASE_DBGU)) ; -		AT91F_US_PutChar((AT91PS_USART) AT91C_BASE_DBGU, ch); -	} +	dbgu.in_head = dbgu.in_tail = dbgu.out_head = dbgu.out_tail = 0; +	dbgu.flush_stack = dbgu.append_stack = 0;  }  /* flush pending data from debug ring buffer to serial port */ -void dbgu_rb_flush(void) -{ -	__rb_flush(); -} -static void __dbgu_rb_append(char *data, int len) +static void dbgu_rb_flush(void)  { -	char *pos = dbgu.next_inbyte; - -	dbgu.next_inbyte += len; -	if (dbgu.next_inbyte >= &dbgu.buf[0]+sizeof(dbgu.buf)) { -		AT91F_DBGU_Printk("WRAP DURING APPEND\r\n"); -		dbgu.next_inbyte -= sizeof(dbgu.buf); +	unsigned long intcFlags; +	unsigned int flush_stack, start, len; +	if (dbgu.in_head == dbgu.out_tail) +		return; + +	/* Transmit can ONLY be disabled when Interrupt is disabled.  We +	 * don't want to be interrupted while Transmit is disabled. */ +	local_irq_save(intcFlags); +	flush_stack = dbgu.flush_stack; +	dbgu.flush_stack = 1; +	if (flush_stack) { +		local_irq_restore(intcFlags); +		return;  	} - -	memcpy(pos, data, len); +	AT91C_BASE_DBGU->DBGU_PTCR = 1 << 9; // Disable transfer +	start = (unsigned)dbgu.buf + dbgu.out_tail; +	len = (dbgu.in_head - dbgu.out_tail) & DEBUG_BUFFER_MASK; +	if (dbgu.in_head > dbgu.out_tail || dbgu.in_head == 0) { // Just 1 fragmentf +		if (AT91C_BASE_DBGU->DBGU_TNCR) { +			if (AT91C_BASE_DBGU->DBGU_TNPR + AT91C_BASE_DBGU->DBGU_TNCR == start) { +				AT91C_BASE_DBGU->DBGU_TNCR += len; +			} else { +				AT91C_BASE_DBGU->DBGU_PTCR = 1 << 8;  // Resume transfer +				local_irq_restore(intcFlags); +				while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0) ALLOW_INTERRUPT_LOOP; +				dbgu.out_head = dbgu.out_tail; // in case we are interrupted, they may need more space +				/* Since the ONLY place where Transmit is started is dbgu_rb_flush and AT91F_DBGU_Frame and: +				 * 1) AT91F_DBGU_Frame always leave the dbgu in a TX completed state +				 * 2) dbgu_rb is non-reentrant by safeguard at the beginning of this routing +				 * We can assume that after this INTERRUPTIBLE while loop, there are NO data to be transmitted +				 */ +				local_irq_save(intcFlags); +				AT91C_BASE_DBGU->DBGU_PTCR = 1 << 9; // Disable transfer +				AT91C_BASE_DBGU->DBGU_TPR = start; +				AT91C_BASE_DBGU->DBGU_TCR = len; +			} +		} else if (AT91C_BASE_DBGU->DBGU_TCR) { +		  if (AT91C_BASE_DBGU->DBGU_TPR + AT91C_BASE_DBGU->DBGU_TCR == start) { +		    dbgu.out_head = AT91C_BASE_DBGU->DBGU_TPR - (unsigned)dbgu.buf; +		    AT91C_BASE_DBGU->DBGU_TCR += len; +		  } else { +		    AT91C_BASE_DBGU->DBGU_TNPR = start; +		    AT91C_BASE_DBGU->DBGU_TNCR = len; +		  } +		} else { +		  AT91C_BASE_DBGU->DBGU_TPR = start; +		  AT91C_BASE_DBGU->DBGU_TCR = len; +		  dbgu.out_head = dbgu.out_tail; +		} +	} else { // 2 fragments +		if ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0) { +			AT91C_BASE_DBGU->DBGU_PTCR = 1 << 8;  // Resume transfer +			local_irq_restore(intcFlags); +			while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0) ALLOW_INTERRUPT_LOOP; +			dbgu.out_head = dbgu.out_tail; // in case we are interrupted, they may need more space +			local_irq_save(intcFlags); +			AT91C_BASE_DBGU->DBGU_PTCR = 1 << 9; // Disable transfer +		} +		AT91C_BASE_DBGU->DBGU_TPR = start; +		AT91C_BASE_DBGU->DBGU_TCR = DEBUG_BUFFER_SIZE - dbgu.out_tail; +		AT91C_BASE_DBGU->DBGU_TNPR = (unsigned)dbgu.buf; +		AT91C_BASE_DBGU->DBGU_TNCR = dbgu.in_head; +		dbgu.out_head = dbgu.out_tail; +	} +	AT91C_BASE_DBGU->DBGU_PTCR = 1 << 8;  // Resume transfer +	dbgu.out_tail = dbgu.in_head; +	dbgu.flush_stack = 0; +	local_irq_restore(intcFlags);  }  void dbgu_rb_append(char *data, int len)  { -	unsigned long flags; -	int bytes_left; -	char *data_cur; +	/* Rules: +	 * 1) ONLY the LOWEST order of dbgu_rb_append CAN update in_head; +	 * 2) WHEN updateing in_head, always set it to the current in_tail (since all higher order dbgu_rb_append have completed +	 * 3) ONLY the LOWEST order of dbgu_rb_append MAY call dbgu_rb_flush +	 */ +	unsigned long intcFlags; +	unsigned int append_stack, avail, local_head; +	if (len <= 0) +		return; -	local_irq_save(flags); - -	bytes_left = &dbgu.buf[0]+sizeof(dbgu.buf)-dbgu.next_inbyte; -	data_cur = data; - -	if (len > bytes_left) { -		AT91F_DBGU_Printk("LEN > BYTES_LEFT\r\n"); -		__rb_flush(); -		__dbgu_rb_append(data_cur, bytes_left); -		len -= bytes_left; -		data_cur += bytes_left; +	local_irq_save(intcFlags); +	append_stack = dbgu.append_stack++; +	if (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) +		dbgu.out_head = dbgu.out_tail; +	avail = (dbgu.out_head - 1 - dbgu.in_tail) & DEBUG_BUFFER_MASK; +	local_head = (unsigned)len; +	if (local_head > avail) { +		local_irq_restore(intcFlags); +		while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0); +		local_irq_save(intcFlags); +		while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) == 0); +		dbgu.out_head = dbgu.out_tail; +		avail = (dbgu.out_head - 1 - dbgu.in_tail) & DEBUG_BUFFER_MASK; +		if (local_head > avail) { +			local_head -= avail; +			AT91C_BASE_DBGU->DBGU_TPR = (unsigned)data; +			AT91C_BASE_DBGU->DBGU_TCR = local_head; +			data += local_head; +			len = avail; +		}  	} -	__dbgu_rb_append(data_cur, len); - -	local_irq_restore(flags); +	local_head = dbgu.in_tail; +	dbgu.in_tail += len; +	dbgu.in_tail &= DEBUG_BUFFER_MASK; +	local_irq_restore(intcFlags); +	if (dbgu.out_head <= local_head) { +		// We may have to wrap around: out_head won't change because NO call to flush will be made YET +		avail = DEBUG_BUFFER_SIZE - local_head; +		if (avail >= (unsigned)len) { +			memcpy(dbgu.buf + local_head, data, (size_t)len); +		} else { +			memcpy(dbgu.buf + local_head, data, (size_t)avail); +			memcpy(dbgu.buf, data + avail, (size_t)(len - avail)); +		} +	} else { +		memcpy(dbgu.buf + local_head, data, len); +	} +	local_irq_save(intcFlags); +	dbgu.append_stack--; +	if (!append_stack) +		dbgu.in_head = dbgu.in_tail; +	local_irq_restore(intcFlags); +	if (!append_stack) +		dbgu_rb_flush();  }  static char dbg_buf[256]; +static int line_num = 0;  void debugp(const char *format, ...)  {  	va_list ap;  	va_start(ap, format); -	vsnprintf(dbg_buf, sizeof(dbg_buf)-1, format, ap); +	sprintf(dbg_buf, "[%06X] ", line_num++); +	vsnprintf(dbg_buf + 9, sizeof(dbg_buf)-10, format, ap);  	va_end(ap);  	dbg_buf[sizeof(dbg_buf)-1] = '\0';			 diff --git a/firmware/src/os/dbgu.h b/firmware/src/os/dbgu.h index c36ac8c..2a5b59d 100644 --- a/firmware/src/os/dbgu.h +++ b/firmware/src/os/dbgu.h @@ -17,17 +17,14 @@  #define AT91C_DBGU_BAUD 115200
 -//#define DEBUGP(x)	AT91F_DBGU_Printk(x)
 -
  //* ----------------------- External Function Prototype -----------------------
  extern const char *hexdump(const void *data, unsigned int len);
  void AT91F_DBGU_Init(void);
  void AT91F_DBGU_Fini(void);
 -void AT91F_DBGU_Printk(	char *buffer);
 -void AT91F_DBGU_Frame(	char *buffer);
 +void AT91F_DBGU_Frame(char *buffer);
 +#define AT91F_DBGU_Printk(x) AT91F_DBGU_Frame(x)
  int AT91F_DBGU_Get( char *val);
 -void dbgu_rb_flush(void);
  #ifndef __WinARM__
  void AT91F_DBGU_scanf(char * type,unsigned int * val);
  #endif
 diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c index 968f6ad..363befc 100644 --- a/firmware/src/os/main.c +++ b/firmware/src/os/main.c @@ -77,7 +77,6 @@ int main(void)  	while (1) {  		/* Call application specific main idle function */  		_main_func(); -		dbgu_rb_flush();  		/* restart watchdog timer */  		wdt_restart(); diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c index 3a7397f..403cef9 100644 --- a/firmware/src/os/pcd_enumerate.c +++ b/firmware/src/os/pcd_enumerate.c @@ -99,8 +99,10 @@ struct epstate {  };  static const struct epstate epstate[] = { -	[0] =	{ .state_busy = RCTX_STATE_INVALID }, -	[1] =	{ .state_busy = RCTX_STATE_INVALID }, +	[0] =	{ .state_busy = RCTX_STATE_UDP_EP0_BUSY, +		  .state_pending = RCTX_STATE_UDP_EP0_PENDING }, +	[1] =	{ .state_busy = RCTX_STATE_UDP_EP1_BUSY, +		  .state_pending = RCTX_STATE_UDP_EP1_PENDING },  	[2] =	{ .state_busy = RCTX_STATE_UDP_EP2_BUSY,  		  .state_pending = RCTX_STATE_UDP_EP2_PENDING },  	[3] =	{ .state_busy = RCTX_STATE_UDP_EP3_BUSY, @@ -112,8 +114,6 @@ static void reset_ep(unsigned int ep)  	AT91PS_UDP pUDP = upcd.pUdp;  	struct req_ctx *rctx; -	//pUDP->UDP_CSR[ep] = AT91C_UDP_EPEDS; -  	atomic_set(&upcd.ep[ep].pkts_in_transit, 0);  	/* free all currently transmitting contexts */ @@ -125,6 +125,7 @@ static void reset_ep(unsigned int ep)  	pUDP->UDP_RSTEP |= (1 << ep);  	pUDP->UDP_RSTEP &= ~(1 << ep); +	pUDP->UDP_CSR[ep] = AT91C_UDP_EPEDS;  	upcd.ep[ep].incomplete.rctx = NULL;  } @@ -137,7 +138,7 @@ void udp_unthrottle(void)  	pUDP->UDP_IER = AT91C_UDP_EPINT1;  } -static int __udp_refill_ep(int ep) +int udp_refill_ep(int ep)  {  	u_int16_t i;  	AT91PS_UDP pUDP = upcd.pUdp; @@ -152,9 +153,11 @@ static int __udp_refill_ep(int ep)  	/* If there are already two packets in transit, the DPR of  	 * the SAM7 UDC doesn't have space for more data */ -	if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2) { +	if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2)  		return -EBUSY; -	} + +	/* disable endpoint interrup */ +	pUDP->UDP_IDR |= 1 << ep;  	/* If we have an incompletely-transmitted req_ctx (>EP size),  	 * we need to transmit the rest and finish the transaction */ @@ -165,8 +168,23 @@ static int __udp_refill_ep(int ep)  		/* get pending rctx and start transmitting from zero */  		rctx = req_ctx_find_get(0, epstate[ep].state_pending,   					epstate[ep].state_busy); -		if (!rctx) +		if (!rctx) { +			/* re-enable endpoint interrupt */ +			pUDP->UDP_IER |= 1 << ep;  			return 0; +		} +		if (rctx->tot_len == 0) { +			/* re-enable endpoint interrupt */ +			pUDP->UDP_IER |= 1 << ep; +			req_ctx_put(rctx); +			return 0; +		} +		DEBUGPCR("USBT(D=%08X, L=%04u, P=$02u) H4/T4: %02X %02X %02X %02X / %02X %02X %02X %02X", +			 rctx->data, rctx->tot_len, req_ctx_count(epstate[ep].state_pending), +			 rctx->data[4], rctx->data[5], rctx->data[6], rctx->data[7], +			 rctx->data[rctx->tot_len - 4], rctx->data[rctx->tot_len - 3], +			 rctx->data[rctx->tot_len - 2], rctx->data[rctx->tot_len - 1]); +  		start = 0;  		upcd.ep[ep].incomplete.bytes_sent = 0; @@ -178,8 +196,6 @@ static int __udp_refill_ep(int ep)  		end = start + AT91C_EP_IN_SIZE;  	/* fill FIFO/DPR */ -	DEBUGII("RCTX_tx(ep=%u,ctx=%u):%u ", ep, req_ctx_num(rctx), -		end - start);  	for (i = start; i < end; i++)   		pUDP->UDP_FDR[ep] = rctx->data[i]; @@ -188,15 +204,13 @@ static int __udp_refill_ep(int ep)  		pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;  	} -	if ((end - start < AT91C_EP_OUT_SIZE) || -	    (((end - start) == 0) && end && (rctx->tot_len % AT91C_EP_OUT_SIZE) == 0)) { +	if (end == rctx->tot_len) {  		/* CASE 1: return context to pool, if  		 * - packet transfer < AT91C_EP_OUT_SIZE  		 * - after ZLP of transfer == AT91C_EP_OUT_SIZE  		 * - after ZLP of transfer % AT91C_EP_OUT_SIZE == 0  		 * - after last packet of transfer % AT91C_EP_OUT_SIZE != 0  		 */ -		DEBUGII("RCTX(ep=%u,ctx=%u)_tx_done ", ep, req_ctx_num(rctx));  		upcd.ep[ep].incomplete.rctx = NULL;  		req_ctx_put(rctx);  	} else { @@ -204,25 +218,15 @@ static int __udp_refill_ep(int ep)  		 * - after data of transfer == AT91C_EP_OUT_SIZE  		 * - after data of transfer > AT91C_EP_OUT_SIZE  		 * - after last packet of transfer % AT91C_EP_OUT_SIZE == 0 -		 */ +	         */  		upcd.ep[ep].incomplete.rctx = rctx;  		upcd.ep[ep].incomplete.bytes_sent += end - start; -		DEBUGII("RCTX(ep=%u)_tx_cont ", ep);  	} -	return 1; -} +	/* re-enable endpoint interrupt */ +	pUDP->UDP_IER |= 1 << ep; -int udp_refill_ep(int ep) -{ -	unsigned long flags; -	int ret; - -	local_irq_save(flags); -	ret = __udp_refill_ep(ep); -	local_irq_restore(flags); - -	return ret; +	return 1;  }  static void udp_irq(void) @@ -238,19 +242,18 @@ static void udp_irq(void)  		DEBUGI("ENDBUSRES ");  		pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;  		pUDP->UDP_IER = AT91C_UDP_EPINT0; -		/* reset all endpoints */ -		pUDP->UDP_RSTEP = (unsigned int)-1; -		pUDP->UDP_RSTEP = 0; +		reset_ep(0); +		reset_ep(1); +		reset_ep(2); +		reset_ep(3); +  		/* Enable the function */  		pUDP->UDP_FADDR = AT91C_UDP_FEN; +  		/* Configure endpoint 0 */  		pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);  		upcd.cur_config = 0;  		upcd.state = USB_STATE_DEFAULT; - -		reset_ep(1); -		reset_ep(2); -		reset_ep(3);  #ifdef CONFIG_DFU  		if (*dfu->dfu_state == DFU_STATE_appDETACH) { @@ -359,7 +362,7 @@ cont_ep2:  			if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)  				pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY; -			__udp_refill_ep(2); +			udp_refill_ep(2);  		}  	}  	if (isr & AT91C_UDP_EPINT3) { @@ -374,7 +377,7 @@ cont_ep2:  			if (atomic_dec_return(&upcd.ep[3].pkts_in_transit) == 1)  				pUDP->UDP_CSR[3] |= AT91C_UDP_TXPKTRDY; -			__udp_refill_ep(3); +			udp_refill_ep(3);  		}  	}  	if (isr & AT91C_UDP_RXSUSP) { diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index cc8d57b..722c099 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -29,11 +29,11 @@  /* FIXME: locking, FIFO order processing */  #if defined(__AT91SAM7S64__) || defined(RUN_FROM_RAM) -#define NUM_RCTX_SMALL 16 -#define NUM_RCTX_LARGE 1 +#define NUM_RCTX_SMALL 0 +#define NUM_RCTX_LARGE 8  #else -#define NUM_RCTX_SMALL 8 -#define NUM_RCTX_LARGE 4 +#define NUM_RCTX_SMALL 0 +#define NUM_RCTX_LARGE 20  #endif  #define NUM_REQ_CTX	(NUM_RCTX_SMALL+NUM_RCTX_LARGE) @@ -43,63 +43,173 @@ static u_int8_t rctx_data_large[NUM_RCTX_LARGE][RCTX_SIZE_LARGE];  static struct req_ctx req_ctx[NUM_REQ_CTX]; +/* queue of RCTX indexed by their current state */ +static struct req_ctx *req_ctx_queues[RCTX_STATE_COUNT], *req_ctx_tails[RCTX_STATE_COUNT]; +static unsigned req_counts[RCTX_STATE_COUNT]; +  struct req_ctx __ramfunc *req_ctx_find_get(int large,  				 unsigned long old_state,   				 unsigned long new_state)  { +	struct req_ctx *toReturn;  	unsigned long flags; -	u_int8_t i; -	 -	if (large) -		i = NUM_RCTX_SMALL; -	else -		i = 0; -	for (; i < NUM_REQ_CTX; i++) { -		local_irq_save(flags); -		if (req_ctx[i].state == old_state) { -			req_ctx[i].state = new_state; -			local_irq_restore(flags); -			return &req_ctx[i]; -		} -		local_irq_restore(flags); +	if (old_state >= RCTX_STATE_COUNT || new_state >= RCTX_STATE_COUNT) { +		DEBUGPCR("Invalid parameters for req_ctx_find_get"); +		return NULL;  	} - -	return NULL; +	local_irq_save(flags); +	toReturn = req_ctx_queues[old_state]; +	if (toReturn) { +		if ((req_ctx_queues[old_state] = toReturn->next)) +			toReturn->next->prev = NULL; +		else +			req_ctx_tails[old_state] = NULL; +		req_counts[old_state]--; +		if ((toReturn->prev = req_ctx_tails[new_state])) +			toReturn->prev->next = toReturn; +		else +			req_ctx_queues[new_state] = toReturn; +		req_ctx_tails[new_state] = toReturn; +		toReturn->state = new_state; +		toReturn->next = NULL; +		req_counts[new_state]++; +	} +	local_irq_restore(flags); +	return toReturn;  }  u_int8_t req_ctx_num(struct req_ctx *ctx)  { -	return ((char *)ctx - (char *)&req_ctx[0])/sizeof(*ctx); +	return ctx - req_ctx;  }  void req_ctx_set_state(struct req_ctx *ctx, unsigned long new_state)  {  	unsigned long flags; +	unsigned old_state; -	/* FIXME: do we need this kind of locking, we're UP! */ +	if (new_state >= RCTX_STATE_COUNT) { +		DEBUGPCR("Invalid new_state for req_ctx_set_state"); +		return; +	}  	local_irq_save(flags); +	old_state = ctx->state; +	if (ctx->prev) +		ctx->prev->next = ctx->next; +	else +		req_ctx_queues[old_state] = ctx->next; +	if (ctx->next) +		ctx->next->prev = ctx->prev; +	else +		req_ctx_tails[old_state] = ctx->prev; +	req_counts[old_state]--; +	if ((ctx->prev = req_ctx_tails[new_state])) +		ctx->prev->next = ctx; +	else +		req_ctx_queues[new_state] = ctx; +	req_ctx_tails[new_state] = ctx;  	ctx->state = new_state; +	ctx->next = NULL; +	req_counts[new_state]++;  	local_irq_restore(flags);  } +#ifdef DEBUG_REQCTX +void req_print(int state) { +	int count = 0; +	struct req_ctx *ctx, *last = NULL; +	DEBUGP("State [%02i] start <==> ", state); +	ctx = req_ctx_queues[state]; +	while (ctx) { +		if (last != ctx->prev) +			DEBUGP("*INV_PREV* "); +		DEBUGP("%08X => ", ctx); +		last = ctx; +		ctx = ctx->next; +		count++; +		if (count > NUM_REQ_CTX) { +		  DEBUGP("*WILD POINTER* => "); +		  break; +		} +	} +	DEBUGPCR("NULL"); +	if (!req_ctx_queues[state] && req_ctx_tails[state]) { +		DEBUGPCR("NULL head, NON-NULL tail"); +	} +	if (last != req_ctx_tails[state]) { +		DEBUGPCR("Tail does not match last element"); +	} +} +#endif +  void req_ctx_put(struct req_ctx *ctx)  { -	req_ctx_set_state(ctx, RCTX_STATE_FREE); +	unsigned long intcFlags; +	unsigned old_state; + +	local_irq_save(intcFlags); +	old_state = ctx->state; +	if (ctx->prev) +		ctx->prev->next = ctx->next; +	else +		req_ctx_queues[old_state] = ctx->next; +	if (ctx->next) +		ctx->next->prev = ctx->prev; +	else +		req_ctx_tails[old_state] = ctx->prev; +	req_counts[old_state]--; +	if ((ctx->prev = req_ctx_tails[RCTX_STATE_FREE])) +		ctx->prev->next = ctx; +	else +		req_ctx_queues[RCTX_STATE_FREE] = ctx; +	req_ctx_tails[RCTX_STATE_FREE] = ctx; +	ctx->state = RCTX_STATE_FREE; +	ctx->next = NULL; +	req_counts[RCTX_STATE_FREE]++; +	local_irq_restore(intcFlags); +} + +unsigned int req_ctx_count(unsigned long state) +{ +	if (state >= RCTX_STATE_COUNT) +		return 0; +	return req_counts[state];  }  void req_ctx_init(void)  {  	int i; -  	for (i = 0; i < NUM_RCTX_SMALL; i++) { +		req_ctx[i].prev = req_ctx + i - 1; +		req_ctx[i].next = req_ctx + i + 1;  		req_ctx[i].size = RCTX_SIZE_SMALL; +		req_ctx[i].tot_len = 0;  		req_ctx[i].data = rctx_data[i];  		req_ctx[i].state = RCTX_STATE_FREE; +		DEBUGPCR("SMALL req_ctx[%02i] initialized at %08X, Data: %08X => %08X", +			i, req_ctx + i, req_ctx[i].data, req_ctx[i].data + RCTX_SIZE_SMALL); +	} + +	for (; i < NUM_REQ_CTX; i++) { +		req_ctx[i].prev = req_ctx + i - 1; +		req_ctx[i].next = req_ctx + i + 1; +		req_ctx[i].size = RCTX_SIZE_LARGE; +		req_ctx[i].tot_len = 0; +		req_ctx[i].data = rctx_data_large[i]; +		req_ctx[i].state = RCTX_STATE_FREE; +		DEBUGPCR("LARGE req_ctx[%02i] initialized at %08X, Data: %08X => %08X", +			i, req_ctx + i, req_ctx[i].data, req_ctx[i].data + RCTX_SIZE_LARGE);  	} +	req_ctx[0].prev = NULL; +	req_ctx[NUM_REQ_CTX - 1].next = NULL; + +	req_ctx_queues[RCTX_STATE_FREE] = req_ctx; +	req_ctx_tails[RCTX_STATE_FREE] = req_ctx + NUM_REQ_CTX - 1; +	req_counts[RCTX_STATE_FREE] = NUM_REQ_CTX; -	for (i = 0; i < NUM_RCTX_LARGE; i++) { -		req_ctx[NUM_RCTX_SMALL+i].size = RCTX_SIZE_LARGE; -		req_ctx[NUM_RCTX_SMALL+i].data = rctx_data_large[i]; +	for (i = RCTX_STATE_FREE + 1; i < RCTX_STATE_COUNT; i++) { +		req_ctx_queues[i] = req_ctx_tails[i] = NULL; +		req_counts[i] = 0;  	}  } diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h index 94b5c5a..92c21a7 100644 --- a/firmware/src/os/req_ctx.h +++ b/firmware/src/os/req_ctx.h @@ -1,11 +1,10 @@  #ifndef _REQ_CTX_H  #define _REQ_CTX_H -#define RCTX_SIZE_LARGE	2048 -#define RCTX_SIZE_SMALL	128 +#define RCTX_SIZE_LARGE	960 +#define RCTX_SIZE_SMALL	320  #define MAX_HDRSIZE	sizeof(struct openpcd_hdr) -#define MAX_REQSIZE	(64-MAX_HDRSIZE)  #define req_buf_payload(x)	(x->data[x->hdr_len])  #define req_buf_hdr(x)		(x->data[0]) @@ -15,35 +14,38 @@  struct req_ctx {  	volatile u_int32_t state; +	volatile struct req_ctx *prev, *next;  	u_int16_t size;  	u_int16_t tot_len;  	u_int8_t *data;  }; -#define RCTX_STATE_FREE			0xfe -#define RCTX_STATE_UDP_RCV_BUSY		0x01 -#define RCTX_STATE_UDP_RCV_DONE		0x02 -#define RCTX_STATE_MAIN_PROCESSING	0x03 -#define RCTX_STATE_RC632IRQ_BUSY	0x04 - -#define RCTX_STATE_UDP_EP2_PENDING	0x10 -#define RCTX_STATE_UDP_EP2_BUSY		0x11 - -#define RCTX_STATE_UDP_EP3_PENDING	0x12 -#define RCTX_STATE_UDP_EP3_BUSY		0x13 - -#define RCTX_STATE_SSC_RX_BUSY		0x20 - -#define RCTX_STATE_LIBRFID_BUSY		0x30 - -#define RCTX_STATE_PIOIRQ_BUSY		0x80 - -#define RCTX_STATE_INVALID		0xff +#define RCTX_STATE_FREE                 0 +#define RCTX_STATE_UDP_RCV_BUSY         1 +#define RCTX_STATE_UDP_RCV_DONE         2 +#define RCTX_STATE_MAIN_PROCESSING      3 +#define RCTX_STATE_RC632IRQ_BUSY        4 +#define RCTX_STATE_UDP_EP2_PENDING      5 +#define RCTX_STATE_UDP_EP2_BUSY         6 +#define RCTX_STATE_UDP_EP3_PENDING      7 +#define RCTX_STATE_UDP_EP3_BUSY         8 +#define RCTX_STATE_SSC_RX_BUSY          9 +#define RCTX_STATE_LIBRFID_BUSY        10 +#define RCTX_STATE_PIOIRQ_BUSY         11 +#define RCTX_STATE_INVALID             12 +// Nominally UNUSED states +#define RCTX_STATE_UDP_EP0_PENDING     13 +#define RCTX_STATE_UDP_EP0_BUSY        14 +#define RCTX_STATE_UDP_EP1_PENDING     15 +#define RCTX_STATE_UDP_EP1_BUSY        16 +// Count of the number of STATES +#define RCTX_STATE_COUNT               17  extern struct req_ctx __ramfunc *req_ctx_find_get(int large, unsigned long old_state, unsigned long new_state);  extern struct req_ctx *req_ctx_find_busy(void);  extern void req_ctx_set_state(struct req_ctx *ctx, unsigned long new_state);  extern void req_ctx_put(struct req_ctx *ctx);  extern u_int8_t req_ctx_num(struct req_ctx *ctx); +unsigned int req_ctx_count(unsigned long state);  #endif /* _REQ_CTX_H */ diff --git a/firmware/src/os/system_irq.c b/firmware/src/os/system_irq.c index dc787eb..4c1da31 100644 --- a/firmware/src/os/system_irq.c +++ b/firmware/src/os/system_irq.c @@ -25,15 +25,15 @@  #include <os/system_irq.h>  #include <os/dbgu.h> +#include <string.h>  #include "../openpcd.h"  static sysirq_hdlr *sysirq_hdlrs[AT91SAM7_SYSIRQ_COUNT]; -static void sys_irq(void) +void sys_irq(u_int32_t previous_pc)  {  	u_int32_t sr; -	DEBUGP("sys_irq ");  	/* Somehow Atmel decided to do really stupid interrupt sharing  	 * for commonly-used interrupts such as the timer irq */ @@ -139,6 +139,10 @@ static void sys_irq(void)  	if (*AT91C_WDTC_WDMR & AT91C_WDTC_WDFIEN) {  		sr = *AT91C_WDTC_WDSR;  		if (sr) { +			char dbg_buf[100]; +			sprintf(dbg_buf, "sys_irq [Old PC = %08X]\n\r", previous_pc); +			AT91F_DBGU_Frame(dbg_buf); +  			DEBUGP("WDT(");  			if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) {  				DEBUGP("handler "); @@ -154,6 +158,14 @@ static void sys_irq(void)  	DEBUGPCR("END");  } +static void sysirq_entry(void) +{ +	/* DON'T MODIFY THIS SECTION AND Cstartup.S/IRQ_Handler_Entry */ +	register unsigned *previous_pc asm("r0"); +	asm("ADD R1, SP, #16; LDR R0, [R1]"); +	sys_irq(previous_pc); +} +  void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr)  {  	if (irq >= AT91SAM7_SYSIRQ_COUNT) @@ -167,6 +179,6 @@ void sysirq_init(void)  	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS,  			      OPENPCD_IRQ_PRIO_SYS,  			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, -			      &sys_irq); +			      &sysirq_entry);  	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);  } diff --git a/firmware/src/os/usbcmd_generic.c b/firmware/src/os/usbcmd_generic.c index 77b992f..aff13eb 100644 --- a/firmware/src/os/usbcmd_generic.c +++ b/firmware/src/os/usbcmd_generic.c @@ -132,7 +132,7 @@ static int gen_usb_rx(struct req_ctx *rctx)  void usbcmd_gen_init(void)  { -	DEBUGP("Inititalizing usbcmd_gen_init\n"); +	DEBUGP("Inititalizing usbcmd_gen_init\n\r");  	/* setup FLASH write support for environment storage */  	flash_init(); diff --git a/firmware/src/os/wdt.c b/firmware/src/os/wdt.c index 99d86a1..d5c19a3 100644 --- a/firmware/src/os/wdt.c +++ b/firmware/src/os/wdt.c @@ -33,9 +33,9 @@  static void wdt_irq(u_int32_t sr)  {  	if (sr & 1) -		DEBUGPCRF("================> WATCHDOG EXPIRED !!!!!"); +		AT91F_DBGU_Frame("================> WATCHDOG EXPIRED !!!!!\n\r");  	if (sr & 2) -		DEBUGPCRF("================> WATCHDOG ERROR !!!!!"); +		AT91F_DBGU_Frame("================> WATCHDOG ERROR !!!!!\n\r");  }  void wdt_restart(void) diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 52522c0..9e8ace9 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -125,6 +125,20 @@ static const u_int8_t di_table[] = {  	12, 20, 2, 4, 8, 16, 32, 64,  }; +void iso_uart_report_errors(void) +{ +	static unsigned lastOverrun = 0, lastParity = 0, lastFrame = 0; +	if (isoh.stats.overrun != lastOverrun) { +		DEBUGPCR("UART overrun: %u", lastOverrun = isoh.stats.overrun); +	} +	if (isoh.stats.frame_err != lastFrame) { +		DEBUGPCR("UART frame error: %u", lastFrame = isoh.stats.frame_err); +	} +	if (isoh.stats.parity_err != lastParity) { +		DEBUGPCR("UART parity error: %u", lastParity = isoh.stats.parity_err); +	} +} +  void iso_uart_stats_dump(void)  {  	DEBUGPCRF("no_rctx: %u, rctx_sent: %u, rst: %u, pps: %u, bytes: %u, " @@ -567,6 +581,26 @@ void iso7816_wtime_expired(void)  	set_state(&isoh, ISO7816_S_WAIT_APDU);  } +void iso_uart_flush(void) +{ +	send_rctx(&isoh); +} + +void iso_uart_idleflush(void) +{ +	static struct req_ctx *last_req = NULL; +	static u_int16_t last_len = 0; + +	if (last_req == isoh.rctx && +	    last_len == isoh.rctx->tot_len && +	    req_ctx_count(RCTX_STATE_UDP_EP2_PENDING) == 0 && +	    (isoh.sh.flags & SIMTRACE_FLAG_ATR) == 0) { +		send_rctx(&isoh); +	} +	last_req = isoh.rctx; +	last_len = isoh.rctx->tot_len; +} +  static __ramfunc void usart_irq(void)  {  	u_int32_t csr = usart->US_CSR; @@ -610,9 +644,13 @@ static __ramfunc void usart_irq(void)  static void reset_pin_irq(u_int32_t pio)  {  	if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio)) { +		/* make sure to flush pending req_ctx */ +		iso_uart_flush();  		DEBUGPCR("nRST");  		set_state(&isoh, ISO7816_S_RESET);  	} else { +		/* make sure to flush pending req_ctx */ +		iso_uart_flush();  		DEBUGPCR("RST");  		set_state(&isoh, ISO7816_S_WAIT_ATR);  		isoh.stats.rst++; @@ -675,6 +713,8 @@ void iso_uart_init(void)  {  	DEBUGPCR("USART Initializing"); +	memset(&isoh, 0, sizeof(isoh)); +  	refill_rctx(&isoh);  	/* make sure we get clock from the power management controller */ diff --git a/firmware/src/simtrace/iso7816_uart.h b/firmware/src/simtrace/iso7816_uart.h index beb0b23..969e6f9 100644 --- a/firmware/src/simtrace/iso7816_uart.h +++ b/firmware/src/simtrace/iso7816_uart.h @@ -1,8 +1,15 @@ +#ifndef SIMTRACE_ISO7816_UART_H +#define SIMTRACE_ISO7816_UART_H  struct simtrace_stats *iso_uart_stats_get(void); +void iso_uart_report_errors(void);  void iso_uart_stats_dump(void);  void iso_uart_dump(void);  void iso_uart_rst(unsigned int state);  void iso_uart_rx_mode(void);  void iso_uart_clk_master(unsigned int master);  void iso_uart_init(void); +void iso_uart_flush(void); +void iso_uart_idleflush(void); + +#endif diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 6f82d96..8069349 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -134,10 +134,40 @@ static int simtrace_usb_in(struct req_ctx *rctx)  		req_ctx_set_state(rctx, RCTX_STATE_FREE);  		break;  	} +	return 0; +} + +static volatile unsigned spuirq_pc, spuirq_count = 0; + +static void check_spurious_irq() +{ +	static unsigned last_count = 0; +	if (last_count != spuirq_count) { +		DEBUGPCR("SPURRIOUS IRQ %i [Old PC = %08X]", spuirq_count, spuirq_pc); +		last_count = spuirq_count; +	} +} + +static void custom_spurious_handler(unsigned previous_pc) +{ +	unsigned flags; +	local_irq_save(flags); +	spuirq_pc = previous_pc; +	spuirq_count++; +	local_irq_restore(flags); +} + +static void custom_spurious_entry(void) +{ +	register unsigned *previous_pc asm("r0"); +	asm("ADD R1, SP, #16; LDR R0, [R1]"); +	custom_spurious_handler(previous_pc);  }  void _init_func(void)  { +	AT91C_BASE_AIC->AIC_SPU = (int)custom_spurious_entry; +  	/* low-level hardware initialization */  	pio_irq_init();  	iso_uart_init(); @@ -218,6 +248,8 @@ int _main_dbgu(char key)  void _main_func(void)  { +	static unsigned loopLow = 0, loopHigh = 0; +  	/* first we try to get rid of pending to-be-sent stuff */  	usb_out_process(); @@ -225,4 +257,15 @@ void _main_func(void)  	usb_in_process();  	udp_unthrottle(); + +	if ((loopLow & 0xFFFF) == 0) { +		DEBUGPCR("Heart beat %08X", loopHigh++); +	} +	if ((loopLow & 0x3F) == 0) { +		iso_uart_idleflush(); +	} +	loopLow++; + +	iso_uart_report_errors(); +	check_spurious_irq();  } diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c index faf48f0..90067ac 100644 --- a/firmware/src/simtrace/sim_switch.c +++ b/firmware/src/simtrace/sim_switch.c @@ -59,9 +59,12 @@ static void sw_sim_irq(u_int32_t pio)  static void vcc_phone_irq(u_int32_t pio)  { -	if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE)) +	if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE)) {  		DEBUGPCR("VCC_PHONE off"); -	else +		/* flush any pending req_ctx to make sure the next ATR +		 * will be aligned to position 0 */ +		iso_uart_flush(); +	} else  		DEBUGPCR("VCC_PHONE on");  }  | 
