1 /**************************************************************************//**
2  * @file     retarget.c
3  * @version  V3.00
4  * @brief    M480 Series Debug Port and Semihost Setting Source File
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8  ******************************************************************************/
9 
10 
11 #include <stdio.h>
12 #include "NuMicro.h"
13 
14 #if defined ( __CC_ARM   )
15 #if (__ARMCC_VERSION < 400000)
16 #else
17 /* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
18 #pragma import _printf_widthprec
19 #endif
20 #endif
21 /* Uncomment this line to disable all printf and getchar. getchar() will always return 0x00*/
22 /* #define DISABLE_UART */
23 
24 #if defined(DEBUG_ENABLE_SEMIHOST)
25     #ifndef DISABLE_UART
26         #define DISABLE_UART
27     #endif
28 #endif
29 
30 #define DEBUG_PORT   UART0
31 /*---------------------------------------------------------------------------------------------------------*/
32 /* Global variables                                                                                        */
33 /*---------------------------------------------------------------------------------------------------------*/
34 #if !(defined(__ICCARM__) && (__VER__ >= 6010000))
35 # if (__ARMCC_VERSION < 6040000)
36 struct __FILE
37 {
38     int handle; /* Add whatever you need here */
39 };
40 # endif
41 #elif(__VER__ >= 8000000)
42 struct __FILE
43 {
44     int handle; /* Add whatever you need here */
45 };
46 #endif
47 FILE __stdout;
48 FILE __stdin;
49 
50 
51 enum { r0, r1, r2, r3, r12, lr, pc, psr};
52 
53 /**
54  * @brief       Helper function to dump register while hard fault occurred
55  * @param[in]   stack pointer points to the dumped registers in SRAM
56  * @return      None
57  * @details     This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr
58  */
stackDump(uint32_t stack[])59 static void stackDump(uint32_t stack[])
60 {
61     printf("r0  = 0x%x\n", stack[r0]);
62     printf("r1  = 0x%x\n", stack[r1]);
63     printf("r2  = 0x%x\n", stack[r2]);
64     printf("r3  = 0x%x\n", stack[r3]);
65     printf("r12 = 0x%x\n", stack[r12]);
66     printf("lr  = 0x%x\n", stack[lr]);
67     printf("pc  = 0x%x\n", stack[pc]);
68     printf("psr = 0x%x\n", stack[psr]);
69 }
70 
71 /**
72  * @brief       Hard fault handler
73  * @param[in]   stack pointer points to the dumped registers in SRAM
74  * @return      None
75  * @details     Replace while(1) at the end of this function with chip reset if WDT is not enabled for end product
76  */
Hard_Fault_Handler(uint32_t stack[])77 void Hard_Fault_Handler(uint32_t stack[])
78 {
79     printf("In Hard Fault Handler\n");
80 
81     stackDump(stack);
82     /* Replace while(1) with chip reset if WDT is not enabled for end product */
83     while(1);
84     /* SYS->IPRST0 = SYS_IPRST0_CHIPRST_Msk; */
85 }
86 
87 
88 
89 /*---------------------------------------------------------------------------------------------------------*/
90 /* Routine to write a char                                                                                 */
91 /*---------------------------------------------------------------------------------------------------------*/
92 
93 #if defined(DEBUG_ENABLE_SEMIHOST)
94 /* The static buffer is used to speed up the semihost    */
95 static char g_buf[16];
96 static char g_buf_len = 0;
97 
98 /* Make sure won't goes here only because --gnu is defined , so
99    add !__CC_ARM and !__ICCARM__ checking */
100 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
101 
102 # elif defined(__ICCARM__)      // IAR
103 
SH_End(void)104 void SH_End(void)
105 {
106     asm("MOVS   R0,#1 \n"        /*; Set return value to 1 */
107         "BX     lr    \n"        /*; Return */
108        );
109 }
110 
SH_ICE(void)111 void SH_ICE(void)
112 {
113   asm("CMP   R2,#0   \n"
114       "BEQ   SH_End  \n"
115       "STR   R0,[R2] \n"       /*; Save the return value to *pn32Out_R0 */
116      );
117 }
118 
119 /**
120  *
121  * @brief      The function to process semihosted command
122  * @param[in]  n32In_R0  : semihost register 0
123  * @param[in]  n32In_R1  : semihost register 1
124  * @param[out] pn32Out_R0: semihost register 0
125  * @retval     0: No ICE debug
126  * @retval     1: ICE debug
127  *
128  */
SH_DoCommand(int32_t n32In_R0,int32_t n32In_R1,int32_t * pn32Out_R0)129 int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
130 {
131     asm("BKPT   0xAB   \n"       /*; This instruction will cause ICE trap or system HardFault */
132         "B      SH_ICE \n"
133         "SH_HardFault: \n"       /*; Captured by HardFault */
134         "MOVS   R0,#0  \n"       /*; Set return value to 0 */
135         "BX     lr     \n"       /*; Return */
136         );
137 
138     return 1;                    /*; Return 1 when it is trap by ICE */
139 }
140 
141 /**
142  * @brief       Get LR value and branch to Hard_Fault_Handler function
143  * @param       None
144  * @return      None
145  * @details     This function is use to get LR value and branch to Hard_Fault_Handler function.
146  */
Get_LR_and_Branch(void)147 void Get_LR_and_Branch(void)
148 {
149     asm("MOV     R1, LR               \n" /*; LR current value */
150         "B       Hard_Fault_Handler   \n"
151        );
152 }
153 
154 /**
155  * @brief       Get MSP value and branch to Get_LR_and_Branch function
156  * @param       None
157  * @return      None
158  * @details     This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
159  */
Stack_Use_MSP(void)160 void Stack_Use_MSP(void)
161 {
162     asm("MRS     R0, MSP           \n" /*; read MSP */
163         "B       Get_LR_and_Branch \n"
164        );
165 }
166 
167 /**
168  * @brief       Get stack pointer value and branch to Get_LR_and_Branch function
169  * @param       None
170  * @return      None
171  * @details     This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
172  */
HardFault_Handler_Ret(void)173 void HardFault_Handler_Ret(void)
174 {
175     asm("MOVS    r0, #4                        \n"
176         "MOV     r1, LR                        \n"
177         "TST     r0, r1                        \n" /*; check LR bit 2 */
178         "BEQ     Stack_Use_MSP                 \n" /*; stack use MSP */
179         "MRS     R0, PSP                       \n" /*; stack use PSP, read PSP */
180         "B       Get_LR_and_Branch             \n"
181        );
182 }
183 
184 /**
185  * @brief    This function is implemented to support semihost
186  * @param    None
187  * @returns  None
188  * @details  This function is implement to support semihost message print.
189  *
190  */
SP_Read_Ready(void)191 void SP_Read_Ready(void)
192 {
193     asm("LDR     R1, [R0, #24] \n"        /*; Get previous PC */
194         "LDRH    R3, [R1]      \n"        /*; Get instruction */
195         "LDR     R2, [pc, #8]  \n"        /*; The special BKPT instruction */
196         "CMP     R3, R2        \n"        /*; Test if the instruction at previous PC is BKPT */
197         "BNE     HardFault_Handler_Ret \n" /*; Not BKPT */
198         "ADDS    R1, #4        \n"        /*; Skip BKPT and next line */
199         "STR     R1, [R0, #24] \n"        /*; Save previous PC */
200         "BX      lr            \n"        /*; Return */
201         "DCD     0xBEAB        \n"        /*; BKPT instruction code */
202         "B       HardFault_Handler_Ret \n"
203        );
204 }
205 
206 /**
207  * @brief       Get stack pointer value and branch to Get_LR_and_Branch function
208  * @param       None
209  * @return      None
210  * @details     This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
211  */
SP_is_PSP(void)212 void SP_is_PSP(void)
213 {
214     asm(
215         "MRS     R0, PSP       \n"      /*; stack use PSP, read PSP */
216         "B       Get_LR_and_Branch    \n"
217 
218        );
219 }
220 
221 /**
222  * @brief    This HardFault handler is implemented to support semihost
223  *
224  * @param    None
225  *
226  * @returns  None
227  *
228  * @details  This function is implement to support semihost message print.
229  *
230  */
HardFault_Handler(void)231 void HardFault_Handler (void)
232 {
233     asm("MOV     R0, lr        \n"
234         "LSLS    R0, #29       \n"        /*; Check bit 2 */
235         "BMI     SP_is_PSP     \n"        /*; previous stack is PSP */
236         "MRS     R0, MSP       \n"        /*; previous stack is MSP, read MSP */
237         "B       SP_Read_Ready \n"
238        );
239 
240     while(1);
241 }
242 
243 # else
244 
245 /**
246  * @brief    This HardFault handler is implemented to support semihost
247  * @param    None
248  * @returns  None
249  * @details  This function is implement to support semihost message print.
250  *
251  */
HardFault_Handler(void)252 __asm int32_t HardFault_Handler(void)
253 {
254     MOV     R0, LR
255     LSLS    R0, #29               /*; Check bit 2 */
256     BMI     SP_is_PSP             /*; previous stack is PSP */
257     MRS     R0, MSP               /*; previous stack is MSP, read MSP */
258     B       SP_Read_Ready
259 SP_is_PSP
260     MRS     R0, PSP               /*; Read PSP */
261 
262 SP_Read_Ready
263     LDR     R1, [R0, #24]         /*; Get previous PC */
264     LDRH    R3, [R1]              /*; Get instruction */
265     LDR     R2, =0xBEAB           /*; The special BKPT instruction */
266     CMP     R3, R2                /*; Test if the instruction at previous PC is BKPT */
267     BNE     HardFault_Handler_Ret /*; Not BKPT */
268 
269     ADDS    R1, #4                /*; Skip BKPT and next line */
270     STR     R1, [R0, #24]         /*; Save previous PC */
271 
272     BX      LR                    /*; Return */
273 HardFault_Handler_Ret
274 
275     /* TODO: Implement your own hard fault handler here. */
276     MOVS    r0, #4
277     MOV     r1, LR
278     TST     r0, r1                          /*; check LR bit 2 */
279     BEQ     Stack_Use_MSP                   /*; stack use MSP */
280     MRS     R0, PSP ;stack use PSP          /*; stack use PSP, read PSP */
281     B       Get_LR_and_Branch
282 Stack_Use_MSP
283     MRS     R0, MSP ; stack use MSP         /*; read MSP */
284 Get_LR_and_Branch
285     MOV     R1, LR ; LR current value       /*; LR current value */
286     LDR     R2,=__cpp(Hard_Fault_Handler)   /*; branch to Hard_Fault_Handler */
287     BX      R2
288 
289     B       .
290 
291     ALIGN
292 }
293 
294 /**
295  *
296  * @brief      The function to process semihosted command
297  * @param[in]  n32In_R0  : semihost register 0
298  * @param[in]  n32In_R1  : semihost register 1
299  * @param[out] pn32Out_R0: semihost register 0
300  * @retval     0: No ICE debug
301  * @retval     1: ICE debug
302  *
303  */
SH_DoCommand(int32_t n32In_R0,int32_t n32In_R1,int32_t * pn32Out_R0)304 __asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
305 {
306     BKPT   0xAB          /*; Wait ICE or HardFault */
307     /*; ICE will step over BKPT directly
308       ; HardFault will step BKPT and the next line */
309     B      SH_ICE
310 
311 SH_HardFault             /*; Captured by HardFault */
312     MOVS   R0, #0        /*; Set return value to 0 */
313     BX     lr            /*; Return */
314 
315 SH_ICE                   /*; Captured by ICE */
316     /*; Save return value */
317     CMP    R2, #0
318     BEQ    SH_End
319     STR    R0, [R2]      /*; Save the return value to *pn32Out_R0 */
320 
321 SH_End
322     MOVS   R0, #1        /*; Set return value to 1 */
323     BX     lr            /*; Return */
324 }
325 #endif
326 
327 #else   // ndef DEBUG_ENABLE_SEMIHOST
328 
329 /* Make sure won't goes here only because --gnu is defined , so
330    add !__CC_ARM and !__ICCARM__ checking */
331 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
332 
333 /**
334  * @brief    This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
335  *
336  * @param    None
337  *
338  * @returns  None
339  *
340  * @details  This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
341  *
342  */
HardFault_Handler(void)343 void HardFault_Handler(void)
344 {
345     asm("MOVS    r0, #4                        \n"
346         "MOV     r1, LR                        \n"
347         "TST     r0, r1                        \n" /*; check LR bit 2 */
348         "BEQ     1f                            \n" /*; stack use MSP */
349         "MRS     R0, PSP                       \n" /*; stack use PSP, read PSP */
350         "MOV     R1, LR                        \n" /*; LR current value */
351         "B       Hard_Fault_Handler            \n"
352         "1:                                    \n"
353         "MRS     R0, MSP                       \n" /*; LR current value */
354         "B       Hard_Fault_Handler            \n"
355         ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
356     );
357     while(1);
358 }
359 
360 # elif defined(__ICCARM__)
361 
Get_LR_and_Branch(void)362 void Get_LR_and_Branch(void)
363 {
364     asm("MOV     R1, LR                  \n" /*; LR current value */
365         "B       Hard_Fault_Handler      \n"
366        );
367 }
368 
Stack_Use_MSP(void)369 void Stack_Use_MSP(void)
370 {
371     asm("MRS     R0, MSP           \n" /*; read MSP */
372         "B       Get_LR_and_Branch \n"
373        );
374 }
375 
376 /**
377  * @brief    This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
378  *
379  * @param    None
380  *
381  * @returns  None
382  *
383  * @details  This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
384  *
385  */
HardFault_Handler(void)386 void HardFault_Handler(void)
387 {
388     asm("MOVS    r0, #4                        \n"
389         "MOV     r1, LR                        \n"
390         "TST     r0, r1                        \n" /*; check LR bit 2 */
391         "BEQ     Stack_Use_MSP                 \n" /*; stack use MSP */
392         "MRS     R0, PSP                       \n" /*; stack use PSP, read PSP */
393         "B       Get_LR_and_Branch             \n"
394        );
395 
396     while(1);
397 }
398 
399 # else
400 
401 /**
402  * @brief    This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
403  *
404  * @param    None
405  *
406  * @return   None
407  *
408  * @details  The function extracts the location of stack frame and passes it to Hard_Fault_Handler function as a pointer
409  *
410  */
HardFault_Handler(void)411 __asm int32_t HardFault_Handler(void)
412 {
413     MOVS    r0, #4
414     MOV     r1, LR
415     TST     r0, r1          /*; check LR bit 2 */
416     BEQ     Stack_Use_MSP   /*; stack use MSP */
417     MRS     R0, PSP         /*; stack use PSP, read PSP */
418     B       Get_LR_and_Branch
419 Stack_Use_MSP
420     MRS     R0, MSP         /*; read MSP */
421 Get_LR_and_Branch
422     MOV     R1, LR          /*; LR current value */
423     LDR     R2,=__cpp(Hard_Fault_Handler) /*; branch to Hard_Fault_Handler */
424     BX      R2
425 }
426 
427 #endif
428 
429 #endif
430 
431 #ifndef DISABLE_UART
432 /**
433  * @brief       Routine to send a char
434  *
435  * @param[in]   ch Character to send to debug port.
436  *
437  * @returns     Send value from UART debug port
438  *
439  * @details     Send a target char to UART debug port .
440  */
441 #ifndef NONBLOCK_PRINTF
SendChar_ToUART(int ch)442 static void SendChar_ToUART(int ch)
443 {
444     while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
445 
446     if(ch == '\n')
447     {
448         DEBUG_PORT->DAT = '\r';
449         while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
450     }
451     DEBUG_PORT->DAT = ch;
452 }
453 
454 #else
455 /* Non-block implement of send char */
456 #define BUF_SIZE    2048
SendChar_ToUART(int ch)457 static void SendChar_ToUART(int ch)
458 {
459     static uint8_t u8Buf[BUF_SIZE] = {0};
460     static int32_t i32Head = 0;
461     static int32_t i32Tail = 0;
462     int32_t i32Tmp;
463 
464     /* Only flush the data in buffer to UART when ch == 0 */
465     if(ch)
466     {
467         /* Push char */
468         if(ch == '\n')
469         {
470             i32Tmp = i32Head+1;
471             if(i32Tmp > BUF_SIZE) i32Tmp = 0;
472             if(i32Tmp != i32Tail)
473             {
474                 u8Buf[i32Head] = '\r';
475                 i32Head = i32Tmp;
476             }
477         }
478 
479         i32Tmp = i32Head+1;
480         if(i32Tmp > BUF_SIZE) i32Tmp = 0;
481         if(i32Tmp != i32Tail)
482         {
483             u8Buf[i32Head] = ch;
484             i32Head = i32Tmp;
485         }
486     }
487     else
488     {
489         if(i32Tail == i32Head)
490             return;
491     }
492 
493     /* pop char */
494     do
495     {
496         i32Tmp = i32Tail + 1;
497         if(i32Tmp > BUF_SIZE) i32Tmp = 0;
498 
499         if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
500         {
501             DEBUG_PORT->DAT = u8Buf[i32Tail];
502             i32Tail = i32Tmp;
503         }
504         else
505             break; /* FIFO full */
506     }while(i32Tail != i32Head);
507 }
508 #endif   /* else for NONBLOCK_PRINTF */
509 
510 #endif   /* if not def DISABLE_UART */
511 
512 /**
513  * @brief       Routine to send a char
514  *
515  * @param[in]   ch Character to send to debug port.
516  *
517  * @returns     Send value from UART debug port or semihost
518  *
519  * @details     Send a target char to UART debug port or semihost.
520  */
SendChar(int ch)521 static void SendChar(int ch)
522 {
523 #if defined(DEBUG_ENABLE_SEMIHOST)
524     g_buf[g_buf_len++] = ch;
525     g_buf[g_buf_len] = '\0';
526     if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
527     {
528         /* Send the char */
529         if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
530         {
531             g_buf_len = 0;
532             return;
533         }
534         else
535         {
536 #ifndef DISABLE_UART
537             int i;
538 
539             for(i = 0; i < g_buf_len; i++)
540                 SendChar_ToUART(g_buf[i]);
541 #endif
542             g_buf_len = 0;
543         }
544     }
545 #else
546 #ifndef DISABLE_UART
547     SendChar_ToUART(ch);
548 #endif
549 #endif
550 }
551 
552 /**
553  * @brief    Routine to get a char
554  *
555  * @param    None
556  *
557  * @returns  Get value from UART debug port or semihost
558  *
559  * @details  Wait UART debug port or semihost to input a char.
560  */
GetChar(void)561 static char GetChar(void)
562 {
563 #ifdef DEBUG_ENABLE_SEMIHOST
564 # if defined (__CC_ARM)
565     int nRet;
566     while(SH_DoCommand(0x101, 0, &nRet) != 0)
567     {
568         if(nRet != 0)
569         {
570             SH_DoCommand(0x07, 0, &nRet);
571             return (char)nRet;
572         }
573     }
574 # else
575     int nRet;
576     while(SH_DoCommand(0x7, 0, &nRet) != 0)
577     {
578         if(nRet != 0)
579             return (char)nRet;
580     }
581 # endif
582     return (0);
583 #else
584 #ifndef DISABLE_UART
585     while(1)
586     {
587         if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
588         {
589             return (DEBUG_PORT->DAT);
590         }
591     }
592 #else
593     return 0;
594 #endif
595 #endif
596 }
597 
598 /**
599  * @brief    Check any char input from UART
600  *
601  * @param    None
602  *
603  * @retval   1: No any char input
604  * @retval   0: Have some char input
605  *
606  * @details  Check UART RSR RX EMPTY or not to determine if any char input from UART
607  */
608 
kbhit(void)609 int kbhit(void)
610 {
611 #ifndef DISABLE_UART
612     return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0);
613 #else
614     return 0;
615 #endif
616 }
617 /**
618  * @brief    Check if debug message finished
619  *
620  * @param    None
621  *
622  * @retval   1: Message is finished
623  * @retval   0: Message is transmitting.
624  *
625  * @details  Check if message finished (FIFO empty of debug port)
626  */
627 
IsDebugFifoEmpty(void)628 int IsDebugFifoEmpty(void)
629 {
630 #ifndef DISABLE_UART
631     return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) != 0);
632 #else
633     return 1;
634 #endif
635 }
636 
637 /**
638  * @brief       C library retargetting
639  *
640  * @param[in]   ch Character to send to debug port.
641  *
642  * @returns     None
643  *
644  * @details     Check if message finished (FIFO empty of debug port)
645  */
646 
_ttywrch(int ch)647 void _ttywrch(int ch)
648 {
649     SendChar(ch);
650     return;
651 }
652 
653 
654 /**
655  * @brief      Write character to stream
656  *
657  * @param[in]  ch       Character to be written. The character is passed as its int promotion.
658  * @param[in]  stream   Pointer to a FILE object that identifies the stream where the character is to be written.
659  *
660  * @returns    If there are no errors, the same character that has been written is returned.
661  *             If an error occurs, EOF is returned and the error indicator is set (see ferror).
662  *
663  * @details    Writes a character to the stream and advances the position indicator.\n
664  *             The character is written at the current position of the stream as indicated \n
665  *             by the internal position indicator, which is then advanced one character.
666  *
667  * @note       The above descriptions are copied from http://www.cplusplus.com/reference/clibrary/cstdio/fputc/.
668  *
669  *
670  */
671 
fputc(int ch,FILE * stream)672 int fputc(int ch, FILE *stream)
673 {
674     SendChar(ch);
675     return ch;
676 }
677 
678 #if defined (__GNUC__) && !defined(__ARMCC_VERSION)
679 
_write(int fd,char * ptr,int len)680 int _write (int fd, char *ptr, int len)
681 {
682     int i = len;
683 
684     while(i--)
685     {
686         while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
687 
688         if(*ptr == '\n')
689         {
690             DEBUG_PORT->DAT = '\r';
691             while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
692         }
693 
694         DEBUG_PORT->DAT = *ptr++;
695 
696     }
697     return len;
698 }
699 
_read(int fd,char * ptr,int len)700 int _read (int fd, char *ptr, int len)
701 {
702 
703     while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
704     *ptr = DEBUG_PORT->DAT;
705     return 1;
706 
707 
708 }
709 
710 #else
711 /**
712  * @brief      Get character from UART debug port or semihosting input
713  *
714  * @param[in]  stream   Pointer to a FILE object that identifies the stream on which the operation is to be performed.
715  *
716  * @returns    The character read from UART debug port or semihosting
717  *
718  * @details    For get message from debug port or semihosting.
719  *
720  */
721 
fgetc(FILE * stream)722 int fgetc(FILE *stream)
723 {
724     return (GetChar());
725 }
726 
727 /**
728  * @brief      Check error indicator
729  *
730  * @param[in]  stream   Pointer to a FILE object that identifies the stream.
731  *
732  * @returns    If the error indicator associated with the stream was set, the function returns a nonzero value.
733  *             Otherwise, it returns a zero value.
734  *
735  * @details    Checks if the error indicator associated with stream is set, returning a value different
736  *             from zero if it is. This indicator is generally set by a previous operation on the stream that failed.
737  *
738  * @note       The above descriptions are copied from http://www.cplusplus.com/reference/clibrary/cstdio/ferror/.
739  *
740  */
741 
ferror(FILE * stream)742 int ferror(FILE *stream)
743 {
744     return EOF;
745 }
746 #endif
747 #ifdef DEBUG_ENABLE_SEMIHOST
748 # ifdef __ICCARM__
__exit(int return_code)749 void __exit(int return_code)
750 {
751 
752     /* Check if link with ICE */
753     if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
754     {
755         /* Make sure all message is print out */
756         while(IsDebugFifoEmpty() == 0);
757     }
758 label:
759     goto label;  /* endless loop */
760 }
761 # else
_sys_exit(int return_code)762 void _sys_exit(int return_code)
763 {
764 
765     /* Check if link with ICE */
766     if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
767     {
768         /* Make sure all message is print out */
769         while(IsDebugFifoEmpty() == 0);
770     }
771 label:
772     goto label;  /* endless loop */
773 }
774 # endif
775 #endif
776