NUC472_NUC442_BSP V3.03.004
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(__ARMCC_VERSION) && (__ARMCC_VERSION < 6040000)) || (defined(__ICCARM__) && (__VER__ >= 8000000))
36struct __FILE { int handle; /* Add whatever you need here */ };
37#endif
40
41enum { r0, r1, r2, r3, r12, lr, pc, psr};
42
48static void stackDump(uint32_t stack[])
49{
50 printf("r0 = 0x%x\n", stack[r0]);
51 printf("r1 = 0x%x\n", stack[r1]);
52 printf("r2 = 0x%x\n", stack[r2]);
53 printf("r3 = 0x%x\n", stack[r3]);
54 printf("r12 = 0x%x\n", stack[r12]);
55 printf("lr = 0x%x\n", stack[lr]);
56 printf("pc = 0x%x\n", stack[pc]);
57 printf("psr = 0x%x\n", stack[psr]);
58}
59
66void Hard_Fault_Handler(uint32_t stack[])
67{
68 printf("In Hard Fault Handler\n");
69
70 stackDump(stack);
71 // Replace while(1) with chip reset if WDT is not enabled for end product
72 while(1);
73 //SYS->IPRSTC1 = SYS_IPRSTC1_CHIP_RST_Msk;
74}
75
76#if defined(DEBUG_ENABLE_SEMIHOST)
77/* The static buffer is used to speed up the semihost */
78static char g_buf[16];
79static char g_buf_len = 0;
80
81/* Make sure won't goes here only because --gnu is defined , so
82 add !__CC_ARM and !__ICCARM__ checking */
83# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
84
85# elif defined(__ICCARM__) // IAR
86
87void SH_End(void)
88{
89 asm("MOVS R0,#1 \n" //; Set return value to 1
90 "BX lr \n" //; Return
91 );
92}
93
94void SH_ICE(void)
95{
96 asm("CMP R2,#0 \n"
97 "BEQ SH_End \n"
98 "STR R0,[R2] \n" //; Save the return value to *pn32Out_R0
99 );
100}
101
112int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
113{
114 asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
115 "B SH_ICE \n"
116 "SH_HardFault: \n" //; Captured by HardFault
117 "MOVS R0,#0 \n" //; Set return value to 0
118 "BX lr \n" //; Return
119 );
120
121 return 1; //; Return 1 when it is trap by ICE
122}
123
124void Get_LR_and_Branch(void)
125{
126 asm("MOV R1, LR \n" //; LR current value
127 "B Hard_Fault_Handler \n"
128 );
129}
130
131void Stack_Use_MSP(void)
132{
133 asm("MRS R0, MSP \n" //; stack use MSP
134 "B Get_LR_and_Branch \n"
135 );
136}
137
138void HardFault_Handler_Ret(void)
139{
140 asm("MOVS r0, #4 \n"
141 "MOV r1, LR \n"
142 "TST r0, r1 \n"
143 "BEQ Stack_Use_MSP \n"
144 "MRS R0, PSP \n" //; stack use PSP
145 "B Get_LR_and_Branch \n"
146 );
147}
148
149void SP_Read_Ready(void)
150{
151 asm("LDR R1, [R0, #24] \n" //; Get previous PC
152 "LDRH R3, [R1] \n" //; Get instruction
153 "LDR R2, [pc, #8] \n" //; The special BKPT instruction
154 "CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
155 "BNE HardFault_Handler_Ret \n" //; Not BKPT
156 "ADDS R1, #4 \n" //; Skip BKPT and next line
157 "STR R1, [R0, #24] \n" //; Save previous PC
158 "BX lr \n" //; Return
159 "DCD 0xBEAB \n" //; BKPT instruction code
160 "B HardFault_Handler_Ret \n"
161 );
162}
163
164
165void SP_is_PSP(void)
166{
167 asm(
168 "MRS R0, PSP \n"
169 );
170}
171
182void HardFault_Handler (void)
183{
184 asm("MOV R0, lr \n"
185 "LSLS R0, #29 \n" //; Check bit 2
186 "BMI SP_is_PSP \n" //; previous stack is PSP
187 "MRS R0, MSP \n" //; previous stack is MSP, read MSP
188 "B SP_Read_Ready \n"
189 );
190
191 while(1);
192}
193
194# else
195
206__asm int32_t HardFault_Handler(void)
207{
208 MOV R0, LR
209 LSLS R0, #29 //; Check bit 2
210 BMI SP_is_PSP //; previous stack is PSP
211 MRS R0, MSP //; previous stack is MSP, read MSP
212 B SP_Read_Ready
213SP_is_PSP
214 MRS R0, PSP //; Read PSP
215
216SP_Read_Ready
217 LDR R1, [R0, #24] //; Get previous PC
218 LDRH R3, [R1] //; Get instruction
219 LDR R2, =0xBEAB //; The special BKPT instruction
220 CMP R3, R2 //; Test if the instruction at previous PC is BKPT
221 BNE HardFault_Handler_Ret //; Not BKPT
222
223 ADDS R1, #4 //; Skip BKPT and next line
224 STR R1, [R0, #24] //; Save previous PC
225
226 BX LR //; Return
227HardFault_Handler_Ret
228
229 /* TODO: Implement your own hard fault handler here. */
230 MOVS r0, #4
231 MOV r1, LR
232 TST r0, r1
233 BEQ Stack_Use_MSP
234 MRS R0, PSP ;stack use PSP
235 B Get_LR_and_Branch
236Stack_Use_MSP
237 MRS R0, MSP ; stack use MSP
238Get_LR_and_Branch
239 MOV R1, LR ; LR current value
240 LDR R2,=__cpp(Hard_Fault_Handler)
241 BX R2
242
243 B .
244
245 ALIGN
246}
247
258__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
259{
260 BKPT 0xAB //; Wait ICE or HardFault
261 //; ICE will step over BKPT directly
262 //; HardFault will step BKPT and the next line
263 B SH_ICE
264
265SH_HardFault //; Captured by HardFault
266 MOVS R0, #0 //; Set return value to 0
267 BX lr //; Return
268
269SH_ICE //; Captured by ICE
270 //; Save return value
271 CMP R2, #0
272 BEQ SH_End
273 STR R0, [R2] //; Save the return value to *pn32Out_R0
274
275SH_End
276 MOVS R0, #1 //; Set return value to 1
277 BX lr //; Return
278}
279#endif
280
281#else
282
283/* Make sure won't goes here only because --gnu is defined , so
284 add !__CC_ARM and !__ICCARM__ checking */
285# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
286
297void HardFault_Handler(void)
298{
299 asm("MOVS r0, #4 \n"
300 "MOV r1, LR \n"
301 "TST r0, r1 \n" /*; check LR bit 2 */
302 "BEQ 1f \n" /*; stack use MSP */
303 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
304 "MOV R1, LR \n" /*; LR current value */
305 "B Hard_Fault_Handler \n"
306 "1: \n"
307 "MRS R0, MSP \n" /*; LR current value */
308 "B Hard_Fault_Handler \n"
309 ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
310 );
311 while(1);
312}
313
314# elif defined(__ICCARM__)
315
316void Get_LR_and_Branch(void)
317{
318 asm("MOV R1, LR \n" //; LR current value
319 "B Hard_Fault_Handler \n"
320 );
321}
322
323void Stack_Use_MSP(void)
324{
325 asm("MRS R0, MSP \n" //; stack use MSP
326 "B Get_LR_and_Branch \n"
327 );
328}
329
340void HardFault_Handler(void)
341{
342 asm("MOVS r0, #4 \n"
343 "MOV r1, LR \n"
344 "TST r0, r1 \n"
345 "BEQ Stack_Use_MSP \n"
346 "MRS R0, PSP \n" //; stack use PSP
347 "B Get_LR_and_Branch \n"
348 );
349
350 while(1);
351}
352
353# else
354
365__asm int32_t HardFault_Handler(void)
366{
367 MOVS r0, #4
368 MOV r1, LR
369 TST r0, r1
370 BEQ Stack_Use_MSP
371 MRS R0, PSP ;stack use PSP
372 B Get_LR_and_Branch
373Stack_Use_MSP
374 MRS R0, MSP ; stack use MSP
375Get_LR_and_Branch
376 MOV R1, LR ; LR current value
377 LDR R2,=__cpp(Hard_Fault_Handler)
378 BX R2
379}
380
381#endif
382
383#endif
384
385#define DEBUG_PORT UART0
386
392void SendChar_ToUART(int ch)
393{
394#ifndef DISABLE_UART
395 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)); //waits for TXFULL bit is clear
396 DEBUG_PORT->DAT = ch;
397 if(ch == '\n') {
398 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)); //waits for TXFULL bit is clear
399 DEBUG_PORT->DAT = '\r';
400 }
401#endif
402}
403
409void SendChar(int ch)
410{
411#if defined(DEBUG_ENABLE_SEMIHOST)
412 g_buf[g_buf_len++] = ch;
413 g_buf[g_buf_len] = '\0';
414 if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0') {
415
416 /* Send the char */
417 if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0) {
418 g_buf_len = 0;
419 return;
420 } else {
421 int i;
422
423 for(i=0; i<g_buf_len; i++)
424 SendChar_ToUART(g_buf[i]);
425 g_buf_len = 0;
426 }
427 }
428#else
429 SendChar_ToUART(ch);
430#endif
431}
432
439char GetChar(void)
440{
441#if defined(DEBUG_ENABLE_SEMIHOST)
442# if defined ( __CC_ARM )
443 int nRet;
444 while(SH_DoCommand(0x101, 0, &nRet) != 0) {
445 if(nRet != 0) {
446 SH_DoCommand(0x07, 0, &nRet);
447 return (char)nRet;
448 }
449 }
450# else
451 int nRet;
452 while(SH_DoCommand(0x7, 0, &nRet) != 0) {
453 if(nRet != 0)
454 return (char)nRet;
455 }
456# endif
457#endif
458
459#ifndef DISABLE_UART
460 while (1) {
461 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0 ) {
462 return (DEBUG_PORT->DAT);
463
464 }
465 }
466#else
467 return(0);
468#endif
469}
470
471
479int kbhit(void)
480{
481#ifndef DISABLE_UART
482 return !(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXFULL_Msk);
483#else
484 return(0);
485#endif
486}
487
496{
497#ifndef DISABLE_UART
498 return (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk);
499#else
500 return(1);
501#endif
502}
503
511void _ttywrch(int ch)
512{
513 SendChar(ch);
514 return;
515}
516
517#if defined ( __GNUC__ )
518
519int _write (int fd, char *ptr, int len)
520{
521 int i = len;
522
523 while(i--) {
524 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
525
526 DEBUG_PORT->DAT = *ptr++;
527
528 if(*ptr == '\n') {
529 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
530 DEBUG_PORT->DAT = '\r';
531 }
532 }
533 return len;
534}
535
536int _read (int fd, char *ptr, int len)
537{
538
539 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
540 *ptr = DEBUG_PORT->DAT;
541 return 1;
542
543
544}
545
546#else
559int fputc(int ch, FILE *stream)
560{
561 SendChar(ch);
562 return ch;
563}
564
572int fgetc(FILE *stream)
573{
574 return (GetChar());
575}
576
586int ferror(FILE *stream)
587{
588 return EOF;
589}
590#endif
591#ifdef DEBUG_ENABLE_SEMIHOST
592# ifdef __ICCARM__
593void __exit(int return_code)
594{
595
596 /* Check if link with ICE */
597 if(SH_DoCommand(0x18, 0x20026, NULL) == 0) {
598 /* Make sure all message is print out */
599 while(IsDebugFifoEmpty() == 0);
600 }
601label:
602 goto label; /* endless loop */
603}
604# else
605void _sys_exit(int return_code)
606{
607
608 /* Check if link with ICE */
609 if(SH_DoCommand(0x18, 0x20026, NULL) == 0) {
610 /* Make sure all message is print out */
611 while(IsDebugFifoEmpty() == 0);
612 }
613label:
614 goto label; /* endless loop */
615}
616# endif
617#endif
618
619/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define UART_FIFOSTS_TXFULL_Msk
Definition: NUC472_442.h:25935
#define UART_FIFOSTS_RXFULL_Msk
Definition: NUC472_442.h:25926
#define UART_FIFOSTS_TXEMPTYF_Msk
Definition: NUC472_442.h:25941
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: NUC472_442.h:25923
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:511
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:365
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:559
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:586
int IsDebugFifoEmpty(void)
Check whether UART transmit FIFO is empty or not.
Definition: retarget.c:495
void SendChar_ToUART(int ch)
Write a char to UART.
Definition: retarget.c:392
int kbhit(void)
Check whether UART receive FIFO is empty or not.
Definition: retarget.c:479
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:572
FILE __stdin
Definition: retarget.c:39
void Hard_Fault_Handler(uint32_t stack[])
Hard fault handler.
Definition: retarget.c:66
void SendChar(int ch)
Write a char to debug console.
Definition: retarget.c:409
FILE __stdout
Definition: retarget.c:38
char GetChar(void)
Read a char from debug console.
Definition: retarget.c:439
#define DEBUG_PORT
Definition: retarget.c:385
@ pc
Definition: retarget.c:41
@ r0
Definition: retarget.c:41
@ r2
Definition: retarget.c:41
@ lr
Definition: retarget.c:41
@ r3
Definition: retarget.c:41
@ r1
Definition: retarget.c:41
@ r12
Definition: retarget.c:41
@ psr
Definition: retarget.c:41
static void stackDump(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:48
return value
Definition: semihosting.h:98