Mini51 BSP  V3.02.002
The Board Support Package for Mini51 Series
retarget.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include <stdio.h>
13 #include "Mini51Series.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 
36 #if !(defined(__ICCARM__) && (__VER__ >= 6010000))
37 struct __FILE { int handle; /* Add whatever you need here */ };
38 #endif
39 FILE __stdout;
40 FILE __stdin;
41 
42 enum { r0, r1, r2, r3, r12, lr, pc, psr};
43 
44 void stackDump(uint32_t stack[])
45 {
46  printf("r0 = 0x%x\n", stack[r0]);
47  printf("r1 = 0x%x\n", stack[r1]);
48  printf("r2 = 0x%x\n", stack[r2]);
49  printf("r3 = 0x%x\n", stack[r3]);
50  printf("r12 = 0x%x\n", stack[r12]);
51  printf("lr = 0x%x\n", stack[lr]);
52  printf("pc = 0x%x\n", stack[pc]);
53  printf("psr = 0x%x\n", stack[psr]);
54 }
55 
56 void Hard_Fault_Handler(uint32_t stack[])
57 {
58  printf("In Hard Fault Handler\n");
59 
60  stackDump(stack);
61 
62  //Chip Reset
63  //SYS_UnlockReg();
64  //SYS->IPRSTC1 |= SYS_IPRSTC1_CHIP_RST_Msk;
65 
66  while(1);
67 }
68 
69 
70 #if defined(DEBUG_ENABLE_SEMIHOST)
71 /* The static buffer is used to speed up the semihost */
72 static char g_buf[16];
73 static char g_buf_len = 0;
74 
75 /* Make sure won't goes here only because --gnu is defined , so
76  add !__CC_ARM and !__ICCARM__ checking */
77 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
78 
79 # elif defined(__ICCARM__)
80 
81 
92 void HardFault_Handler(void)
93 {
94  asm("MOV R0, lr \n"
95  "LSLS R0, #29 \n" //; Check bit 2
96  "BMI SP_is_PSP \n" //; previous stack is PSP
97  "MRS R0, MSP \n" //; previous stack is MSP, read MSP
98  "B SP_Read_Ready \n"
99  "SP_is_PSP: \n"
100  "MRS R0, PSP \n" //; Read PSP
101  "SP_Read_Ready: \n"
102  "LDR R1, [R0, #24] \n" //; Get previous PC
103  "LDRH R3, [R1] \n" //; Get instruction
104  "LDR R2, [pc, #8] \n" //; The sepcial BKPT instruction
105  "CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
106  "BNE HardFault_Handler_Ret\n" //; Not BKPT
107  "ADDS R1, #4 \n" //; Skip BKPT and next line
108  "STR R1, [R0, #24] \n" //; Save previous PC
109  "BX lr \n" //; Return
110  "DCD 0xBEAB \n" //; BKPT instruction code
111  "HardFault_Handler_Ret:\n"
112  "MOVS r0, #4 \n"
113  "MOV r1, LR \n"
114  "TST r0, r1 \n"
115  "BEQ Stack_Use_MSP \n"
116  "MRS R0, PSP \n" //; stack use PSP
117  "B Get_LR_and_Branch \n"
118  "Stack_Use_MSP: \n"
119  "MRS R0, MSP \n" //; stack use MSP
120  "Get_LR_and_Branch: \n"
121  "MOV R1, LR \n" //; LR current value
122  "B Hard_Fault_Handler \n"
123  );
124 
125  while(1);
126 }
127 
138 int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
139 {
140  asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
141  "B SH_ICE \n"
142  "SH_HardFault: \n" //; Captured by HardFault
143  "MOVS R0, #0 \n" //; Set return value to 0
144  "BX lr \n" //; Return
145  "SH_ICE: \n" //; Captured by ICE
146  "CMP R2, #0 \n"
147  "BEQ SH_End \n"
148  "STR R0, [R2]\n" //; Save the return value to *pn32Out_R0
149  "SH_End: \n");
150 
151  return 1; //; Return 1 when it is trap by ICE
152 
153 }
154 
155 
156 # else
157 
168 __asm int32_t HardFault_Handler(void)
169 {
170 
171  MOV R0, LR
172  LSLS R0, #29 //; Check bit 2
173  BMI SP_is_PSP //; previous stack is PSP
174  MRS R0, MSP //; previous stack is MSP, read MSP
175  B SP_Read_Ready
176 SP_is_PSP
177  MRS R0, PSP //; Read PSP
178 
179 SP_Read_Ready
180  LDR R1, [R0, #24] //; Get previous PC
181  LDRH R3, [R1] //; Get instruction
182  LDR R2, =0xBEAB //; The sepcial BKPT instruction
183  CMP R3, R2 //; Test if the instruction at previous PC is BKPT
184  BNE HardFault_Handler_Ret //; Not BKPT
185 
186  ADDS R1, #4 //; Skip BKPT and next line
187  STR R1, [R0, #24] //; Save previous PC
188 
189  BX LR //; Return
190 HardFault_Handler_Ret
191 
192  /* TODO: Implement your own hard fault handler here. */
193  MOVS r0, #4
194  MOV r1, LR
195  TST r0, r1
196  BEQ Stack_Use_MSP
197  MRS R0, PSP ;stack use PSP
198  B Get_LR_and_Branch
199 Stack_Use_MSP
200  MRS R0, MSP ; stack use MSP
201 Get_LR_and_Branch
202  MOV R1, LR ; LR current value
203  LDR R2,=__cpp(Hard_Fault_Handler)
204  BX R2
205 
206  B .
207 
208  ALIGN
209 }
210 
221 __asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
222 {
223  BKPT 0xAB //; Wait ICE or HardFault
224  //; ICE will step over BKPT directly
225  //; HardFault will step BKPT and the next line
226  B SH_ICE
227 
228 SH_HardFault //; Captured by HardFault
229  MOVS R0, #0 //; Set return value to 0
230  BX lr //; Return
231 
232 SH_ICE //; Captured by ICE
233  //; Save return value
234  CMP R2, #0
235  BEQ SH_End
236  STR R0, [R2] //; Save the return value to *pn32Out_R0
237 
238 SH_End
239  MOVS R0, #1 //; Set return value to 1
240  BX lr //; Return
241 }
242 #endif
243 
244 #else
245 
246 /* Make sure won't goes here only because --gnu is defined , so
247  add !__CC_ARM and !__ICCARM__ checking */
248 # if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
249 
260 void HardFault_Handler(void)
261 {
262  asm("MOVS r0, #4 \n"
263  "MOV r1, LR \n"
264  "TST r0, r1 \n" /*; check LR bit 2 */
265  "BEQ 1f \n" /*; stack use MSP */
266  "MRS R0, PSP \n" /*; stack use PSP, read PSP */
267  "MOV R1, LR \n" /*; LR current value */
268  "B Hard_Fault_Handler \n"
269  "1: \n"
270  "MRS R0, MSP \n" /*; LR current value */
271  "B Hard_Fault_Handler \n"
272  ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
273  );
274  while(1);
275 }
276 
277 # elif defined(__ICCARM__)
278 
289 void HardFault_Handler(void)
290 {
291  asm("MOVS r0, #4 \n"
292  "MOV r1, LR \n"
293  "TST r0, r1 \n"
294  "BEQ Stack_Use_MSP \n"
295  "MRS R0, PSP \n" //; stack use PSP
296  "B Get_LR_and_Branch \n"
297  "Stack_Use_MSP: \n"
298  "MRS R0, MSP \n" //; stack use MSP
299  "Get_LR_and_Branch: \n"
300  "MOV R1, LR \n" //; LR current value
301  "B Hard_Fault_Handler \n"
302  );
303 
304  while(1);
305 }
306 
307 # else
308 
319 __asm int32_t HardFault_Handler(void)
320 {
321  MOVS r0, #4
322  MOV r1, LR
323  TST r0, r1
324  BEQ Stack_Use_MSP
325  MRS R0, PSP ;stack use PSP
326  B Get_LR_and_Branch
327 Stack_Use_MSP
328  MRS R0, MSP ; stack use MSP
329 Get_LR_and_Branch
330  MOV R1, LR ; LR current value
331  LDR R2,=__cpp(Hard_Fault_Handler)
332  BX R2
333 }
334 
335 #endif
336 
337 #endif
338 
339 
346 void SendChar_ToUART(int ch)
347 {
348 #ifndef DISABLE_UART
349  while(UART->FSR & UART_FSR_TX_FULL_Msk);
350  UART->THR = ch;
351  if(ch == '\n')
352  {
353  while(UART->FSR & UART_FSR_TX_FULL_Msk);
354  UART->THR = '\r';
355  }
356 #endif
357 }
358 
359 
366 void SendChar(int ch)
367 {
368 #if defined(DEBUG_ENABLE_SEMIHOST)
369  g_buf[g_buf_len++] = ch;
370  g_buf[g_buf_len] = '\0';
371  if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
372  {
373 
374  /* Send the char */
375 
376  if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
377  {
378  g_buf_len = 0;
379  return;
380  }
381  else
382  {
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  {
410  if(nRet != 0)
411  {
412  SH_DoCommand(0x07, 0, &nRet);
413  return (char)nRet;
414  }
415  }
416 # else
417  int nRet;
418  while(SH_DoCommand(0x7, 0, &nRet) != 0)
419  {
420  if(nRet != 0)
421  return (char)nRet;
422  }
423 # endif
424 #endif
425 #ifndef DISABLE_UART
426  while (1){
427  if(!(UART->FSR & UART_FSR_RX_EMPTY_Msk))
428  {
429  return (UART->RBR);
430 
431  }
432  }
433 #else
434  return(0);
435 #endif
436 }
437 
438 
446 int kbhit(void)
447 {
448 #ifndef DISABLE_UART
449  return !(UART->FSR & UART_FSR_RX_EMPTY_Msk);
450 #else
451  return(0);
452 #endif
453 }
454 
463 {
464 #ifndef DISABLE_UART
465  return (UART->FSR & UART_FSR_TE_FLAG_Msk) ? 1 : 0;
466 #else
467  return(1);
468 #endif
469 
470 }
471 
472 /*---------------------------------------------------------------------------------------------------------*/
473 /* C library retargetting */
474 /*---------------------------------------------------------------------------------------------------------*/
475 void _ttywrch(int ch)
476 {
477  SendChar(ch);
478  return;
479 }
480 
481 int fputc(int ch, FILE *f)
482 {
483  SendChar(ch);
484  return ch;
485 }
486 #if defined (__GNUC__) && !defined(__ARMCC_VERSION)
487 
488 int _write (int fd, char *ptr, int len)
489 {
490  int i = len;
491 
492  while(i--)
493  {
494  while(UART->FSR & UART_FSR_TX_FULL_Msk);
495 
496  UART->THR = *ptr++;
497 
498  if(*ptr == '\n')
499  {
500  while(UART->FSR & UART_FSR_TX_FULL_Msk);
501  UART->THR = '\r';
502  }
503  }
504  return len;
505 }
506 
507 int _read (int fd, char *ptr, int len)
508 {
509 
510  while((UART->FSR & UART_FSR_RX_EMPTY_Msk) != 0);
511  *ptr = UART->RBR;
512  return 1;
513 
514 
515 }
516 
517 #else
518 int fgetc(FILE *f)
519 {
520  return (GetChar());
521 }
522 
523 
524 int ferror(FILE *f)
525 {
526  return EOF;
527 }
528 #endif
529 #ifdef DEBUG_ENABLE_SEMIHOST
530 # ifdef __ICCARM__
531 void __exit(int return_code) {
532 
533  /* Check if link with ICE */
534 
535  if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
536  {
537  /* Make sure all message is print out */
538 
539  while(IsDebugFifoEmpty() == 0);
540  }
541 label: goto label; /* endless loop */
542 }
543 # else
544 void _sys_exit(int return_code) {
545 
546  /* Check if link with ICE */
547  if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
548  {
549  /* Make sure all message is print out */
550  while(IsDebugFifoEmpty() == 0);
551  }
552 label: goto label; /* endless loop */
553 }
554 # endif
555 #endif
556 /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
557 
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:462
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:319
void _ttywrch(int ch)
Definition: retarget.c:475
Definition: retarget.c:42
void SendChar_ToUART(int ch)
Write a char to UART.
Definition: retarget.c:346
Mini51 series peripheral access layer header file. This file contains all the peripheral register's d...
int ferror(FILE *f)
Definition: retarget.c:524
Definition: retarget.c:42
void Hard_Fault_Handler(uint32_t stack[])
Definition: retarget.c:56
Definition: retarget.c:42
Definition: retarget.c:42
#define UART_FSR_TX_FULL_Msk
Definition: retarget.c:42
int kbhit(void)
Check whether UART receive FIFO is empty or not.
Definition: retarget.c:446
void SendChar(int ch)
Write a char to debug console.
Definition: retarget.c:366
int handle
Definition: retarget.c:37
#define UART
Pointer to UART register structure.
Definition: retarget.c:42
#define UART_FSR_RX_EMPTY_Msk
int fgetc(FILE *f)
Definition: retarget.c:518
void stackDump(uint32_t stack[])
Definition: retarget.c:44
FILE __stdout
Definition: retarget.c:39
#define UART_FSR_TE_FLAG_Msk
#define NULL
NULL pointer.
int fputc(int ch, FILE *f)
Definition: retarget.c:481
return value
Definition: semihosting.h:98
FILE __stdin
Definition: retarget.c:40
Definition: retarget.c:42
Definition: retarget.c:42