Contiki 2.6

debug-uart.c

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 }