M480 BSP V3.05.005
The Board Support Package for M480 Series
retarget.c
Go to the documentation of this file.
1/**************************************************************************/
11#include <stdio.h>
12#include "NuMicro.h"
13
14#if defined ( __CC_ARM )
15#if (__ARMCC_VERSION < 400000)
16#else
17/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
18#pragma import _printf_widthprec
19#endif
20#endif
21/* Uncomment this line to disable all printf and getchar. getchar() will always return 0x00*/
22/* #define DISABLE_UART */
23
24#if defined(DEBUG_ENABLE_SEMIHOST)
25 #ifndef DISABLE_UART
26 #define DISABLE_UART
27 #endif
28#endif
29
30#define DEBUG_PORT UART0
31/*---------------------------------------------------------------------------------------------------------*/
32/* Global variables */
33/*---------------------------------------------------------------------------------------------------------*/
34#if (defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 6040000)) || (defined(__ICCARM__) && (__VER__ >= 8000000))
35struct __FILE { int handle; /* Add whatever you need here */ };
36#endif
39
40
41enum { r0, r1, r2, r3, r12, lr, pc, psr};
42
49static void stackDump(uint32_t stack[])
50{
51 printf("r0 = 0x%x\n", stack[r0]);
52 printf("r1 = 0x%x\n", stack[r1]);
53 printf("r2 = 0x%x\n", stack[r2]);
54 printf("r3 = 0x%x\n", stack[r3]);
55 printf("r12 = 0x%x\n", stack[r12]);
56 printf("lr = 0x%x\n", stack[lr]);
57 printf("pc = 0x%x\n", stack[pc]);
58 printf("psr = 0x%x\n", stack[psr]);
59}
60
67void Hard_Fault_Handler(uint32_t stack[])
68{
69 printf("In Hard Fault Handler\n");
70
71 stackDump(stack);
72 /* Replace while(1) with chip reset if WDT is not enabled for end product */
73 while(1);
74 /* SYS->IPRST0 = SYS_IPRST0_CHIPRST_Msk; */
75}
76
77
78
79/*---------------------------------------------------------------------------------------------------------*/
80/* Routine to write a char */
81/*---------------------------------------------------------------------------------------------------------*/
82
83#if defined(DEBUG_ENABLE_SEMIHOST)
84/* The static buffer is used to speed up the semihost */
85static char g_buf[16];
86static char g_buf_len = 0;
87
88/* Make sure won't goes here only because --gnu is defined , so
89 add !__CC_ARM and !__ICCARM__ checking */
90# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
91
92# elif defined(__ICCARM__) // IAR
93
94void SH_End(void)
95{
96 asm("MOVS R0,#1 \n" /*; Set return value to 1 */
97 "BX lr \n" /*; Return */
98 );
99}
100
101void SH_ICE(void)
102{
103 asm("CMP R2,#0 \n"
104 "BEQ SH_End \n"
105 "STR R0,[R2] \n" /*; Save the return value to *pn32Out_R0 */
106 );
107}
108
119int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
120{
121 asm("BKPT 0xAB \n" /*; This instruction will cause ICE trap or system HardFault */
122 "B SH_ICE \n"
123 "SH_HardFault: \n" /*; Captured by HardFault */
124 "MOVS R0,#0 \n" /*; Set return value to 0 */
125 "BX lr \n" /*; Return */
126 );
127
128 return 1; /*; Return 1 when it is trap by ICE */
129}
130
137void Get_LR_and_Branch(void)
138{
139 asm("MOV R1, LR \n" /*; LR current value */
140 "B Hard_Fault_Handler \n"
141 );
142}
143
150void Stack_Use_MSP(void)
151{
152 asm("MRS R0, MSP \n" /*; read MSP */
153 "B Get_LR_and_Branch \n"
154 );
155}
156
163void HardFault_Handler_Ret(void)
164{
165 asm("MOVS r0, #4 \n"
166 "MOV r1, LR \n"
167 "TST r0, r1 \n" /*; check LR bit 2 */
168 "BEQ Stack_Use_MSP \n" /*; stack use MSP */
169 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
170 "B Get_LR_and_Branch \n"
171 );
172}
173
181void SP_Read_Ready(void)
182{
183 asm("LDR R1, [R0, #24] \n" /*; Get previous PC */
184 "LDRH R3, [R1] \n" /*; Get instruction */
185 "LDR R2, [pc, #8] \n" /*; The special BKPT instruction */
186 "CMP R3, R2 \n" /*; Test if the instruction at previous PC is BKPT */
187 "BNE HardFault_Handler_Ret \n" /*; Not BKPT */
188 "ADDS R1, #4 \n" /*; Skip BKPT and next line */
189 "STR R1, [R0, #24] \n" /*; Save previous PC */
190 "BX lr \n" /*; Return */
191 "DCD 0xBEAB \n" /*; BKPT instruction code */
192 "B HardFault_Handler_Ret \n"
193 );
194}
195
202void SP_is_PSP(void)
203{
204 asm(
205 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
206 "B Get_LR_and_Branch \n"
207
208 );
209}
210
221void HardFault_Handler (void)
222{
223 asm("MOV R0, lr \n"
224 "LSLS R0, #29 \n" /*; Check bit 2 */
225 "BMI SP_is_PSP \n" /*; previous stack is PSP */
226 "MRS R0, MSP \n" /*; previous stack is MSP, read MSP */
227 "B SP_Read_Ready \n"
228 );
229
230 while(1);
231}
232
233# else
234
242__asm int32_t HardFault_Handler(void)
243{
244 MOV R0, LR
245 LSLS R0, #29 /*; Check bit 2 */
246 BMI SP_is_PSP /*; previous stack is PSP */
247 MRS R0, MSP /*; previous stack is MSP, read MSP */
248 B SP_Read_Ready
249SP_is_PSP
250 MRS R0, PSP /*; Read PSP */
251
252SP_Read_Ready
253 LDR R1, [R0, #24] /*; Get previous PC */
254 LDRH R3, [R1] /*; Get instruction */
255 LDR R2, =0xBEAB /*; The special BKPT instruction */
256 CMP R3, R2 /*; Test if the instruction at previous PC is BKPT */
257 BNE HardFault_Handler_Ret /*; Not BKPT */
258
259 ADDS R1, #4 /*; Skip BKPT and next line */
260 STR R1, [R0, #24] /*; Save previous PC */
261
262 BX LR /*; Return */
263HardFault_Handler_Ret
264
265 /* TODO: Implement your own hard fault handler here. */
266 MOVS r0, #4
267 MOV r1, LR
268 TST r0, r1 /*; check LR bit 2 */
269 BEQ Stack_Use_MSP /*; stack use MSP */
270 MRS R0, PSP ;stack use PSP /*; stack use PSP, read PSP */
271 B Get_LR_and_Branch
272Stack_Use_MSP
273 MRS R0, MSP ; stack use MSP /*; read MSP */
274Get_LR_and_Branch
275 MOV R1, LR ; LR current value /*; LR current value */
276 LDR R2,=__cpp(Hard_Fault_Handler) /*; branch to Hard_Fault_Handler */
277 BX R2
278
279 B .
280
281 ALIGN
282}
283
294__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
295{
296 BKPT 0xAB /*; Wait ICE or HardFault */
297 /*; ICE will step over BKPT directly
298 ; HardFault will step BKPT and the next line */
299 B SH_ICE
300
301SH_HardFault /*; Captured by HardFault */
302 MOVS R0, #0 /*; Set return value to 0 */
303 BX lr /*; Return */
304
305SH_ICE /*; Captured by ICE */
306 /*; Save return value */
307 CMP R2, #0
308 BEQ SH_End
309 STR R0, [R2] /*; Save the return value to *pn32Out_R0 */
310
311SH_End
312 MOVS R0, #1 /*; Set return value to 1 */
313 BX lr /*; Return */
314}
315#endif
316
317#else // ndef DEBUG_ENABLE_SEMIHOST
318
319/* Make sure won't goes here only because --gnu is defined , so
320 add !__CC_ARM and !__ICCARM__ checking */
321# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
322
333void HardFault_Handler(void)
334{
335 asm("MOVS r0, #4 \n"
336 "MOV r1, LR \n"
337 "TST r0, r1 \n" /*; check LR bit 2 */
338 "BEQ 1f \n" /*; stack use MSP */
339 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
340 "MOV R1, LR \n" /*; LR current value */
341 "B Hard_Fault_Handler \n"
342 "1: \n"
343 "MRS R0, MSP \n" /*; LR current value */
344 "B Hard_Fault_Handler \n"
345 ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
346 );
347 while(1);
348}
349
350# elif defined(__ICCARM__)
351
352void Get_LR_and_Branch(void)
353{
354 asm("MOV R1, LR \n" /*; LR current value */
355 "B Hard_Fault_Handler \n"
356 );
357}
358
359void Stack_Use_MSP(void)
360{
361 asm("MRS R0, MSP \n" /*; read MSP */
362 "B Get_LR_and_Branch \n"
363 );
364}
365
376void HardFault_Handler(void)
377{
378 asm("MOVS r0, #4 \n"
379 "MOV r1, LR \n"
380 "TST r0, r1 \n" /*; check LR bit 2 */
381 "BEQ Stack_Use_MSP \n" /*; stack use MSP */
382 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
383 "B Get_LR_and_Branch \n"
384 );
385
386 while(1);
387}
388
389# else
390
401__asm int32_t HardFault_Handler(void)
402{
403 MOVS r0, #4
404 MOV r1, LR
405 TST r0, r1 /*; check LR bit 2 */
406 BEQ Stack_Use_MSP /*; stack use MSP */
407 MRS R0, PSP /*; stack use PSP, read PSP */
408 B Get_LR_and_Branch
409Stack_Use_MSP
410 MRS R0, MSP /*; read MSP */
411Get_LR_and_Branch
412 MOV R1, LR /*; LR current value */
413 LDR R2,=__cpp(Hard_Fault_Handler) /*; branch to Hard_Fault_Handler */
414 BX R2
415}
416
417#endif
418
419#endif
420
421#ifndef DISABLE_UART
431#ifndef NONBLOCK_PRINTF
432static void SendChar_ToUART(int ch)
433{
434 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
435
436 if(ch == '\n')
437 {
438 DEBUG_PORT->DAT = '\r';
439 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
440 }
441 DEBUG_PORT->DAT = ch;
442}
443
444#else
445/* Non-block implement of send char */
446#define BUF_SIZE 2048
447static void SendChar_ToUART(int ch)
448{
449 static uint8_t u8Buf[BUF_SIZE] = {0};
450 static int32_t i32Head = 0;
451 static int32_t i32Tail = 0;
452 int32_t i32Tmp;
453
454 /* Only flush the data in buffer to UART when ch == 0 */
455 if(ch)
456 {
457 /* Push char */
458 if(ch == '\n')
459 {
460 i32Tmp = i32Head+1;
461 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
462 if(i32Tmp != i32Tail)
463 {
464 u8Buf[i32Head] = '\r';
465 i32Head = i32Tmp;
466 }
467 }
468
469 i32Tmp = i32Head+1;
470 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
471 if(i32Tmp != i32Tail)
472 {
473 u8Buf[i32Head] = ch;
474 i32Head = i32Tmp;
475 }
476 }
477 else
478 {
479 if(i32Tail == i32Head)
480 return;
481 }
482
483 /* pop char */
484 do
485 {
486 i32Tmp = i32Tail + 1;
487 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
488
489 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
490 {
491 DEBUG_PORT->DAT = u8Buf[i32Tail];
492 i32Tail = i32Tmp;
493 }
494 else
495 break; /* FIFO full */
496 }while(i32Tail != i32Head);
497}
498#endif /* else for NONBLOCK_PRINTF */
499
500#endif /* if not def DISABLE_UART */
501
511static void SendChar(int ch)
512{
513#if defined(DEBUG_ENABLE_SEMIHOST)
514 g_buf[g_buf_len++] = ch;
515 g_buf[g_buf_len] = '\0';
516 if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
517 {
518 /* Send the char */
519 if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
520 {
521 g_buf_len = 0;
522 return;
523 }
524 else
525 {
526#ifndef DISABLE_UART
527 int i;
528
529 for(i = 0; i < g_buf_len; i++)
530 SendChar_ToUART(g_buf[i]);
531#endif
532 g_buf_len = 0;
533 }
534 }
535#else
536#ifndef DISABLE_UART
537 SendChar_ToUART(ch);
538#endif
539#endif
540}
541
551static char GetChar(void)
552{
553#ifdef DEBUG_ENABLE_SEMIHOST
554# if defined (__CC_ARM)
555 int nRet;
556 while(SH_DoCommand(0x101, 0, &nRet) != 0)
557 {
558 if(nRet != 0)
559 {
560 SH_DoCommand(0x07, 0, &nRet);
561 return (char)nRet;
562 }
563 }
564# else
565 int nRet;
566 while(SH_DoCommand(0x7, 0, &nRet) != 0)
567 {
568 if(nRet != 0)
569 return (char)nRet;
570 }
571# endif
572 return (0);
573#else
574#ifndef DISABLE_UART
575 while(1)
576 {
577 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
578 {
579 return (DEBUG_PORT->DAT);
580 }
581 }
582#else
583 return 0;
584#endif
585#endif
586}
587
599int kbhit(void)
600{
601#ifndef DISABLE_UART
602 return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0);
603#else
604 return 0;
605#endif
606}
619{
620#ifndef DISABLE_UART
621 return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) != 0);
622#else
623 return 1;
624#endif
625}
626
637void _ttywrch(int ch)
638{
639 SendChar(ch);
640 return;
641}
642
643
662int fputc(int ch, FILE *stream)
663{
664 SendChar(ch);
665 return ch;
666}
667
668#if defined (__GNUC__) && !defined(__ARMCC_VERSION)
669
670int _write (int fd, char *ptr, int len)
671{
672 int i = len;
673
674 while(i--)
675 {
676 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
677
678 if(*ptr == '\n')
679 {
680 DEBUG_PORT->DAT = '\r';
681 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
682 }
683
684 DEBUG_PORT->DAT = *ptr++;
685
686 }
687 return len;
688}
689
690int _read (int fd, char *ptr, int len)
691{
692
693 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
694 *ptr = DEBUG_PORT->DAT;
695 return 1;
696
697
698}
699
700#else
712int fgetc(FILE *stream)
713{
714 return (GetChar());
715}
716
732int ferror(FILE *stream)
733{
734 return EOF;
735}
736#endif
737#ifdef DEBUG_ENABLE_SEMIHOST
738# ifdef __ICCARM__
739void __exit(int return_code)
740{
741
742 /* Check if link with ICE */
743 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
744 {
745 /* Make sure all message is print out */
746 while(IsDebugFifoEmpty() == 0);
747 }
748label:
749 goto label; /* endless loop */
750}
751# else
752void _sys_exit(int return_code)
753{
754
755 /* Check if link with ICE */
756 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
757 {
758 /* Make sure all message is print out */
759 while(IsDebugFifoEmpty() == 0);
760 }
761label:
762 goto label; /* endless loop */
763}
764# endif
765#endif
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
Definition: M480.h:605
#define UART_FIFOSTS_TXFULL_Msk
Definition: uart_reg.h:1997
#define UART_FIFOSTS_TXEMPTYF_Msk
Definition: uart_reg.h:2003
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: uart_reg.h:1985
static void SendChar_ToUART(int ch)
Routine to send a char.
Definition: retarget.c:432
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:637
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:401
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:662
static char GetChar(void)
Routine to get a char.
Definition: retarget.c:551
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:732
int IsDebugFifoEmpty(void)
Check if debug message finished.
Definition: retarget.c:618
int kbhit(void)
Check any char input from UART.
Definition: retarget.c:599
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:712
FILE __stdin
Definition: retarget.c:38
void Hard_Fault_Handler(uint32_t stack[])
Hard fault handler.
Definition: retarget.c:67
FILE __stdout
Definition: retarget.c:37
#define DEBUG_PORT
Definition: retarget.c:30
@ 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 SendChar(int ch)
Routine to send a char.
Definition: retarget.c:511
static void stackDump(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:49
return value
Definition: semihosting.h:98