Contiki 2.6

debug-uart.c

00001 #include <debug-uart.h>
00002 #include <string.h>
00003 #include <stm32f10x_map.h>
00004 #include <stm32f10x_dma.h>
00005 #include <gpio.h>
00006 #include <nvic.h>
00007 
00008 #ifndef DBG_UART
00009 #define DBG_UART USART1
00010 #endif
00011 
00012 #ifndef DBG_DMA_NO
00013 #define DBG_DMA_NO 1
00014 #endif
00015 
00016 #ifndef DBG_DMA_CHANNEL_NO
00017 #define DBG_DMA_CHANNEL_NO 4
00018 #endif
00019 
00020 
00021 #define _DBG_DMA_NAME(x) DMA##x
00022 #define DBG_DMA_NAME(x) _DBG_DMA_NAME(x)
00023 #define DBG_DMA DBG_DMA_NAME(DBG_DMA_NO)
00024 
00025 #define _DMA_CHANNEL_NAME(x,c) DMA ## x ## _Channel ## c
00026 #define DMA_CHANNEL_NAME(x,c) _DMA_CHANNEL_NAME(x,c)
00027 #define DBG_DMA_CHANNEL  DMA_CHANNEL_NAME(DBG_DMA_NO, DBG_DMA_CHANNEL_NO)
00028 
00029 #define _DBG_DMA_CHANNEL_IFCR_CGIF(c) DMA_IFCR_CGIF ## c
00030 #define _XDBG_DMA_CHANNEL_IFCR_CGIF(c) _DBG_DMA_CHANNEL_IFCR_CGIF(c)
00031 #define DBG_DMA_CHANNEL_IFCR_CGIF \
00032 _XDBG_DMA_CHANNEL_IFCR_CGIF(DBG_DMA_CHANNEL_NO)
00033 
00034 
00035 #ifndef DBG_XMIT_BUFFER_LEN
00036 #define DBG_XMIT_BUFFER_LEN 1024
00037 #endif
00038 
00039 
00040 static unsigned char xmit_buffer[DBG_XMIT_BUFFER_LEN];
00041 #define XMIT_BUFFER_END &xmit_buffer[DBG_XMIT_BUFFER_LEN]
00042 void
00043 dbg_setup_uart_default()
00044 {
00045   RCC->APB2ENR |=  (RCC_APB2ENR_AFIOEN
00046                     | RCC_APB2ENR_IOPAEN| RCC_APB2ENR_IOPBEN
00047                     | RCC_APB2ENR_USART1EN );
00048   RCC->AHBENR |= RCC_AHBENR_DMA1EN;
00049   AFIO_REMAP( AFIO_MAPR_USART1_REMAP, AFIO_MAPR_USART1_REMAP);
00050   GPIO_CONF_OUTPUT_PORT(B,6,ALT_PUSH_PULL,50);
00051   GPIO_CONF_INPUT_PORT(B,7,FLOATING);
00052   
00053   USART1->CR1 = USART_CR1_UE;
00054   
00055   USART1->CR2 = 0;
00056   USART1->CR3 = USART_CR3_DMAT;
00057   USART1->CR1 |= USART_CR1_TE;
00058   USART1->BRR= 0x1a1;
00059 }
00060 
00061 /* Valid data in head to tail-1 */
00062 /* Read position */
00063 static unsigned char * volatile xmit_buffer_head = xmit_buffer;
00064 
00065 /* Write position */
00066 static unsigned char * volatile xmit_buffer_tail = xmit_buffer;
00067 
00068 /* xmit_buffer_head == xmit_buffer_tail means empty so we can only store
00069    DBG_XMIT_BUFFER_LEN-1 characters */
00070 
00071 volatile unsigned char dma_running = 0;
00072 static unsigned char * volatile dma_end;
00073 void
00074 DMA1_Channel4_handler() __attribute__((interrupt));
00075 
00076 
00077 static void
00078 update_dma(void)
00079 {
00080   if (xmit_buffer_tail == xmit_buffer_head) return;
00081   DBG_DMA_CHANNEL->CCR = (DMA_Priority_Low |
00082                           DMA_PeripheralDataSize_Byte |
00083                           DMA_MemoryDataSize_Byte |
00084                           DMA_PeripheralInc_Disable |
00085                           DMA_MemoryInc_Enable |
00086                           DMA_Mode_Normal |
00087                           DMA_DIR_PeripheralDST |
00088                           DMA_CCR4_TCIE
00089                           );
00090   DBG_DMA_CHANNEL->CPAR = (u32)&DBG_UART->DR;
00091   DBG_DMA_CHANNEL->CMAR = (u32)xmit_buffer_head;
00092   if (xmit_buffer_head < xmit_buffer_tail) {
00093     DBG_DMA_CHANNEL->CNDTR = xmit_buffer_tail - xmit_buffer_head;
00094     dma_end = xmit_buffer_tail;    
00095   } else {
00096     DBG_DMA_CHANNEL->CNDTR =  XMIT_BUFFER_END - xmit_buffer_head;
00097     dma_end = xmit_buffer;
00098   }
00099   NVIC_ENABLE_INT(DMA1_Channel4_IRQChannel);
00100   NVIC_SET_PRIORITY(DMA1_Channel4_IRQChannel, 2);
00101   DBG_DMA_CHANNEL->CCR |=DMA_CCR4_EN;
00102 }
00103 
00104 
00105 
00106 void
00107 DMA1_Channel4_handler()
00108 {
00109   DBG_DMA->IFCR = DBG_DMA_CHANNEL_IFCR_CGIF;
00110   xmit_buffer_head = dma_end;
00111   if (xmit_buffer_tail == xmit_buffer_head) {
00112     dma_running = 0;
00113     return;
00114   }
00115   update_dma();
00116 }
00117 
00118 unsigned int
00119 dbg_send_bytes(const unsigned char *seq, unsigned int len)
00120 {
00121   /* Since each of the pointers should be read atomically
00122      there's no need to disable interrupts */
00123   unsigned char *head = xmit_buffer_head;
00124   unsigned char *tail = xmit_buffer_tail;
00125   if (tail >= head) {
00126     /* Free space wraps */
00127     unsigned int xfer_len = XMIT_BUFFER_END - tail;
00128     unsigned int free = DBG_XMIT_BUFFER_LEN - (tail - head) - 1;
00129     if (len > free) len = free;
00130     if (xfer_len < len) {
00131       memcpy(tail, seq, xfer_len);
00132       seq += xfer_len;
00133       xfer_len = len - xfer_len;
00134       memcpy(xmit_buffer, seq, xfer_len);
00135       tail = xmit_buffer + xfer_len;
00136     } else {
00137       memcpy(tail, seq, len);
00138       tail += len;
00139       if (tail == XMIT_BUFFER_END) tail = xmit_buffer;
00140     }
00141   } else {
00142     /* Free space continuous */
00143     unsigned int free = (head - tail) - 1;
00144     if (len > free) len = free;
00145     memcpy(tail, seq, len);
00146     tail += len;
00147   }
00148   xmit_buffer_tail = tail;
00149   if (!dma_running) {
00150     dma_running = 1;
00151     update_dma();
00152   }
00153   return len;
00154 }
00155 
00156 static unsigned char dbg_write_overrun = 0;
00157 
00158 void
00159 dbg_putchar(const char ch)
00160 {
00161   if (dbg_write_overrun) {
00162     if (dbg_send_bytes((const unsigned char*)"^",1) != 1) return;
00163   }
00164   dbg_write_overrun = 0;
00165   if (dbg_send_bytes((const unsigned char*)&ch,1) != 1) {
00166     dbg_write_overrun = 1;
00167   }
00168 }
00169 
00170 void
00171 dbg_blocking_putchar(const char ch)
00172 {
00173   if (dbg_write_overrun) {
00174     while (dbg_send_bytes((const unsigned char*)"^",1) != 1);
00175   }
00176   dbg_write_overrun = 0;
00177   while (dbg_send_bytes((const unsigned char*)&ch,1) != 1);
00178 }
00179 
00180 void
00181 dbg_drain()
00182 {
00183   while(xmit_buffer_tail != xmit_buffer_head);
00184 }