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