EVE 1.0
debug-uart.c
1 /* vi: set noai ts=2 sw=2 expandtab: */
2 
3 #include <debug-uart.h>
4 #include <string.h>
5 #include <core/pm.h>
6 #include <lib/assert.h>
7 #include <app_util_platform.h>
8 #include <dev/uart.h>
9 
10 #ifndef DBG_XMIT_BUFFER_LEN
11 #define DBG_XMIT_BUFFER_LEN 1024
12 #endif
13 
14 struct dbg_uart_state_t {
15  const struct uart_t *uart;
16  uint8_t *volatile xmit_buffer_head;
17  uint8_t *volatile xmit_buffer_tail;
18  uint8_t dma_size;
19  uint8_t write_overrun;
20  uint8_t xmit_buffer[DBG_XMIT_BUFFER_LEN];
21 };
22 
23 struct dbg_uart_state_t dbg_uart_state;
24 #define XMIT_BUFFER_END(s) (&(s)->xmit_buffer[DBG_XMIT_BUFFER_LEN])
25 
26 static void dbg_uart_event_hander(const struct uart_t *uart, void *data);
27 
28 void dbg_setup()
29 {
30  struct dbg_uart_state_t *s = &dbg_uart_state;
31  s->xmit_buffer_head = s->xmit_buffer;
32  s->xmit_buffer_tail = s->xmit_buffer;
33 }
34 
35 static uint8_t
36 update_dma(void)
37 {
38  struct dbg_uart_state_t *s = &dbg_uart_state;
39  unsigned bytes;
40 
41  if (s->xmit_buffer_tail == s->xmit_buffer_head)
42  return 0;
43 
44  if (s->xmit_buffer_head < s->xmit_buffer_tail)
45  bytes = s->xmit_buffer_tail - s->xmit_buffer_head;
46  else
47  bytes = XMIT_BUFFER_END(s) - s->xmit_buffer_head;
48 
49  /* Activate DMA channel for TX */
50  if (bytes) {
51  if (bytes > 255)
52  bytes = 255;
53  UartStartBasicTx(s->uart, s->xmit_buffer_head, bytes, dbg_uart_event_hander, NULL);
54  }
55 
56  return bytes;
57 }
58 
59 static void dbg_uart_event_hander(const struct uart_t *uart, void *data)
60 {
61  struct dbg_uart_state_t *s = &dbg_uart_state;
62  CRITICAL_REGION_ENTER();
63  s->xmit_buffer_head += s->dma_size;
64  if (s->xmit_buffer_head == XMIT_BUFFER_END(s))
65  s->xmit_buffer_head = s->xmit_buffer;
66  dbg_uart_state.dma_size = update_dma();
67  CRITICAL_REGION_EXIT();
68 }
69 
70 unsigned int
71 dbg_send_bytes(const uint8_t *seq, unsigned int len)
72 {
73  /* Since each of the pointers should be read atomically
74  there's no need to disable interrupts */
75  struct dbg_uart_state_t *s = &dbg_uart_state;
76  uint8_t *head = s->xmit_buffer_head;
77  uint8_t *tail = s->xmit_buffer_tail;
78 
79  if (tail >= head) {
80  /* Free space wraps */
81  unsigned int xfer_len = XMIT_BUFFER_END(s) - tail;
82  unsigned int free = DBG_XMIT_BUFFER_LEN - (tail - head) - 1;
83 
84  if (len > free)
85  len = free;
86  if (xfer_len < len) {
87  memcpy(tail, seq, xfer_len);
88  seq += xfer_len;
89  xfer_len = len - xfer_len;
90  memcpy(s->xmit_buffer, seq, xfer_len);
91  tail = s->xmit_buffer + xfer_len;
92  } else {
93  memcpy(tail, seq, len);
94  tail += len;
95  if (tail == XMIT_BUFFER_END(s))
96  tail = s->xmit_buffer;
97  }
98  } else {
99  /* Free space continuous */
100  unsigned int free = (head - tail) - 1;
101  if (len > free)
102  len = free;
103  memcpy(tail, seq, len);
104  tail += len;
105  }
106 
107  if (s->uart) {
108  /* Start DMA */
109  CRITICAL_REGION_ENTER();
110  s->xmit_buffer_tail = tail;
111  if (!dbg_uart_state.dma_size)
112  dbg_uart_state.dma_size = update_dma();
113  CRITICAL_REGION_EXIT();
114  }
115 
116  return len;
117 }
118 
119 void
120 dbg_putchar(const char ch)
121 {
122  struct dbg_uart_state_t *s = &dbg_uart_state;
123  if (s->write_overrun) {
124  if (dbg_send_bytes((const uint8_t*)"^", 1) != 1)
125  return;
126  }
127  s->write_overrun = 0;
128  if (dbg_send_bytes((const uint8_t*)&ch, 1) != 1) {
129  s->write_overrun = 1;
130  }
131 }
132 
133 void
134 dbg_blocking_putchar(const char ch)
135 {
136  struct dbg_uart_state_t *s = &dbg_uart_state;
137  if (s->write_overrun) {
138  while (dbg_send_bytes((const uint8_t*)"^", 1) != 1)
139  pm_relax();
140  }
141  s->write_overrun = 0;
142  while (dbg_send_bytes((const uint8_t*)&ch, 1) != 1)
143  pm_relax();
144 }
145 
146 void
147 dbg_drain()
148 {
149  struct dbg_uart_state_t *s = &dbg_uart_state;
150  while(s->xmit_buffer_tail != s->xmit_buffer_head)
151  pm_relax();
152 }
153 
154 void
155 dbg_panic(void)
156 {
157 }
158 
159 void
160 dbg_uart_set_uart(const struct uart_t *uart)
161 {
162  struct dbg_uart_state_t *s = &dbg_uart_state;
163  s->uart = uart;
164 }
165 
Abstract UART driver header.
Definition: uart.h:222
Header file for the EVE power management framework.
static void UartStartBasicTx(const struct uart_t *Uart, uint8_t *DataSrc, uint16_t DataSize, uart_tx_callback_t Callback, void *CallbackData)
Name: UartStartBasicTx Transmit data using DMA transfer in basic mode. Using primary DMA descriptor o...
Definition: uart.h:292
uint32_t seq
Definition: usbnet.h:140
void pm_relax(void)
uint8_t data[USBNET_RX_BUF_SIZE]
Definition: usbnet.h:140