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