Nano102_112 Series BSP  V3.03.002
The Board Support Package for Nano102_112 Series
retarget.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include <stdio.h>
13 #include "Nano1X2Series.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 #ifndef DEBUG_PORT
24 #define DEBUG_PORT UART0
25 #endif
26 
27 /* Un-comment this line to disable all printf and getchar. getchar() will always return 0x00*/
28 //#define DISABLE_UART
29 
30 #if defined(DEBUG_ENABLE_SEMIHOST)
31 #ifndef DISABLE_UART
32 #define DISABLE_UART
33 #endif
34 #endif
35 
36 /*---------------------------------------------------------------------------------------------------------*/
37 /* Global variables */
38 /*---------------------------------------------------------------------------------------------------------*/
39 
40 #if !(defined(__ICCARM__) && (__VER__ >= 6010000))
41 struct __FILE
42 {
43  int handle; /* Add whatever you need here */
44 };
45 #endif
46 FILE __stdout;
47 FILE __stdin;
48 
49 enum { r0, r1, r2, r3, r12, lr, pc, psr};
50 
51 void stackDump(uint32_t stack[])
52 {
53  printf("r0 = 0x%x\n", stack[r0]);
54  printf("r1 = 0x%x\n", stack[r1]);
55  printf("r2 = 0x%x\n", stack[r2]);
56  printf("r3 = 0x%x\n", stack[r3]);
57  printf("r12 = 0x%x\n", stack[r12]);
58  printf("lr = 0x%x\n", stack[lr]);
59  printf("pc = 0x%x\n", stack[pc]);
60  printf("psr = 0x%x\n", stack[psr]);
61 }
62 
63 void Hard_Fault_Handler(uint32_t stack[])
64 {
65  printf("In Hard Fault Handler\n");
66 
67  stackDump(stack);
68 
69  //Chip Reset
70  //SYS_UnlockReg();
71  //SYS->IPRST_CTL1 |= SYS_IPRST_CTL1_CHIP_RST_Msk;
72 
73  while(1);
74 }
75 
76 
77 #if defined(DEBUG_ENABLE_SEMIHOST)
78 /* The static buffer is used to speed up the semihost */
79 static char g_buf[16];
80 static char g_buf_len = 0;
81 
82 /* Make sure won't goes here only because --gnu is defined , so
83  add !__CC_ARM and !__ICCARM__ checking */
84 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
85 
86 # elif defined(__ICCARM__)
87 
88 
99 void HardFault_Handler(void)
100 {
101  asm("MOV R0, lr \n"
102  "LSLS R0, #29 \n" //; Check bit 2
103  "BMI SP_is_PSP \n" //; previous stack is PSP
104  "MRS R0, MSP \n" //; previous stack is MSP, read MSP
105  "B SP_Read_Ready \n"
106  "SP_is_PSP: \n"
107  "MRS R0, PSP \n" //; Read PSP
108  "SP_Read_Ready: \n"
109  "LDR R1, [R0, #24] \n" //; Get previous PC
110  "LDRH R3, [R1] \n" //; Get instruction
111  "LDR R2, [pc, #8] \n" //; The sepcial BKPT instruction
112  "CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
113  "BNE HardFault_Handler_Ret\n" //; Not BKPT
114  "ADDS R1, #4 \n" //; Skip BKPT and next line
115  "STR R1, [R0, #24] \n" //; Save previous PC
116  "BX lr \n" //; Return
117  "DCD 0xBEAB \n" //; BKPT instruction code
118  "HardFault_Handler_Ret:\n"
119  "MOVS r0, #4 \n"
120  "MOV r1, LR \n"
121  "TST r0, r1 \n"
122  "BEQ Stack_Use_MSP \n"
123  "MRS R0, PSP \n" //; stack use PSP
124  "B Get_LR_and_Branch \n"
125  "Stack_Use_MSP: \n"
126  "MRS R0, MSP \n" //; stack use MSP
127  "Get_LR_and_Branch: \n"
128  "MOV R1, LR \n" //; LR current value
129  "B Hard_Fault_Handler \n"
130  );
131 
132  while(1);
133 }
134 
145 int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
146 {
147  asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
148  "B SH_ICE \n"
149  "SH_HardFault: \n" //; Captured by HardFault
150  "MOVS R0, #0 \n" //; Set return value to 0
151  "BX lr \n" //; Return
152  "SH_ICE: \n" //; Captured by ICE
153  "CMP R2, #0 \n"
154  "BEQ SH_End \n"
155  "STR R0, [R2]\n" //; Save the return value to *pn32Out_R0
156  "SH_End: \n");
157 
158  return 1; //; Return 1 when it is trap by ICE
159 
160 }
161 
162 
163 # else
164 
175 __asm int32_t HardFault_Handler(void)
176 {
177 
178  MOV R0, LR
179  LSLS R0, #29 //; Check bit 2
180  BMI SP_is_PSP //; previous stack is PSP
181  MRS R0, MSP //; previous stack is MSP, read MSP
182  B SP_Read_Ready
183 SP_is_PSP
184  MRS R0, PSP //; Read PSP
185 
186 SP_Read_Ready
187  LDR R1, [R0, #24] //; Get previous PC
188  LDRH R3, [R1] //; Get instruction
189  LDR R2, =0xBEAB //; The sepcial BKPT instruction
190  CMP R3, R2 //; Test if the instruction at previous PC is BKPT
191  BNE HardFault_Handler_Ret //; Not BKPT
192 
193  ADDS R1, #4 //; Skip BKPT and next line
194  STR R1, [R0, #24] //; Save previous PC
195 
196  BX LR //; Return
197 HardFault_Handler_Ret
198 
199  /* TODO: Implement your own hard fault handler here. */
200  MOVS r0, #4
201  MOV r1, LR
202  TST r0, r1
203  BEQ Stack_Use_MSP
204  MRS R0, PSP ; stack use PSP
205  B Get_LR_and_Branch
206 Stack_Use_MSP
207  MRS R0, MSP ; stack use MSP
208 Get_LR_and_Branch
209  MOV R1, LR ; LR current value
210  LDR R2,=__cpp(Hard_Fault_Handler)
211  BX R2
212 
213  B .
214 
215  ALIGN
216 }
217 
228 __asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
229 {
230  BKPT 0xAB //; Wait ICE or HardFault
231  //; ICE will step over BKPT directly
232  //; HardFault will step BKPT and the next line
233  B SH_ICE
234 
235 SH_HardFault //; Captured by HardFault
236  MOVS R0, #0 //; Set return value to 0
237  BX lr //; Return
238 
239 SH_ICE //; Captured by ICE
240  //; Save return value
241  CMP R2, #0
242  BEQ SH_End
243  STR R0, [R2] //; Save the return value to *pn32Out_R0
244 
245 SH_End
246  MOVS R0, #1 //; Set return value to 1
247  BX lr //; Return
248 }
249 #endif
250 
251 #else
252 
253 /* Make sure won't goes here only because --gnu is defined , so
254  add !__CC_ARM and !__ICCARM__ checking */
255 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
256 
267 void HardFault_Handler(void)
268 {
269  asm("MOVS r0, #4 \n"
270  "MOV r1, LR \n"
271  "TST r0, r1 \n" /*; check LR bit 2 */
272  "BEQ 1f \n" /*; stack use MSP */
273  "MRS R0, PSP \n" /*; stack use PSP, read PSP */
274  "MOV R1, LR \n" /*; LR current value */
275  "B Hard_Fault_Handler \n"
276  "1: \n"
277  "MRS R0, MSP \n" /*; LR current value */
278  "B Hard_Fault_Handler \n"
279  ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
280  );
281  while(1);
282 }
283 
284 # elif defined(__ICCARM__)
285 
296 void HardFault_Handler(void)
297 {
298  asm("MOVS r0, #4 \n"
299  "MOV r1, LR \n"
300  "TST r0, r1 \n"
301  "BEQ Stack_Use_MSP \n"
302  "MRS R0, PSP \n" //; stack use PSP
303  "B Get_LR_and_Branch \n"
304  "Stack_Use_MSP: \n"
305  "MRS R0, MSP \n" //; stack use MSP
306  "Get_LR_and_Branch: \n"
307  "MOV R1, LR \n" //; LR current value
308  "B Hard_Fault_Handler \n"
309  );
310 
311  while(1);
312 }
313 
314 # else
315 
326 __asm int32_t HardFault_Handler(void)
327 {
328  MOVS r0, #4
329  MOV r1, LR
330  TST r0, r1
331  BEQ Stack_Use_MSP
332  MRS R0, PSP ;stack use PSP
333  B Get_LR_and_Branch
334 Stack_Use_MSP
335  MRS R0, MSP ;stack use MSP
336 Get_LR_and_Branch
337  MOV R1, LR ;LR current value
338  LDR R2,=__cpp(Hard_Fault_Handler)
339  BX R2
340 }
341 
342 #endif
343 
344 #endif
345 
346 
353 void SendChar_ToUART(int ch)
354 {
355 #ifndef DISABLE_UART
356  while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_F_Msk);
357  DEBUG_PORT->THR = ch;
358  if(ch == '\n')
359  {
360  while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_F_Msk);
361  DEBUG_PORT->THR = '\r';
362  }
363 #endif
364 }
365 
366 
373 void SendChar(int ch)
374 {
375 #if defined(DEBUG_ENABLE_SEMIHOST)
376  g_buf[g_buf_len++] = ch;
377  g_buf[g_buf_len] = '\0';
378  if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
379  {
380 
381  /* Send the char */
382 
383  if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
384  {
385  g_buf_len = 0;
386  return;
387  }
388  else
389  {
390  int i;
391 
392  for(i=0; i<g_buf_len; i++)
393  SendChar_ToUART(g_buf[i]);
394  g_buf_len = 0;
395  }
396  }
397 #else
398  SendChar_ToUART(ch);
399 #endif
400 }
401 
402 
410 char GetChar(void)
411 {
412 #if defined(DEBUG_ENABLE_SEMIHOST)
413 # if defined ( __CC_ARM )
414  int nRet;
415  while(SH_DoCommand(0x101, 0, &nRet) != 0)
416  {
417  if(nRet != 0)
418  {
419  SH_DoCommand(0x07, 0, &nRet);
420  return (char)nRet;
421  }
422  }
423 # else
424  int nRet;
425  while(SH_DoCommand(0x7, 0, &nRet) != 0)
426  {
427  if(nRet != 0)
428  return (char)nRet;
429  }
430 # endif
431 #endif
432 #ifndef DISABLE_UART
433  while (1)
434  {
435  if(!(DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_F_Msk))
436  {
437  return (DEBUG_PORT->RBR);
438 
439  }
440  }
441 #else
442  return(0);
443 #endif
444 }
445 
446 
454 int kbhit(void)
455 {
456 #ifndef DISABLE_UART
457  return !(DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_F_Msk);
458 #else
459  return(0);
460 #endif
461 }
462 
471 {
472 #ifndef DISABLE_UART
473  return (DEBUG_PORT->FSR & UART_FSR_TE_F_Msk) ? 1 : 0;
474 #else
475  return(1);
476 #endif
477 
478 }
479 
480 /*---------------------------------------------------------------------------------------------------------*/
481 /* C library retargetting */
482 /*---------------------------------------------------------------------------------------------------------*/
483 void _ttywrch(int ch)
484 {
485  SendChar(ch);
486  return;
487 }
488 
489 int fputc(int ch, FILE *f)
490 {
491  SendChar(ch);
492  return ch;
493 }
494 
495 #if defined (__GNUC__) && !defined(__ARMCC_VERSION)
496 
497 int _write (int fd, char *ptr, int len)
498 {
499  int i = len;
500 
501  while(i--)
502  {
503  while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_F_Msk);
504 
505  DEBUG_PORT->THR = *ptr++;
506 
507  if(*ptr == '\n')
508  {
509  while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_F_Msk);
510  DEBUG_PORT->THR = '\r';
511  }
512  }
513  return len;
514 }
515 
516 int _read (int fd, char *ptr, int len)
517 {
518 
519  while((DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_F_Msk) != 0);
520  *ptr = DEBUG_PORT->RBR;
521  return 1;
522 
523 
524 }
525 
526 #else
527 int fgetc(FILE *f)
528 {
529  return (GetChar());
530 }
531 
532 
533 int ferror(FILE *f)
534 {
535  return EOF;
536 }
537 #endif
538 
539 #ifdef DEBUG_ENABLE_SEMIHOST
540 # ifdef __ICCARM__
541 void __exit(int return_code)
542 {
543 
544  /* Check if link with ICE */
545 
546  if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
547  {
548  /* Make sure all message is print out */
549 
550  while(IsDebugFifoEmpty() == 0);
551  }
552 label:
553  goto label; /* endless loop */
554 }
555 # else
556 void _sys_exit(int return_code)
557 {
558 
559  /* Check if link with ICE */
560  if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
561  {
562  /* Make sure all message is print out */
563  while(IsDebugFifoEmpty() == 0);
564  }
565 label:
566  goto label; /* endless loop */
567 }
568 # endif
569 #endif
570 /*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
571 
char GetChar(void)
Read a char from debug console.
Definition: retarget.c:410
int IsDebugFifoEmpty(void)
Check whether UART transmit FIFO is empty or not.
Definition: retarget.c:470
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:326
void _ttywrch(int ch)
Definition: retarget.c:483
#define DEBUG_PORT
Definition: retarget.c:24
Definition: retarget.c:49
void SendChar_ToUART(int ch)
Write a char to UART.
Definition: retarget.c:353
#define UART_FSR_TE_F_Msk
int ferror(FILE *f)
Definition: retarget.c:533
void Hard_Fault_Handler(uint32_t stack[])
Definition: retarget.c:63
Definition: retarget.c:49
#define NULL
NULL pointer.
int kbhit(void)
Check whether UART receive FIFO is empty or not.
Definition: retarget.c:454
Nano102/112 peripheral access layer header file. This file contains all the peripheral register's def...
Definition: retarget.c:49
Definition: retarget.c:49
void SendChar(int ch)
Write a char to debug console.
Definition: retarget.c:373
int handle
Definition: retarget.c:43
Definition: retarget.c:49
int fgetc(FILE *f)
Definition: retarget.c:527
Definition: retarget.c:49
#define UART_FSR_TX_FULL_F_Msk
void stackDump(uint32_t stack[])
Definition: retarget.c:51
#define UART_FSR_RX_EMPTY_F_Msk
FILE __stdout
Definition: retarget.c:46
int fputc(int ch, FILE *f)
Definition: retarget.c:489
Definition: retarget.c:49
return value
Definition: semihosting.h:98
Definition: retarget.c:49
FILE __stdin
Definition: retarget.c:47