M480 BSP V3.0.7000
The Board Support Package for M480 Series
retarget_iap.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 // keil
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
318#else // ndef DEBUG_ENABLE_SEMIHOST
319
320
321/* Make sure won't goes here only because --gnu is defined , so
322 add !__CC_ARM and !__ICCARM__ checking */
323# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
324
335void HardFault_Handler(void)
336{
337 asm("MOVS r0, #4 \n"
338 "MOV r1, LR \n"
339 "TST r0, r1 \n" /*; check LR bit 2 */
340 "BEQ 1f \n" /*; stack use MSP */
341 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
342 "MOV R1, LR \n" /*; LR current value */
343 "B Hard_Fault_Handler \n"
344 "1: \n"
345 "MRS R0, MSP \n" /*; LR current value */
346 "B Hard_Fault_Handler \n"
347 ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
348 );
349 while(1);
350}
351
352# elif defined(__ICCARM__) // IAR
353
354void Get_LR_and_Branch(void)
355{
356 asm("MOV R1, LR \n" /*; LR current value */
357 "B Hard_Fault_Handler \n"
358 );
359}
360
361void Stack_Use_MSP(void)
362{
363 asm("MRS R0, MSP \n" /*; read MSP */
364 "B Get_LR_and_Branch \n"
365 );
366}
367
378void HardFault_Handler(void)
379{
380 asm("MOVS r0, #4 \n"
381 "MOV r1, LR \n"
382 "TST r0, r1 \n" /*; check LR bit 2 */
383 "BEQ Stack_Use_MSP \n" /*; stack use MSP */
384 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
385 "B Get_LR_and_Branch \n"
386 );
387
388 while(1);
389}
390
391# else // Keil
392
403__asm int32_t HardFault_Handler(void)
404{
405 MOVS r0, #4
406 MOV r1, LR
407 TST r0, r1 /*; check LR bit 2 */
408 BEQ Stack_Use_MSP /*; stack use MSP */
409 MRS R0, PSP /*; stack use PSP, read PSP */
410 B Get_LR_and_Branch
411Stack_Use_MSP
412 MRS R0, MSP /*; read MSP */
413Get_LR_and_Branch
414 MOV R1, LR /*; LR current value */
415 LDR R2,=__cpp(Hard_Fault_Handler) /*; branch to Hard_Fault_Handler */
416 BX R2
417}
418
419#endif
420
421#endif // defined(DEBUG_ENABLE_SEMIHOST)
422
423
424#ifndef DISABLE_UART
434#ifndef NONBLOCK_PRINTF
435static void SendChar_ToUART(int ch)
436{
437 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
438
439 if(ch == '\n')
440 {
441 DEBUG_PORT->DAT = '\r';
442 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
443 }
444 DEBUG_PORT->DAT = ch;
445}
446
447#else
448/* Non-block implement of send char */
449#define BUF_SIZE 2048
450static void SendChar_ToUART(int ch)
451{
452 static uint8_t u8Buf[BUF_SIZE] = {0};
453 static int32_t i32Head = 0;
454 static int32_t i32Tail = 0;
455 int32_t i32Tmp;
456
457 /* Only flush the data in buffer to UART when ch == 0 */
458 if(ch)
459 {
460 /* Push char */
461 if(ch == '\n')
462 {
463 i32Tmp = i32Head+1;
464 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
465 if(i32Tmp != i32Tail)
466 {
467 u8Buf[i32Head] = '\r';
468 i32Head = i32Tmp;
469 }
470 }
471
472 i32Tmp = i32Head+1;
473 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
474 if(i32Tmp != i32Tail)
475 {
476 u8Buf[i32Head] = ch;
477 i32Head = i32Tmp;
478 }
479 }
480 else
481 {
482 if(i32Tail == i32Head)
483 return;
484 }
485
486 /* pop char */
487 do
488 {
489 i32Tmp = i32Tail + 1;
490 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
491
492 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
493 {
494 DEBUG_PORT->DAT = u8Buf[i32Tail];
495 i32Tail = i32Tmp;
496 }
497 else
498 break; /* FIFO full */
499 }while(i32Tail != i32Head);
500}
501#endif /* else for NONBLOCK_PRINTF */
502
503#endif /* if not def DISABLE_UART */
504
514static void SendChar(int ch)
515{
516#if defined(DEBUG_ENABLE_SEMIHOST)
517 g_buf[g_buf_len++] = ch;
518 g_buf[g_buf_len] = '\0';
519 if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
520 {
521 /* Send the char */
522 if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
523 {
524 g_buf_len = 0;
525 return;
526 }
527 else
528 {
529#ifndef DISABLE_UART
530 int i;
531
532 for(i = 0; i < g_buf_len; i++)
533 SendChar_ToUART(g_buf[i]);
534#endif
535 g_buf_len = 0;
536 }
537 }
538#else
539#ifndef DISABLE_UART
540 SendChar_ToUART(ch);
541#endif
542#endif
543}
544
554static char GetChar(void)
555{
556#ifdef DEBUG_ENABLE_SEMIHOST
557# if defined (__CC_ARM)
558 int nRet;
559 while(SH_DoCommand(0x101, 0, &nRet) != 0)
560 {
561 if(nRet != 0)
562 {
563 SH_DoCommand(0x07, 0, &nRet);
564 return (char)nRet;
565 }
566 }
567# else
568 int nRet;
569 while(SH_DoCommand(0x7, 0, &nRet) != 0)
570 {
571 if(nRet != 0)
572 return (char)nRet;
573 }
574# endif
575 return (0);
576#else
577#ifndef DISABLE_UART
578 while(1)
579 {
580 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
581 {
582 return (DEBUG_PORT->DAT);
583 }
584 }
585#else
586 return 0;
587#endif
588#endif
589}
590
602int kbhit(void)
603{
604#ifndef DISABLE_UART
605 return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0);
606#else
607 return 1;
608#endif
609}
622{
623#ifndef DISABLE_UART
624 return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) != 0);
625#else
626 return 1;
627#endif
628}
629
640void _ttywrch(int ch)
641{
642 SendChar(ch);
643 return;
644}
645
646
665int fputc(int ch, FILE *stream)
666{
667 SendChar(ch);
668 return ch;
669}
670
671#if defined (__GNUC__) && !defined(__ARMCC_VERSION)
672
673int _write (int fd, char *ptr, int len)
674{
675 int i = len;
676
677 while(i--)
678 {
679 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
680
681 if(*ptr == '\n')
682 {
683 DEBUG_PORT->DAT = '\r';
684 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
685 }
686
687 DEBUG_PORT->DAT = *ptr++;
688
689 }
690 return len;
691}
692
693int _read (int fd, char *ptr, int len)
694{
695
696 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
697 *ptr = DEBUG_PORT->DAT;
698 return 1;
699
700
701}
702
703#else
715int fgetc(FILE *stream)
716{
717 return (GetChar());
718}
719
735int ferror(FILE *stream)
736{
737 return EOF;
738}
739#endif
740#ifdef DEBUG_ENABLE_SEMIHOST
741# ifdef __ICCARM__
742void __exit(int return_code)
743{
744
745 /* Check if link with ICE */
746 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
747 {
748 /* Make sure all message is print out */
749 while(IsDebugFifoEmpty() == 0);
750 }
751label:
752 goto label; /* endless loop */
753}
754# else
755void _sys_exit(int return_code)
756{
757
758 /* Check if link with ICE */
759 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
760 {
761 /* Make sure all message is print out */
762 while(IsDebugFifoEmpty() == 0);
763 }
764label:
765 goto label; /* endless loop */
766}
767# endif
768#endif
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
Definition: M480.h:605
#define UART_FIFOSTS_TXFULL_Msk
Definition: uart_reg.h:2000
#define UART_FIFOSTS_TXEMPTYF_Msk
Definition: uart_reg.h:2006
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: uart_reg.h:1988
static void SendChar_ToUART(int ch)
Routine to send a char.
Definition: retarget_iap.c:435
void _ttywrch(int ch)
C library retargetting.
Definition: retarget_iap.c:640
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget_iap.c:403
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget_iap.c:665
static char GetChar(void)
Routine to get a char.
Definition: retarget_iap.c:554
int ferror(FILE *stream)
Check error indicator.
Definition: retarget_iap.c:735
int IsDebugFifoEmpty(void)
Check if debug message finished.
Definition: retarget_iap.c:621
int kbhit(void)
Check any char input from UART.
Definition: retarget_iap.c:602
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget_iap.c:715
FILE __stdin
Definition: retarget_iap.c:38
void Hard_Fault_Handler(uint32_t stack[])
Hard fault handler.
Definition: retarget_iap.c:67
FILE __stdout
Definition: retarget_iap.c:37
#define DEBUG_PORT
Definition: retarget_iap.c:30
@ pc
Definition: retarget_iap.c:41
@ r0
Definition: retarget_iap.c:41
@ r2
Definition: retarget_iap.c:41
@ lr
Definition: retarget_iap.c:41
@ r3
Definition: retarget_iap.c:41
@ r1
Definition: retarget_iap.c:41
@ r12
Definition: retarget_iap.c:41
@ psr
Definition: retarget_iap.c:41
static void SendChar(int ch)
Routine to send a char.
Definition: retarget_iap.c:514
static void stackDump(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget_iap.c:49
return value
Definition: semihosting.h:98