1 #include <stdio.h>
2 #include <string.h>
3 #include "SEGGER_RTT.h"
4 #include "dbg_printf.h"
5
6 #define LOG_UART_GRP UART0
7 #define LOG_UART_PORT GPIO0
8 #define LOG_UART_TX_PIN GPIO_PIN_10
9 #define LOG_UART_RX_PIN GPIO_PIN_11
10 #define LOG_UART_TX_PINMUX GPIO_MUX_2
11 #define LOG_UART_RX_PINMUX GPIO_MUX_2
12
13
14 typedef struct {
15 char send_buf[DBG_RING_BUF_SIZE];
16 uint32_t head;
17 uint32_t tail;
18 uint32_t valid;
19 } ring_buf_t;
20
21 static ring_buf_t dbg_ring_buf;
22 static dbg_printf_mode_t dbg_printf_mode = DBG_PRINTF_NONE;
23 volatile int32_t ITM_RxBuffer = 0x5AA55AA5U;
24
SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex,const char * sName,uint8_t * pBuffer,unsigned BufferSize,unsigned Flags)25 __WEAK int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, uint8_t* pBuffer, unsigned BufferSize,
26 unsigned Flags)
27 {
28 return 0;
29 }
30
SEGGER_RTT_Write(unsigned BufferIndex,const uint8_t * pBuffer,unsigned NumBytes)31 __WEAK unsigned SEGGER_RTT_Write(unsigned BufferIndex, const uint8_t* pBuffer, unsigned NumBytes)
32 {
33 return 0;
34 }
35
SEGGER_RTT_WaitKey(void)36 __WEAK int SEGGER_RTT_WaitKey(void)
37 {
38 return 0;
39 }
40
push_char(ring_buf_t * p_ring_buf,uint8_t ch)41 static uint8_t push_char(ring_buf_t *p_ring_buf, uint8_t ch)
42 {
43 uint8_t ret = 0;
44
45 GLOBAL_EXCEPTION_DISABLE();
46 if (p_ring_buf->valid < DBG_RING_BUF_SIZE) {
47 p_ring_buf->send_buf[p_ring_buf->tail++] = ch;
48 if (p_ring_buf->tail == DBG_RING_BUF_SIZE)
49 p_ring_buf->tail = 0;
50 p_ring_buf->valid++;
51 ret = 1;
52 } else {
53 ret = 0;
54 }
55 GLOBAL_EXCEPTION_ENABLE();
56
57 return ret;
58 }
59
pop_char(ring_buf_t * p_ring_buf)60 static uint8_t pop_char(ring_buf_t *p_ring_buf)
61 {
62 uint8_t ret = 0;
63
64 GLOBAL_EXCEPTION_DISABLE();
65 if (p_ring_buf->valid) {
66 p_ring_buf->valid--;
67 ret = p_ring_buf->send_buf[p_ring_buf->head++];
68 if (p_ring_buf->head == DBG_RING_BUF_SIZE)
69 p_ring_buf->head = 0;
70 } else {
71 ret = 0;
72 }
73 GLOBAL_EXCEPTION_ENABLE();
74
75 return ret;
76 }
77
dbg_uart_init(uart_regs_t * UARTx,dbg_printf_mode_t mode)78 static void dbg_uart_init(uart_regs_t *UARTx, dbg_printf_mode_t mode)
79 {
80 uint32_t baud;
81 uint32_t uart_pclk = SystemCoreClock;
82 gpio_init_t gpio_config = GPIO_DEFAULT_CONFIG;
83
84 /* Initialize ring buffer */
85 memset_s(&dbg_ring_buf, sizeof (dbg_ring_buf), 0, sizeof(dbg_ring_buf));
86
87 /* Enable serial module clock */
88 ll_cgc_disable_force_off_serial_hclk();
89 ll_cgc_disable_wfi_off_serial_hclk();
90
91 if (UARTx == UART0) {
92 /* Enable UART0 clock */
93 ll_cgc_disable_force_off_uart0_hclk();
94 } else if (UARTx == UART1) {
95 /* Enable UART1 clock */
96 ll_cgc_disable_force_off_uart1_hclk();
97 }
98
99 gpio_config.mode = GPIO_MODE_MUX;
100 gpio_config.pin = LOG_UART_TX_PIN;
101 gpio_config.mux = LOG_UART_TX_PINMUX;
102 hal_gpio_init(LOG_UART_PORT, &gpio_config);
103
104 gpio_config.pin = LOG_UART_RX_PIN;
105 gpio_config.mux = LOG_UART_RX_PINMUX;
106 hal_gpio_init(LOG_UART_PORT, &gpio_config);
107
108 /* Set baudrate */
109 baud = DBG_UART_BAUDRATE;
110 ll_uart_set_baud_rate(UARTx, uart_pclk, baud);
111
112 /**
113 Set data bit to 8.
114 Set stop bit to 1.
115 Set parity to none.
116 Set fifo to enable.
117 */
118 ll_uart_config_character(UARTx, LL_UART_DATABITS_8B, LL_UART_PARITY_NONE, LL_UART_STOPBITS_1);
119 /* Set fifo enable */
120 ll_uart_enable_fifo(UARTx);
121
122 if ((DBG_PRINTF_INT_UART0 == mode) || (DBG_PRINTF_INT_UART1 == mode)) {
123 /* Set tx fifo threshold */
124 ll_uart_set_tx_fifo_threshold(UARTx, LL_UART_TX_FIFO_TH_EMPTY);
125
126 /* Enable NVIC uart interrupt */
127 IRQn_Type uart_irq_num = ((UARTx == UART0) ? UART0_IRQn : UART1_IRQn);
128 NVIC_SetPriority(uart_irq_num, 0xF0);
129 NVIC_ClearPendingIRQ(uart_irq_num);
130 NVIC_EnableIRQ(uart_irq_num);
131 }
132 return;
133 }
134
dbg_uart_send_char(uart_regs_t * UARTx,uint8_t ch)135 static void dbg_uart_send_char(uart_regs_t *UARTx, uint8_t ch)
136 {
137 if ((DBG_PRINTF_UART0 == dbg_printf_mode) || (DBG_PRINTF_UART1 == dbg_printf_mode)) {
138 /* Wait untill TX FIFO is not full */
139 while (!ll_uart_is_active_flag_tfnf(UARTx));
140 ll_uart_transmit_data8(UARTx, ch);
141 } else if ((DBG_PRINTF_INT_UART0 == dbg_printf_mode) || (DBG_PRINTF_INT_UART1 == dbg_printf_mode)) {
142 /* Fill ring buffer to use interrupt send */
143 push_char(&dbg_ring_buf, ch);
144 /* Enable TXE interrupt */
145 ll_uart_enable_it(UARTx, LL_UART_IER_THRE);
146 }
147 return;
148 }
149
dbg_uart_get_char(uart_regs_t * UARTx)150 static uint8_t dbg_uart_get_char(uart_regs_t *UARTx)
151 {
152 uint8_t ch;
153
154 while (!ll_uart_is_active_flag_rfne(UARTx));
155 /* UART receive byte */
156 ch = ll_uart_receive_data8(UARTx);
157 return ch;
158 }
159
dbg_send_char(int ch)160 static int dbg_send_char(int ch)
161 {
162 switch (dbg_printf_mode) {
163 case DBG_PRINTF_UART0:
164 case DBG_PRINTF_INT_UART0:
165 dbg_uart_send_char(UART0, (uint8_t)ch);
166 break;
167 case DBG_PRINTF_UART1:
168 case DBG_PRINTF_INT_UART1:
169 dbg_uart_send_char(UART1, (uint8_t)ch);
170 break;
171 case DBG_PRINTF_ITM:
172 ITM_SendChar(ch);
173 break;
174 case DBG_PRINTF_RTT:
175 SEGGER_RTT_Write(0, &ch, 1);
176 break;
177 default:
178 break;
179 }
180 return ch;
181 }
182
dbg_get_char(void)183 static int dbg_get_char(void)
184 {
185 int32_t ch = -1;
186
187 switch (dbg_printf_mode) {
188 case DBG_PRINTF_UART0:
189 case DBG_PRINTF_INT_UART0:
190 ch = dbg_uart_get_char(UART0);
191 break;
192 case DBG_PRINTF_UART1:
193 case DBG_PRINTF_INT_UART1:
194 ch = dbg_uart_get_char(UART1);
195 break;
196 case DBG_PRINTF_ITM:
197 while (ITM_CheckChar() == 0) {
198 }
199 ch = ITM_ReceiveChar();
200 break;
201 case DBG_PRINTF_RTT:
202 ch = SEGGER_RTT_WaitKey();
203 break;
204 default:
205 break;
206 }
207 return ch;
208 }
209
dbg_printf_set_mode(dbg_printf_mode_t mode)210 void dbg_printf_set_mode(dbg_printf_mode_t mode)
211 {
212 switch (mode) {
213 case DBG_PRINTF_UART0:
214 case DBG_PRINTF_INT_UART0:
215 dbg_uart_init(UART0, mode);
216 break;
217 case DBG_PRINTF_UART1:
218 case DBG_PRINTF_INT_UART1:
219 dbg_uart_init(UART1, mode);
220 break;
221 case DBG_PRINTF_ITM:
222 /* Set MUX2 of GPIO_PIN_2 to enable SWV. */
223 ll_gpio_set_mux_pin_0_7(GPIO0, LL_GPIO_PIN_2, LL_GPIO_MUX_2);
224 break;
225 case DBG_PRINTF_RTT:
226 SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
227 break;
228 default:
229 break;
230 }
231
232 dbg_printf_mode = mode;
233 return;
234 }
235
dbg_printf_uart_callback(uart_regs_t * UARTx)236 uint8_t dbg_printf_uart_callback(uart_regs_t *UARTx)
237 {
238 uint32_t isrflag = ll_uart_get_it_flag(UARTx);
239 if (LL_UART_IIR_THRE == isrflag) {
240 if (dbg_ring_buf.valid == 0) {
241 /* Disable TXE interrupt */
242 ll_uart_disable_it(UARTx, LL_UART_IER_THRE);
243 } else {
244 uint8_t curxfercnt = UART_TXFIFO_SIZE - ll_uart_get_tx_fifo_level(UARTx);
245 while (curxfercnt && dbg_ring_buf.valid) {
246 ll_uart_transmit_data8(UARTx, pop_char(&dbg_ring_buf));
247 curxfercnt--;
248 }
249 }
250 return 1;
251 } else {
252 return 0;
253 }
254 }
255
dbg_printf_uart_flush(void)256 uint32_t dbg_printf_uart_flush(void)
257 {
258 uint32_t count = 0;
259 if ((DBG_PRINTF_INT_UART0 == dbg_printf_mode) || (DBG_PRINTF_INT_UART1 == dbg_printf_mode)) {
260 uart_regs_t *UARTx = ((DBG_PRINTF_INT_UART0 == dbg_printf_mode)? UART0: UART1);
261 IRQn_Type uart_irq_num = ((DBG_PRINTF_INT_UART0 == dbg_printf_mode) ? UART0_IRQn : UART1_IRQn);
262
263 NVIC_DisableIRQ(uart_irq_num);
264 NVIC_ClearPendingIRQ(uart_irq_num);
265 count = dbg_ring_buf.valid;
266 while (dbg_ring_buf.valid) {
267 /* Wait untill TX FIFO is not full */
268 while (!ll_uart_is_active_flag_tfnf(UARTx));
269 ll_uart_transmit_data8(UARTx, pop_char(&dbg_ring_buf));
270 }
271 /* Wait untill TX FIFO is empty. */
272 while (!ll_uart_is_active_flag_tfe(UARTx));
273 NVIC_EnableIRQ(uart_irq_num);
274 } else if ((DBG_PRINTF_UART0 == dbg_printf_mode) || (DBG_PRINTF_UART1 == dbg_printf_mode)) {
275 uart_regs_t *UARTx = ((DBG_PRINTF_UART0 == dbg_printf_mode)? UART0: UART1);
276 /* Wait untill TX FIFO is empty. */
277 while (!ll_uart_is_active_flag_tfe(UARTx));
278 }
279
280 return count;
281 }
282
283 #if defined(__CC_ARM)
284
285 struct __FILE {
286 int handle;
287 };
288
fputc(int ch,FILE * file)289 int fputc(int ch, FILE * file)
290 {
291 return (dbg_send_char(ch));
292 }
293
fgetc(FILE * file)294 int fgetc(FILE * file)
295 {
296 return dbg_get_char();
297 }
298
_sys_exit(int return_code)299 void _sys_exit(int return_code)
300 {
301 while (1) {
302 ;
303 }
304 }
305
306 #elif defined(__GNUC__)
307
_write(int file,const char * buf,int len)308 int _write(int file, const char *buf, int len)
309 {
310 int tx_len = 0;
311 char *temp_buf = buf;
312
313 while (tx_len < len) {
314 dbg_send_char(*temp_buf);
315 temp_buf++;
316 tx_len++;
317 }
318 return tx_len;
319 }
320
_read(int file,char * buf,int len)321 int _read(int file, char *buf, int len)
322 {
323 int rx_len = 0;
324 char *temp_buf = buf;
325
326 while (rx_len < len) {
327 *temp_buf = dbg_get_char();
328 temp_buf++;
329 rx_len++;
330 }
331 return rx_len;
332 }
333
334
335 #elif defined(__ICCARM__)
336
_write(int handle,const unsigned char * buf,size_t size)337 size_t _write(int handle, const unsigned char * buf, size_t size)
338 {
339 size_t len = 0;
340
341 while (len < size) {
342 dbg_send_char(*buf);
343 buf++;
344 len++;
345 }
346 return len;
347 }
348
_read(int handle,unsigned char * buf,size_t size)349 size_t _read(int handle, unsigned char * buf, size_t size)
350 {
351 int rx_len = 0;
352
353 while (rx_len < size) {
354 *buf = dbg_get_char();
355 buf++;
356 rx_len++;
357 }
358 return rx_len;
359 }
360
361 #endif /* defined(__CC_ARM) */
362