NANO103 BSP V3.02.000
The Board Support Package for Nano103 Series
retarget.c
Go to the documentation of this file.
1/**************************************************************************/
11#include <stdio.h>
12#include "Nano103.h"
13
14#if defined (__ICCARM__)
15 #pragma diag_suppress=Pm150
16#endif
17
18
19#if defined ( __CC_ARM )
20 #if (__ARMCC_VERSION < 400000)
21 #else
22 /* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
23 #pragma import _printf_widthprec
24 #endif
25#endif
26
27#ifndef DEBUG_PORT
28 #define DEBUG_PORT UART0
29#endif
30# define BUF_SIZE 512
31
32
33/*---------------------------------------------------------------------------------------------------------*/
34/* Global variables */
35/*---------------------------------------------------------------------------------------------------------*/
36#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
37#if (__ARMCC_VERSION < 6040000)
38struct __FILE
39{
40 int handle; /* Add whatever you need here */
41};
42#else
43#if !defined(__MICROLIB)
44 #if (__OPTIMIZE__ == -O0)
45 __asm(".global __ARM_use_no_argv\n\t" "__ARM_use_no_argv:\n\t");
46 #endif /* (__OPTIMIZE__ == -O0) */
47#endif /* !defined(__MICROLIB) */
48#endif /* (__ARMCC_VERSION < 6040000) */
49
50#elif(__VER__ >= 8000000)
51struct __FILE
52{
53 int handle; /* Add whatever you need here */
54};
55#endif /* !(defined(__ICCARM__) && (__VER__ >= 6010000)) */
56
59
60#if defined (__ARMCC_VERSION) || defined (__ICCARM__)
61 extern int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0);
62
63 #if defined( __ICCARM__ )
64 __WEAK
65 #else
66 __attribute__((weak))
67 #endif
68
69 uint32_t ProcessHardFault(uint32_t lr, uint32_t msp, uint32_t psp);
70#endif
71
72int kbhit(void);
73int IsDebugFifoEmpty(void);
74void _ttywrch(int ch);
75int fputc(int ch, FILE *stream);
76
77#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
78 #if !defined (OS_USE_SEMIHOSTING)
79 int _read(int fd, char *ptr, int len);
80 #endif
81
82 int _write(int fd, char *ptr, int len);
83#endif
84
85#if defined (__ARMCC_VERSION) || defined (__ICCARM__)
86 int fgetc(FILE *stream);
87 int ferror(FILE *stream);
88#endif
89
90char GetChar(void);
91void SendChar_ToUART(int ch);
92void SendChar(int ch);
93static volatile int32_t g_ICE_Conneced = 1;
94enum { r0, r1, r2, r3, r12, lr, pc, psr};
95
96
103static void DumpStack(uint32_t stack[])
104{
105 /*
106 printf("r0 =0x%x\n", stack[r0]);
107 printf("r1 =0x%x\n", stack[r1]);
108 printf("r2 =0x%x\n", stack[r2]);
109 printf("r3 =0x%x\n", stack[r3]);
110 printf("r12=0x%x\n", stack[r12]);
111 printf("lr =0x%x\n", stack[lr]);
112 printf("pc =0x%x\n", stack[pc]);
113 printf("psr=0x%x\n", stack[psr]);
114 */
115}
116
117
118#if defined(DEBUG_ENABLE_SEMIHOST)
119
120/* The static buffer is used to speed up the semihost */
121static char g_buf[16];
122static char g_buf_len = 0;
123
134int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
135{
136 if (g_ICE_Conneced)
137 {
138 if (pn32Out_R0)
139 *pn32Out_R0 = n32In_R0;
140
141 return 1;
142 }
143
144 return 0;
145}
146
147
148#else // defined(DEBUG_ENABLE_SEMIHOST)
149
150#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
151
162__attribute__((weak)) void HardFault_Handler(void)
163{
164 asm("MOV R0, LR \n"
165 "MRS R1, MSP \n"
166 "MRS R2, PSP \n"
167 "LDR R3, =ProcessHardFault \n"
168 "BLX R3 \n"
169 "BX R0 \n"
170 );
171}
172
173#else
174int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0);
175int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
176{
177 return 0;
178}
179#endif
180
181#endif /* defined(DEBUG_ENABLE_SEMIHOST) */
182
183
184#if defined( __ICCARM__ )
185 __WEAK
186#else
188#endif
189uint32_t ProcessHardFault(uint32_t lr, uint32_t msp, uint32_t psp)
190{
191 uint32_t *sp;
192 uint32_t inst;
193
194 /* It is casued by hardfault. Just process the hard fault */
195 /* TODO: Implement your hardfault handle code here */
196
197 /* Check the used stack */
198#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
199
200 if (lr & 0x40UL)
201 {
202#endif
203
204 /* Secure stack used */
205 if (lr & 4UL)
206 {
207 sp = (uint32_t *)psp;
208 }
209 else
210 {
211 sp = (uint32_t *)msp;
212 }
213
214#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
215 }
216 else
217 {
218 /* Non-secure stack used */
219 if (lr & 4)
220 sp = (uint32_t *)__TZ_get_PSP_NS();
221 else
222 sp = (uint32_t *)__TZ_get_MSP_NS();
223 }
224
225#endif
226
227 /* Get the instruction caused the hardfault */
228 inst = M16(sp[6]);
229
230 if (inst == 0xBEAB)
231 {
232 /*
233 If the instruction is 0xBEAB, it means it is caused by BKPT without ICE connected.
234 We still return for output/input message to UART.
235 */
236 g_ICE_Conneced = 0; // Set a flag for ICE offline
237 sp[6] += 2; // Return to next instruction
238 return lr; // Keep lr in R0
239 }
240
241 printf(" HardFault!\n\n");
242 DumpStack(sp);
243
244 /* Or *sp to remove compiler warning */
245 while (1U | *sp) {}
246
247 return lr;
248}
249
250
260#ifndef NONBLOCK_PRINTF
261void SendChar_ToUART(int ch)
262{
263 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) {}
264
265 if ((char)ch == '\n')
266 {
267 DEBUG_PORT->DAT = '\r';
268
269 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) {}
270
271 }
272
273 DEBUG_PORT->DAT = (uint32_t)ch;
274}
275
276#else
277
278/* Non-block implement of send char */
279void SendChar_ToUART(int ch)
280{
281 static uint8_t u8Buf[BUF_SIZE] = {0};
282 static int32_t i32Head = 0;
283 static int32_t i32Tail = 0;
284 int32_t i32Tmp;
285
286 /* Only flush the data in buffer to UART when ch == 0 */
287 if (ch)
288 {
289 // Push char
290
291 if (ch == '\n')
292 {
293 i32Tmp = i32Head + 1;
294
295 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
296
297 if (i32Tmp != i32Tail)
298 {
299 u8Buf[i32Head] = '\r';
300 i32Head = i32Tmp;
301 }
302 }
303
304 i32Tmp = i32Head + 1;
305
306 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
307
308 if (i32Tmp != i32Tail)
309 {
310 u8Buf[i32Head] = ch;
311 i32Head = i32Tmp;
312 }
313 }
314 else
315 {
316 if (i32Tail == i32Head)
317 return;
318 }
319
320 // Pop char
321 do
322 {
323 i32Tmp = i32Tail + 1;
324
325 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
326
327 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
328 {
329 DEBUG_PORT->DAT = u8Buf[i32Tail];
330 i32Tail = i32Tmp;
331 }
332 else
333 break; // FIFO full
334 } while (i32Tail != i32Head);
335}
336#endif /* else for NONBLOCK_PRINTF */
337
338
349#if !defined( __ICCARM__ )
350 #define __WEAK __attribute__((weak))
351#endif
352__WEAK void SendChar(int ch)
353{
354#if defined(DEBUG_ENABLE_SEMIHOST)
355 g_buf[g_buf_len++] = ch;
356 g_buf[g_buf_len] = '\0';
357
358 if (g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
359 {
360 /* Send the char */
361 if (g_ICE_Conneced)
362 {
363
364 if (SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
365 {
366 g_buf_len = 0;
367
368 return;
369 }
370 }
371 else
372 {
373#if (DEBUG_ENABLE_SEMIHOST == 1) // Re-direct to UART Debug Port only when DEBUG_ENABLE_SEMIHOST=1
374 int i;
375
376 for (i = 0; i < g_buf_len; i++)
377 SendChar_ToUART(g_buf[i]);
378
379#endif
380 g_buf_len = 0;
381 }
382 }
383
384#else
385 SendChar_ToUART(ch);
386#endif /* DEBUG_ENABLE_SEMIHOST */
387}
388
389
399char GetChar(void)
400{
401#ifdef DEBUG_ENABLE_SEMIHOST
402
403 if (g_ICE_Conneced)
404 {
405#if defined (__ICCARM__)
406 int nRet;
407
408 while (SH_DoCommand(0x7, 0, &nRet) != 0)
409 {
410 if (nRet != 0)
411 return (char)nRet;
412 }
413
414#else
415 int nRet;
416
417 while (SH_DoCommand(0x101, 0, &nRet) != 0)
418 {
419 if (nRet != 0)
420 {
421 SH_DoCommand(0x07, 0, &nRet);
422 return (char)nRet;
423 }
424 }
425
426#endif
427
428 }
429 else
430 {
431
432#if (DEBUG_ENABLE_SEMIHOST == 1) // Re-direct to UART Debug Port only when DEBUG_ENABLE_SEMIHOST=1
433
434 /* Use debug port when ICE is not connected at semihost mode */
435 while (!g_ICE_Conneced)
436 {
437 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U)
438 {
439 return ((char)DEBUG_PORT->DAT);
440 }
441 }
442
443#endif
444 }
445
446 return (0);
447
448#else
449
450 while (1)
451 {
452 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U)
453 {
454 return ((char)DEBUG_PORT->DAT);
455 }
456 }
457
458#endif
459}
460
461
472int kbhit(void)
473{
474 return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U);
475}
476
477
489{
490 return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXENDF_Msk) != 0U);
491}
492
493
503void _ttywrch(int ch)
504{
505 SendChar(ch);
506 return;
507}
508
509
527int fputc(int ch, FILE *stream)
528{
529 SendChar(ch);
530 return ch;
531}
532
533
534#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
535
536#if defined (OS_USE_SEMIHOSTING)
537
538#else
539
540int _write(int fd, char *ptr, int len)
541{
542 int i = len;
543
544 while (i--)
545 {
546 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
547
548 if (*ptr == '\n')
549 {
550 DEBUG_PORT->DAT = '\r';
551
552 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
553 }
554
555 DEBUG_PORT->DAT = *ptr++;
556 }
557
558 return len;
559}
560
561
562int _read(int fd, char *ptr, int len)
563{
564 while ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
565
566 *ptr = DEBUG_PORT->DAT;
567 return 1;
568}
569#endif
570
571#else
572
583int fgetc(FILE *stream)
584{
585 return ((int)GetChar());
586}
587
588
603int ferror(FILE *stream)
604{
605 return EOF;
606}
607#endif
608
609
610#ifdef DEBUG_ENABLE_SEMIHOST
611#ifdef __ICCARM__
612void __exit(int return_code)
613{
614 /* Check if link with ICE */
615 if (SH_DoCommand(0x18, 0x20026, NULL) == 0)
616 {
617 /* Make sure all message is print out */
618 while (IsDebugFifoEmpty() == 0);
619 }
620
621label:
622 goto label; /* Endless loop */
623}
624
625#else
626
627void _sys_exit(int return_code)
628{
629 /* Check if link with ICE */
630 if (SH_DoCommand(0x18, 0x20026, NULL) == 0)
631 {
632 /* Make sure all message is print out */
633 while (IsDebugFifoEmpty() == 0);
634 }
635
636label:
637 goto label; /* Endless loop */
638}
639
640#endif
641#endif
NANO103 peripheral access layer header file. This file contains all the peripheral register's definit...
#define UART_FIFOSTS_TXENDF_Msk
Definition: Nano103.h:11123
#define UART_FIFOSTS_TXFULL_Msk
Definition: Nano103.h:11120
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: Nano103.h:11099
#define M16(addr)
Get a 16-bit unsigned value from specified address.
Definition: Nano103.h:13844
#define NULL
NULL pointer.
Definition: Nano103.h:13963
__attribute__((weak))
A callback called by library while smartcard request for a time extension.
Definition: retarget.c:187
@ pc
Definition: retarget.c:94
@ r0
Definition: retarget.c:94
@ r2
Definition: retarget.c:94
@ lr
Definition: retarget.c:94
@ r3
Definition: retarget.c:94
@ r1
Definition: retarget.c:94
@ r12
Definition: retarget.c:94
@ psr
Definition: retarget.c:94
static void DumpStack(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:103
int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
Definition: retarget.c:175
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:503
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:527
void SendChar(int ch)
Definition: retarget.c:352
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:603
int IsDebugFifoEmpty(void)
Check if debug message finished.
Definition: retarget.c:488
void SendChar_ToUART(int ch)
Routine to send a char.
Definition: retarget.c:261
#define BUF_SIZE
Definition: retarget.c:30
int kbhit(void)
Check any char input from UART.
Definition: retarget.c:472
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:583
FILE __stdin
Definition: retarget.c:58
FILE __stdout
Definition: retarget.c:57
#define __WEAK
Routine to send a char.
Definition: retarget.c:350
char GetChar(void)
Routine to get a char.
Definition: retarget.c:399
#define DEBUG_PORT
Definition: retarget.c:28
static volatile int32_t g_ICE_Conneced
Definition: retarget.c:93
int handle
Definition: retarget.c:40