| NUC472_NUC442_BSP V3.03.003 The Board Support Package for NUC472/NUC442

retarget.c
Go to the documentation of this file.
1/**************************************************************************/
12#include <stdio.h>
13#include "NUC472_442.h"
14
15#if defined ( __CC_ARM )
16#if (__ARMCC_VERSION < 400000)
17#else
18/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
19#pragma import _printf_widthprec
20#endif
21#endif
22
23/* Un-comment this line to disable all printf and getchar. getchar() will always return 0x00*/
24//#define DISABLE_UART
25
26#if defined(DEBUG_ENABLE_SEMIHOST)
27 #ifndef DISABLE_UART
28 #define DISABLE_UART
29 #endif
30#endif
31
32/*--------------------------------------------------------------------------------------------------------- */
33/* Global variables */
34/*--------------------------------------------------------------------------------------------------------- */
35#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
36# if (__ARMCC_VERSION < 6040000)
37 struct __FILE
38{
39 int handle; /* Add whatever you need here */
40};
41# endif
42#elif(__VER__ >= 8000000)
43 struct __FILE
44{
45 int handle; /* Add whatever you need here */
46};
47#endif
48FILE __stdout;
49FILE __stdin;
50
51 enum { r0, r1, r2, r3, r12, lr, pc, psr};
52
58 static void stackDump(uint32_t stack[])
59{
60 printf("r0 = 0x%x\n", stack[r0]);
61 printf("r1 = 0x%x\n", stack[r1]);
62 printf("r2 = 0x%x\n", stack[r2]);
63 printf("r3 = 0x%x\n", stack[r3]);
64 printf("r12 = 0x%x\n", stack[r12]);
65 printf("lr = 0x%x\n", stack[lr]);
66 printf("pc = 0x%x\n", stack[pc]);
67 printf("psr = 0x%x\n", stack[psr]);
68}
69
76 void Hard_Fault_Handler(uint32_t stack[])
77{
78 printf("In Hard Fault Handler\n");
79
80 stackDump(stack);
81 // Replace while(1) with chip reset if WDT is not enabled for end product
82 while(1);
83 //SYS->IPRSTC1 = SYS_IPRSTC1_CHIP_RST_Msk;
84}
85
86#if defined(DEBUG_ENABLE_SEMIHOST)
87/* The static buffer is used to speed up the semihost */
88 static char g_buf[16];
89 static char g_buf_len = 0;
90
91/* Make sure won't goes here only because --gnu is defined , so
92 add !__CC_ARM and !__ICCARM__ checking */
93# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
94
95# elif defined(__ICCARM__) // IAR
96
97 void SH_End(void)
98{
99 asm("MOVS R0,#1 \n" //; Set return value to 1
100 "BX lr \n" //; Return
101 );
102}
103
104 void SH_ICE(void)
105{
106 asm("CMP R2,#0 \n"
107 "BEQ SH_End \n"
108 "STR R0,[R2] \n" //; Save the return value to *pn32Out_R0
109 );
110}
111
122int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
123{
124 asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
125 "B SH_ICE \n"
126 "SH_HardFault: \n" //; Captured by HardFault
127 "MOVS R0,#0 \n" //; Set return value to 0
128 "BX lr \n" //; Return
129 );
130
131 return 1; //; Return 1 when it is trap by ICE
132}
133
134 void Get_LR_and_Branch(void)
135{
136 asm("MOV R1, LR \n" //; LR current value
137 "B Hard_Fault_Handler \n"
138 );
139}
140
141 void Stack_Use_MSP(void)
142{
143 asm("MRS R0, MSP \n" //; stack use MSP
144 "B Get_LR_and_Branch \n"
145 );
146}
147
148 void HardFault_Handler_Ret(void)
149{
150 asm("MOVS r0, #4 \n"
151 "MOV r1, LR \n"
152 "TST r0, r1 \n"
153 "BEQ Stack_Use_MSP \n"
154 "MRS R0, PSP \n" //; stack use PSP
155 "B Get_LR_and_Branch \n"
156 );
157}
158
159 void SP_Read_Ready(void)
160{
161 asm("LDR R1, [R0, #24] \n" //; Get previous PC
162 "LDRH R3, [R1] \n" //; Get instruction
163 "LDR R2, [pc, #8] \n" //; The special BKPT instruction
164 "CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
165 "BNE HardFault_Handler_Ret \n" //; Not BKPT
166 "ADDS R1, #4 \n" //; Skip BKPT and next line
167 "STR R1, [R0, #24] \n" //; Save previous PC
168 "BX lr \n" //; Return
169 "DCD 0xBEAB \n" //; BKPT instruction code
170 "B HardFault_Handler_Ret \n"
171 );
172}
173
174
175 void SP_is_PSP(void)
176{
177 asm(
178 "MRS R0, PSP \n"
179 );
180}
181
192 void HardFault_Handler (void)
193{
194 asm("MOV R0, lr \n"
195 "LSLS R0, #29 \n" //; Check bit 2
196 "BMI SP_is_PSP \n" //; previous stack is PSP
197 "MRS R0, MSP \n" //; previous stack is MSP, read MSP
198 "B SP_Read_Ready \n"
199 );
200
201 while(1);
202}
203
204# else
205
216__asm int32_t HardFault_Handler(void)
217{
218 MOV R0, LR
219 LSLS R0, #29 //; Check bit 2
220 BMI SP_is_PSP //; previous stack is PSP
221 MRS R0, MSP //; previous stack is MSP, read MSP
222 B SP_Read_Ready
223SP_is_PSP
224 MRS R0, PSP //; Read PSP
225
226SP_Read_Ready
227 LDR R1, [R0, #24] //; Get previous PC
228 LDRH R3, [R1] //; Get instruction
229 LDR R2, =0xBEAB //; The special BKPT instruction
230 CMP R3, R2 //; Test if the instruction at previous PC is BKPT
231 BNE HardFault_Handler_Ret //; Not BKPT
232
233 ADDS R1, #4 //; Skip BKPT and next line
234 STR R1, [R0, #24] //; Save previous PC
235
236 BX LR //; Return
237HardFault_Handler_Ret
238
239 /* TODO: Implement your own hard fault handler here. */
240 MOVS r0, #4
241 MOV r1, LR
242 TST r0, r1
243 BEQ Stack_Use_MSP
244 MRS R0, PSP ;stack use PSP
245 B Get_LR_and_Branch
246Stack_Use_MSP
247 MRS R0, MSP ; stack use MSP
248Get_LR_and_Branch
249 MOV R1, LR ; LR current value
250 LDR R2,=__cpp(Hard_Fault_Handler)
251 BX R2
252
253 B .
254
255 ALIGN
256}
257
268__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
269{
270 BKPT 0xAB //; Wait ICE or HardFault
271 //; ICE will step over BKPT directly
272 //; HardFault will step BKPT and the next line
273 B SH_ICE
274
275SH_HardFault //; Captured by HardFault
276 MOVS R0, #0 //; Set return value to 0
277 BX lr //; Return
278
279SH_ICE //; Captured by ICE
280 //; Save return value
281 CMP R2, #0
282 BEQ SH_End
283 STR R0, [R2] //; Save the return value to *pn32Out_R0
284
285SH_End
286 MOVS R0, #1 //; Set return value to 1
287 BX lr //; Return
288}
289#endif
290
291#else
292
293/* Make sure won't goes here only because --gnu is defined , so
294 add !__CC_ARM and !__ICCARM__ checking */
295# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
296
307 void HardFault_Handler(void)
308{
309 asm("MOVS r0, #4 \n"
310 "MOV r1, LR \n"
311 "TST r0, r1 \n" /*; check LR bit 2 */
312 "BEQ 1f \n" /*; stack use MSP */
313 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
314 "MOV R1, LR \n" /*; LR current value */
315 "B Hard_Fault_Handler \n"
316 "1: \n"
317 "MRS R0, MSP \n" /*; LR current value */
318 "B Hard_Fault_Handler \n"
319 ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
320 );
321 while(1);
322}
323
324# elif defined(__ICCARM__)
325
326 void Get_LR_and_Branch(void)
327{
328 asm("MOV R1, LR \n" //; LR current value
329 "B Hard_Fault_Handler \n"
330 );
331}
332
333 void Stack_Use_MSP(void)
334{
335 asm("MRS R0, MSP \n" //; stack use MSP
336 "B Get_LR_and_Branch \n"
337 );
338}
339
350 void HardFault_Handler(void)
351{
352 asm("MOVS r0, #4 \n"
353 "MOV r1, LR \n"
354 "TST r0, r1 \n"
355 "BEQ Stack_Use_MSP \n"
356 "MRS R0, PSP \n" //; stack use PSP
357 "B Get_LR_and_Branch \n"
358 );
359
360 while(1);
361}
362
363# else
364
375__asm int32_t HardFault_Handler(void)
376{
377 MOVS r0, #4
378 MOV r1, LR
379 TST r0, r1
380 BEQ Stack_Use_MSP
381 MRS R0, PSP ;stack use PSP
382 B Get_LR_and_Branch
383Stack_Use_MSP
384 MRS R0, MSP ; stack use MSP
385Get_LR_and_Branch
386 MOV R1, LR ; LR current value
387 LDR R2,=__cpp(Hard_Fault_Handler)
388 BX R2
389}
390
391#endif
392
393#endif
394
395#define DEBUG_PORT UART0
396
402 void SendChar_ToUART(int ch)
403{
404#ifndef DISABLE_UART
405 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)); //waits for TXFULL bit is clear
406 DEBUG_PORT->DAT = ch;
407 if(ch == '\n') {
408 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)); //waits for TXFULL bit is clear
409 DEBUG_PORT->DAT = '\r';
410 }
411#endif
412}
413
419 void SendChar(int ch)
420{
421#if defined(DEBUG_ENABLE_SEMIHOST)
422 g_buf[g_buf_len++] = ch;
423 g_buf[g_buf_len] = '\0';
424 if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0') {
425
426 /* Send the char */
427 if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0) {
428 g_buf_len = 0;
429 return;
430 } else {
431 int i;
432
433 for(i=0; i<g_buf_len; i++)
434 SendChar_ToUART(g_buf[i]);
435 g_buf_len = 0;
436 }
437 }
438#else
439 SendChar_ToUART(ch);
440#endif
441}
442
449 char GetChar(void)
450{
451#if defined(DEBUG_ENABLE_SEMIHOST)
452# if defined ( __CC_ARM )
453 int nRet;
454 while(SH_DoCommand(0x101, 0, &nRet) != 0) {
455 if(nRet != 0) {
456 SH_DoCommand(0x07, 0, &nRet);
457 return (char)nRet;
458 }
459 }
460# else
461 int nRet;
462 while(SH_DoCommand(0x7, 0, &nRet) != 0) {
463 if(nRet != 0)
464 return (char)nRet;
465 }
466# endif
467#endif
468
469#ifndef DISABLE_UART
470 while (1) {
471 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0 ) {
472 return (DEBUG_PORT->DAT);
473
474 }
475 }
476#else
477 return(0);
478#endif
479}
480
481
489 int kbhit(void)
490{
491#ifndef DISABLE_UART
492 return !(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXFULL_Msk);
493#else
494 return(0);
495#endif
496}
497
505 int IsDebugFifoEmpty(void)
506{
507#ifndef DISABLE_UART
508 return (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk);
509#else
510 return(1);
511#endif
512}
513
521 void _ttywrch(int ch)
522{
523 SendChar(ch);
524 return;
525}
526
527#if defined ( __GNUC__ )
528
529 int _write (int fd, char *ptr, int len)
530{
531 int i = len;
532
533 while(i--) {
534 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
535
536 DEBUG_PORT->DAT = *ptr++;
537
538 if(*ptr == '\n') {
539 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
540 DEBUG_PORT->DAT = '\r';
541 }
542 }
543 return len;
544}
545
546 int _read (int fd, char *ptr, int len)
547{
548
549 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
550 *ptr = DEBUG_PORT->DAT;
551 return 1;
552
553
554}
555
556#else
569 int fputc(int ch, FILE *stream)
570{
571 SendChar(ch);
572 return ch;
573}
574
582 int fgetc(FILE *stream)
583{
584 return (GetChar());
585}
586
596 int ferror(FILE *stream)
597{
598 return EOF;
599}
600#endif
601#ifdef DEBUG_ENABLE_SEMIHOST
602# ifdef __ICCARM__
603 void __exit(int return_code)
604{
605
606 /* Check if link with ICE */
607 if(SH_DoCommand(0x18, 0x20026, NULL) == 0) {
608 /* Make sure all message is print out */
609 while(IsDebugFifoEmpty() == 0);
610 }
611label:
612 goto label; /* endless loop */
613}
614# else
615 void _sys_exit(int return_code)
616{
617
618 /* Check if link with ICE */
619 if(SH_DoCommand(0x18, 0x20026, NULL) == 0) {
620 /* Make sure all message is print out */
621 while(IsDebugFifoEmpty() == 0);
622 }
623label:
624 goto label; /* endless loop */
625}
626# endif
627#endif
628
629/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
NUC472_442.h
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
UART_FIFOSTS_TXFULL_Msk
#define UART_FIFOSTS_TXFULL_Msk
Definition: NUC472_442.h:25935
UART_FIFOSTS_RXFULL_Msk
#define UART_FIFOSTS_RXFULL_Msk
Definition: NUC472_442.h:25926
UART_FIFOSTS_TXEMPTYF_Msk
#define UART_FIFOSTS_TXEMPTYF_Msk
Definition: NUC472_442.h:25941
UART_FIFOSTS_RXEMPTY_Msk
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: NUC472_442.h:25923
NULL
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
_ttywrch
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:521
HardFault_Handler
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:375
fputc
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:569
ferror
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:596
IsDebugFifoEmpty
int IsDebugFifoEmpty(void)
Check whether UART transmit FIFO is empty or not.
Definition: retarget.c:505
SendChar_ToUART
void SendChar_ToUART(int ch)
Write a char to UART.
Definition: retarget.c:402
kbhit
int kbhit(void)
Check whether UART receive FIFO is empty or not.
Definition: retarget.c:489
fgetc
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:582
__stdin
FILE __stdin
Definition: retarget.c:49
Hard_Fault_Handler
void Hard_Fault_Handler(uint32_t stack[])
Hard fault handler.
Definition: retarget.c:76
SendChar
void SendChar(int ch)
Write a char to debug console.
Definition: retarget.c:419
__stdout
FILE __stdout
Definition: retarget.c:48
GetChar
char GetChar(void)
Read a char from debug console.
Definition: retarget.c:449
DEBUG_PORT
#define DEBUG_PORT
Definition: retarget.c:395
pc
@ pc
Definition: retarget.c:51
r0
@ r0
Definition: retarget.c:51
r2
@ r2
Definition: retarget.c:51
lr
@ lr
Definition: retarget.c:51
r3
@ r3
Definition: retarget.c:51
r1
@ r1
Definition: retarget.c:51
r12
@ r12
Definition: retarget.c:51
psr
@ psr
Definition: retarget.c:51
stackDump
static void stackDump(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:58
value
return value
Definition: semihosting.h:98
__FILE
Definition: retarget.c:38
__FILE::handle
int handle
Definition: retarget.c:39