diff options
Diffstat (limited to 'lib/chibios-contrib/os/hal/src/usbh/hal_usbh_debug.c')
-rw-r--r-- | lib/chibios-contrib/os/hal/src/usbh/hal_usbh_debug.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/hal/src/usbh/hal_usbh_debug.c b/lib/chibios-contrib/os/hal/src/usbh/hal_usbh_debug.c new file mode 100644 index 000000000..225489df8 --- /dev/null +++ b/lib/chibios-contrib/os/hal/src/usbh/hal_usbh_debug.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio | ||
3 | Copyright (C) 2015..2019 Diego Ismirlian, (dismirlian(at)google's mail) | ||
4 | |||
5 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | you may not use this file except in compliance with the License. | ||
7 | You may obtain a copy of the License at | ||
8 | |||
9 | http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | |||
11 | Unless required by applicable law or agreed to in writing, software | ||
12 | distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | See the License for the specific language governing permissions and | ||
15 | limitations under the License. | ||
16 | */ | ||
17 | |||
18 | #include "hal.h" | ||
19 | |||
20 | #if HAL_USE_USBH && USBH_DEBUG_ENABLE | ||
21 | |||
22 | #include "ch.h" | ||
23 | #include "usbh/debug.h" | ||
24 | #include "chprintf.h" | ||
25 | #include <stdarg.h> | ||
26 | |||
27 | #define TEMP_BUFF_LEN 255 | ||
28 | |||
29 | /* ************************ */ | ||
30 | /* Circular queue structure */ | ||
31 | /* ************************ */ | ||
32 | static int dq_append_string(usbh_dq_t *q, const uint8_t *s, int len) { | ||
33 | if (len <= 0) return 0; | ||
34 | if (len > TEMP_BUFF_LEN) len = TEMP_BUFF_LEN; | ||
35 | if (q->rem < len + 1) return -1; | ||
36 | q->rem -= len + 1; | ||
37 | |||
38 | uint8_t *d = q->next; | ||
39 | *d++ = len; | ||
40 | if (d == q->end) d = q->start; | ||
41 | while (len--) { | ||
42 | *d++ = *s++; | ||
43 | if (d == q->end) d = q->start; | ||
44 | } | ||
45 | q->next = d; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void dq_remove_oldest_string(usbh_dq_t *q) { | ||
50 | int len = *q->first; | ||
51 | if (len) { | ||
52 | ++len; | ||
53 | q->rem += len; | ||
54 | q->first += len; | ||
55 | if (q->first >= q->end) { | ||
56 | q->first -= q->sz; | ||
57 | } | ||
58 | if (q->rem == q->sz) { | ||
59 | *q->first = 0; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static int dq_read_oldest_string(usbh_dq_t *q, uint8_t *d) { | ||
65 | uint8_t *s = q->first; | ||
66 | int len; | ||
67 | int sz; | ||
68 | len = sz = *s++; | ||
69 | while (len--) { | ||
70 | *d++ = *s++; | ||
71 | if (d == q->end) d = q->start; | ||
72 | } | ||
73 | *d = 0; | ||
74 | return sz; | ||
75 | } | ||
76 | |||
77 | static void dq_init(usbh_dq_t *q, uint8_t *buff, int len) { | ||
78 | q->start = q->first = q->next = buff; | ||
79 | q->end = q->start + len; | ||
80 | q->sz = q->rem = len; | ||
81 | *buff = 0; | ||
82 | } | ||
83 | |||
84 | |||
85 | static uint8_t buff[TEMP_BUFF_LEN + 1]; | ||
86 | |||
87 | static inline syssts_t _dbg_prologue(struct usbh_debug_helper *debug, | ||
88 | uint32_t hfnum, uint16_t hfir, const char *s, int *len) { | ||
89 | syssts_t sts = chSysGetStatusAndLockX(); | ||
90 | |||
91 | debug->last = osalOsGetSystemTimeX(); | ||
92 | if (debug->ena) { | ||
93 | debug->first = debug->last; | ||
94 | } | ||
95 | |||
96 | if (((hfnum & 0x3fff) == 0x3fff) && (hfir == (hfnum >> 16))) { | ||
97 | *len = chsnprintf((char *)buff, sizeof(buff), "+%08d ", debug->last - debug->first); | ||
98 | debug->ena = FALSE; | ||
99 | } else { | ||
100 | uint32_t f = hfnum & 0xffff; | ||
101 | uint32_t p = 1000 - ((hfnum >> 16) / (hfir / 1000)); | ||
102 | *len = chsnprintf((char *)buff, sizeof(buff), "%05d.%03d %s", f, p, s); | ||
103 | debug->ena = TRUE; | ||
104 | } | ||
105 | |||
106 | return sts; | ||
107 | } | ||
108 | |||
109 | static inline void dbg_epilogue(struct usbh_debug_helper *debug, | ||
110 | syssts_t sts, int len) { | ||
111 | |||
112 | while (dq_append_string(&debug->dq, buff, len) < 0) { | ||
113 | dq_remove_oldest_string(&debug->dq); | ||
114 | } | ||
115 | |||
116 | if (debug->on) { | ||
117 | chThdResumeI(&debug->tr, MSG_OK); | ||
118 | } | ||
119 | |||
120 | chSysRestoreStatusX(sts); | ||
121 | } | ||
122 | |||
123 | #if USBH_DEBUG_MULTI_HOST | ||
124 | void usbDbgPrintf(USBHDriver *host, const char *fmt, ...) { | ||
125 | if (!host) return; | ||
126 | struct usbh_debug_helper *const debug = &host->debug; | ||
127 | uint32_t hfnum = host->otg->HFNUM; | ||
128 | uint16_t hfir = host->otg->HFIR; | ||
129 | #else | ||
130 | void usbDbgPrintf(const char *fmt, ...) { | ||
131 | struct usbh_debug_helper *const debug = &usbh_debug; | ||
132 | uint32_t hfnum = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFNUM; | ||
133 | uint16_t hfir = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFIR; | ||
134 | #endif | ||
135 | int len; | ||
136 | |||
137 | syssts_t sts = _dbg_prologue(debug, hfnum, hfir, "", &len); | ||
138 | |||
139 | va_list ap; | ||
140 | va_start(ap, fmt); | ||
141 | len += chvsnprintf((char *)buff + len, sizeof(buff) - len, fmt, ap); | ||
142 | va_end(ap); | ||
143 | |||
144 | dbg_epilogue(debug, sts, len); | ||
145 | } | ||
146 | |||
147 | #if USBH_DEBUG_MULTI_HOST | ||
148 | void usbDbgPuts(USBHDriver *host, const char *s) { | ||
149 | if (!host) return; | ||
150 | struct usbh_debug_helper *const debug = &host->debug; | ||
151 | uint32_t hfnum = host->otg->HFNUM; | ||
152 | uint16_t hfir = host->otg->HFIR; | ||
153 | #else | ||
154 | void usbDbgPuts(const char *s) { | ||
155 | struct usbh_debug_helper *const debug = &usbh_debug; | ||
156 | uint32_t hfnum = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFNUM; | ||
157 | uint16_t hfir = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFIR; | ||
158 | #endif | ||
159 | int len; | ||
160 | syssts_t sts = _dbg_prologue(debug, hfnum, hfir, s, &len); | ||
161 | dbg_epilogue(debug, sts, len); | ||
162 | } | ||
163 | |||
164 | #if USBH_DEBUG_MULTI_HOST | ||
165 | void usbDbgEnable(USBHDriver *host, bool enable) { | ||
166 | struct usbh_debug_helper *const debug = &host->debug; | ||
167 | #else | ||
168 | void usbDbgEnable(bool enable) { | ||
169 | struct usbh_debug_helper *const debug = &usbh_debug; | ||
170 | #endif | ||
171 | debug->on = enable; | ||
172 | } | ||
173 | |||
174 | static void usb_debug_thread(void *arg) { | ||
175 | #if USBH_DEBUG_MULTI_HOST | ||
176 | USBHDriver *const host = (USBHDriver *)arg; | ||
177 | struct usbh_debug_helper *const debug = &host->debug; | ||
178 | #else | ||
179 | (void)arg; | ||
180 | struct usbh_debug_helper *const debug = &usbh_debug; | ||
181 | #endif | ||
182 | |||
183 | uint8_t rdbuff[TEMP_BUFF_LEN + 1]; | ||
184 | |||
185 | chRegSetThreadName("USBH_DBG"); | ||
186 | while (true) { | ||
187 | chSysLock(); | ||
188 | int len = dq_read_oldest_string(&debug->dq, rdbuff); | ||
189 | if (!len) { | ||
190 | chThdSuspendS(&debug->tr); | ||
191 | chSysUnlock(); | ||
192 | } else { | ||
193 | dq_remove_oldest_string(&debug->dq); | ||
194 | chSysUnlock(); | ||
195 | #if USBH_DEBUG_MULTI_HOST | ||
196 | USBH_DEBUG_OUTPUT_CALLBACK(host, rdbuff, len); | ||
197 | #else | ||
198 | USBH_DEBUG_OUTPUT_CALLBACK(rdbuff, len); | ||
199 | #endif | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
204 | #if USBH_DEBUG_MULTI_HOST | ||
205 | void usbDbgInit(USBHDriver *host) { | ||
206 | struct usbh_debug_helper *const debug = &host->debug; | ||
207 | void *param = host; | ||
208 | #else | ||
209 | void usbDbgInit(void) { | ||
210 | struct usbh_debug_helper *const debug = &usbh_debug; | ||
211 | void *param = NULL; | ||
212 | #endif | ||
213 | dq_init(&debug->dq, debug->buff, sizeof(debug->buff)); | ||
214 | debug->on = true; | ||
215 | chThdCreateStatic(debug->thd_wa, sizeof(debug->thd_wa), | ||
216 | NORMALPRIO, usb_debug_thread, param); | ||
217 | } | ||
218 | |||
219 | #endif | ||