Contiki 2.6
|
00001 #include <debug-uart.h> 00002 #include <sys-interrupt.h> 00003 /* #include <strformat.h> */ 00004 #include <AT91SAM7S64.h> 00005 #include <string.h> 00006 #include <interrupt-utils.h> 00007 00008 #ifndef DBG_XMIT_BUFFER_LEN 00009 #define DBG_XMIT_BUFFER_LEN 3024 00010 #endif 00011 #ifndef DBG_RECV_BUFFER_LEN 00012 #define DBG_RECV_BUFFER_LEN 256 00013 #endif 00014 00015 static unsigned char dbg_xmit_buffer[DBG_XMIT_BUFFER_LEN]; 00016 static unsigned char dbg_recv_buffer[DBG_RECV_BUFFER_LEN]; 00017 static unsigned int dbg_recv_buffer_len = 0; 00018 00019 void 00020 dbg_setup_uart() 00021 { 00022 /* Setup PIO ports */ 00023 *AT91C_PIOA_OER = AT91C_PA10_DTXD; 00024 *AT91C_PIOA_ODR = AT91C_PA9_DRXD; 00025 *AT91C_PIOA_ASR = AT91C_PA10_DTXD | AT91C_PA9_DRXD; 00026 *AT91C_PIOA_PDR = AT91C_PA10_DTXD | AT91C_PA9_DRXD; 00027 00028 *AT91C_DBGU_MR = AT91C_US_PAR_NONE | AT91C_US_CHMODE_NORMAL; 00029 *AT91C_DBGU_IDR= 0xffffffff; 00030 00031 *AT91C_DBGU_BRGR = MCK / (115200 * 16); 00032 *AT91C_DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN; 00033 00034 *AT91C_DBGU_TPR = (unsigned int)dbg_xmit_buffer; 00035 *AT91C_DBGU_TNPR = (unsigned int)dbg_xmit_buffer; 00036 00037 00038 } 00039 00040 static void (*input_func)(const char *inp, unsigned int len) = NULL; 00041 00042 static int dbg_recv_handler_func() 00043 { 00044 if (!(*AT91C_DBGU_CSR & AT91C_US_RXRDY)) return 0; 00045 unsigned char c = *AT91C_DBGU_RHR; 00046 /* Leave one byte for '\0' */ 00047 if (dbg_recv_buffer_len < (DBG_RECV_BUFFER_LEN -1)) { 00048 dbg_recv_buffer[dbg_recv_buffer_len++] = c; 00049 } 00050 if (c == '\n') { 00051 dbg_recv_buffer[dbg_recv_buffer_len] = '\0'; 00052 if (input_func) input_func((char*)dbg_recv_buffer, dbg_recv_buffer_len); 00053 dbg_recv_buffer_len = 0; 00054 } 00055 return 1; 00056 } 00057 00058 static SystemInterruptHandler dbg_recv_handler = {NULL, dbg_recv_handler_func}; 00059 00060 void 00061 dbg_set_input_handler(void (*handler)(const char *inp, unsigned int len)) 00062 { 00063 input_func = handler; 00064 sys_interrupt_append_handler(&dbg_recv_handler); 00065 sys_interrupt_enable(); 00066 *AT91C_DBGU_IER = AT91C_US_RXRDY; 00067 } 00068 static volatile unsigned char mutex = 0; 00069 00070 unsigned int 00071 dbg_send_bytes(const unsigned char *seq, unsigned int len) 00072 { 00073 unsigned short next_count; 00074 unsigned short current_count; 00075 unsigned short left; 00076 unsigned int save = disableIRQ(); 00077 if (mutex) { 00078 restoreIRQ(save); 00079 return 0; /* Buffer being updated */ 00080 } 00081 mutex = 1; /* Prevent interrupts from messing up the transmission */ 00082 *AT91C_DBGU_PTCR =AT91C_PDC_TXTDIS; /* Stop transmitting */ 00083 while(*AT91C_DBGU_PTSR & AT91C_PDC_TXTEN); /* Wait until stopped */ 00084 next_count = *AT91C_DBGU_TNCR; 00085 current_count = *AT91C_DBGU_TCR; 00086 00087 left = DBG_XMIT_BUFFER_LEN - next_count - current_count; 00088 if (left > 0) { 00089 if (left < len) len = left; 00090 if (next_count > 0) { 00091 /* Buffer is wrapped */ 00092 memcpy(&dbg_xmit_buffer[next_count], seq, len); 00093 *AT91C_DBGU_TNCR = next_count + len; 00094 } else { 00095 unsigned char *to = ((unsigned char*)*AT91C_DBGU_TPR) + current_count; 00096 left = &dbg_xmit_buffer[DBG_XMIT_BUFFER_LEN] - to; 00097 if (len > left) { 00098 unsigned int wrapped = len - left; 00099 memcpy(to, seq, left); 00100 memcpy(dbg_xmit_buffer, &seq[left], wrapped); 00101 *AT91C_DBGU_TCR = current_count + left; 00102 *AT91C_DBGU_TNCR = wrapped; 00103 } else { 00104 memcpy(to, seq, len); 00105 *AT91C_DBGU_TCR = current_count + len; 00106 } 00107 } 00108 } else { 00109 len = 0; 00110 } 00111 00112 *AT91C_DBGU_PTCR =AT91C_PDC_TXTEN; /* Restart transmission */ 00113 mutex = 0; 00114 restoreIRQ(save); 00115 return len; 00116 } 00117 static unsigned char dbg_write_overrun = 0; 00118 00119 void 00120 dbg_putchar(const char ch) 00121 { 00122 if (dbg_write_overrun) { 00123 if (dbg_send_bytes((const unsigned char*)"^",1) != 1) return; 00124 } 00125 dbg_write_overrun = 0; 00126 if (dbg_send_bytes((const unsigned char*)&ch,1) != 1) { 00127 dbg_write_overrun = 1; 00128 } 00129 } 00130 00131 void 00132 dbg_blocking_putchar(const char ch) 00133 { 00134 if (dbg_write_overrun) { 00135 while (dbg_send_bytes((const unsigned char*)"^",1) != 1); 00136 } 00137 dbg_write_overrun = 0; 00138 while (dbg_send_bytes((const unsigned char*)&ch,1) != 1); 00139 } 00140 00141 #if 0 00142 static StrFormatResult 00143 dbg_write_cb(void *user_data, const char *data, unsigned int len) 00144 { 00145 if (dbg_send_bytes((const unsigned char*)data, len) != len) { 00146 dbg_write_overrun = 1; 00147 return STRFORMAT_FAILED; 00148 } 00149 return STRFORMAT_OK; 00150 } 00151 00152 void 00153 dbg_printf(const char *format, ...) 00154 { 00155 static const StrFormatContext ctxt = {dbg_write_cb, NULL}; 00156 va_list ap; 00157 if (dbg_write_overrun) { 00158 if (dbg_send_bytes((const unsigned char*)"^",1) != 1) return; 00159 } 00160 dbg_write_overrun = 0; 00161 va_start(ap, format); 00162 format_str_v(&ctxt, format, ap); 00163 va_end(ap); 00164 } 00165 00166 static StrFormatResult 00167 dbg_write_blocking_cb(void *user_data, const char *data, unsigned int len) 00168 { 00169 unsigned int left = len; 00170 while(left > 0) { 00171 unsigned int sent = dbg_send_bytes((const unsigned char*)data, left); 00172 left -= sent; 00173 data += sent; 00174 } 00175 return STRFORMAT_OK; 00176 } 00177 00178 void 00179 dbg_blocking_printf(const char *format, ...) 00180 { 00181 static const StrFormatContext ctxt = {dbg_write_blocking_cb, NULL}; 00182 va_list ap; 00183 if (dbg_write_overrun) { 00184 while (dbg_send_bytes((const unsigned char*)"^",1) != 1); 00185 } 00186 dbg_write_overrun = 0; 00187 va_start(ap, format); 00188 format_str_v(&ctxt, format, ap); 00189 va_end(ap); 00190 } 00191 #endif 00192 void 00193 dbg_drain() 00194 { 00195 while(!(*AT91C_DBGU_CSR & AT91C_US_TXBUFE)); 00196 }