M471M/R1/S BSP V3.01.000
The Board Support Package for M4521
retarget.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include "NuMicro.h"
12
13#if defined ( __CC_ARM )
14#if (__ARMCC_VERSION < 400000)
15#else
16/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
17#pragma import _printf_widthprec
18#endif
19#endif
20
21/*---------------------------------------------------------------------------------------------------------*/
22/* Global variables */
23/*---------------------------------------------------------------------------------------------------------*/
24#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
25struct __FILE
26{
27 int handle; /* Add whatever you need here */
28};
29#endif
32
33enum { r0, r1, r2, r3, r12, lr, pc, psr};
34
41static void stackDump(uint32_t stack[])
42{
43 printf("r0 = 0x%x\n", stack[r0]);
44 printf("r1 = 0x%x\n", stack[r1]);
45 printf("r2 = 0x%x\n", stack[r2]);
46 printf("r3 = 0x%x\n", stack[r3]);
47 printf("r12 = 0x%x\n", stack[r12]);
48 printf("lr = 0x%x\n", stack[lr]);
49 printf("pc = 0x%x\n", stack[pc]);
50 printf("psr = 0x%x\n", stack[psr]);
51}
52
59void Hard_Fault_Handler(uint32_t stack[])
60{
61 printf("In Hard Fault Handler\n");
62
63 stackDump(stack);
64 // Replace while(1) with chip reset if WDT is not enabled for end product
65 while(1);
66 //SYS->IPRST0 = SYS_IPRST0_CHIPRST_Msk;
67}
68
69
70
71/*---------------------------------------------------------------------------------------------------------*/
72/* Routine to write a char */
73/*---------------------------------------------------------------------------------------------------------*/
74
75#if defined(DEBUG_ENABLE_SEMIHOST)
76/* The static buffer is used to speed up the semihost */
77static char g_buf[16];
78static char g_buf_len = 0;
79
80/* Make sure won't goes here only because --gnu is defined , so
81 add !__CC_ARM and !__ICCARM__ checking */
82# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
83
84# elif defined(__ICCARM__) // IAR
85
86void SH_End(void)
87{
88 asm("MOVS R0,#1 \n" //; Set return value to 1
89 "BX lr \n" //; Return
90 );
91}
92
93void SH_ICE(void)
94{
95 asm("CMP R2,#0 \n"
96 "BEQ SH_End \n"
97 "STR R0,[R2] \n" //; Save the return value to *pn32Out_R0
98 );
99}
100
111int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
112{
113 asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
114 "B SH_ICE \n"
115 "SH_HardFault: \n" //; Captured by HardFault
116 "MOVS R0,#0 \n" //; Set return value to 0
117 "BX lr \n" //; Return
118 );
119
120 return 1; //; Return 1 when it is trap by ICE
121}
122
129void Get_LR_and_Branch(void)
130{
131 asm("MOV R1, LR \n" //; LR current value
132 "B Hard_Fault_Handler \n"
133 );
134}
135
142void Stack_Use_MSP(void)
143{
144 asm("MRS R0, MSP \n" //; read MSP
145 "B Get_LR_and_Branch \n"
146 );
147}
148
155void HardFault_Handler_Ret(void)
156{
157 asm("MOVS r0, #4 \n"
158 "MOV r1, LR \n"
159 "TST r0, r1 \n" //; check LR bit 2
160 "BEQ Stack_Use_MSP \n" //; stack use MSP
161 "MRS R0, PSP \n" //; stack use PSP, read PSP
162 "B Get_LR_and_Branch \n"
163 );
164}
165
173void SP_Read_Ready(void)
174{
175 asm("LDR R1, [R0, #24] \n" //; Get previous PC
176 "LDRH R3, [R1] \n" //; Get instruction
177 "LDR R2, [pc, #8] \n" //; The special BKPT instruction
178 "CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
179 "BNE HardFault_Handler_Ret \n" //; Not BKPT
180 "ADDS R1, #4 \n" //; Skip BKPT and next line
181 "STR R1, [R0, #24] \n" //; Save previous PC
182 "BX lr \n" //; Return
183 "DCD 0xBEAB \n" //; BKPT instruction code
184 "B HardFault_Handler_Ret \n"
185 );
186}
187
194void SP_is_PSP(void)
195{
196 asm(
197 "MRS R0, PSP \n" //; stack use PSP, read PSP
198 "B Get_LR_and_Branch \n"
199
200 );
201}
202
213void HardFault_Handler (void)
214{
215 asm("MOV R0, lr \n"
216 "LSLS R0, #29 \n" //; Check bit 2
217 "BMI SP_is_PSP \n" //; previous stack is PSP
218 "MRS R0, MSP \n" //; previous stack is MSP, read MSP
219 "B SP_Read_Ready \n"
220 );
221
222 while(1);
223}
224
225# else
226
234__asm int32_t HardFault_Handler(void)
235{
236 MOV R0, LR
237 LSLS R0, #29 //; Check bit 2
238 BMI SP_is_PSP //; previous stack is PSP
239 MRS R0, MSP //; previous stack is MSP, read MSP
240 B SP_Read_Ready
241SP_is_PSP
242 MRS R0, PSP //; Read PSP
243
244SP_Read_Ready
245 LDR R1, [R0, #24] //; Get previous PC
246 LDRH R3, [R1] //; Get instruction
247 LDR R2, =0xBEAB //; The special BKPT instruction
248 CMP R3, R2 //; Test if the instruction at previous PC is BKPT
249 BNE HardFault_Handler_Ret //; Not BKPT
250
251 ADDS R1, #4 //; Skip BKPT and next line
252 STR R1, [R0, #24] //; Save previous PC
253
254 BX LR //; Return
255HardFault_Handler_Ret
256
257 /* TODO: Implement your own hard fault handler here. */
258 MOVS r0, #4
259 MOV r1, LR
260 TST r0, r1 //; check LR bit 2
261 BEQ Stack_Use_MSP //; stack use MSP
262 MRS R0, PSP ;stack use PSP //; stack use PSP, read PSP
263 B Get_LR_and_Branch
264Stack_Use_MSP
265 MRS R0, MSP ; stack use MSP //; read MSP
266Get_LR_and_Branch
267 MOV R1, LR ; LR current value //; LR current value
268 LDR R2,=__cpp(Hard_Fault_Handler) //; branch to Hard_Fault_Handler
269 BX R2
270
271 B .
272
273 ALIGN
274}
275
286__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
287{
288 BKPT 0xAB //; Wait ICE or HardFault
289 //; ICE will step over BKPT directly
290 //; HardFault will step BKPT and the next line
291 B SH_ICE
292
293SH_HardFault //; Captured by HardFault
294 MOVS R0, #0 //; Set return value to 0
295 BX lr //; Return
296
297SH_ICE //; Captured by ICE
298 //; Save return value
299 CMP R2, #0
300 BEQ SH_End
301 STR R0, [R2] //; Save the return value to *pn32Out_R0
302
303SH_End
304 MOVS R0, #1 //; Set return value to 1
305 BX lr //; Return
306}
307#endif
308
309#else // ndef DEBUG_ENABLE_SEMIHOST
310
311/* Make sure won't goes here only because --gnu is defined , so
312 add !__CC_ARM and !__ICCARM__ checking */
313# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
314
325void HardFault_Handler(void)
326{
327 asm("MOVS r0, #4 \n"
328 "MOV r1, LR \n"
329 "TST r0, r1 \n" /*; check LR bit 2 */
330 "BEQ 1f \n" /*; stack use MSP */
331 "MRS R0, PSP \n" /*; stack use PSP, read PSP */
332 "MOV R1, LR \n" /*; LR current value */
333 "B Hard_Fault_Handler \n"
334 "1: \n"
335 "MRS R0, MSP \n" /*; LR current value */
336 "B Hard_Fault_Handler \n"
337 ::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
338 );
339 while(1);
340}
341
342# elif defined(__ICCARM__)
343
344void Get_LR_and_Branch(void)
345{
346 asm("MOV R1, LR \n" //; LR current value
347 "B Hard_Fault_Handler \n"
348 );
349}
350
351void Stack_Use_MSP(void)
352{
353 asm("MRS R0, MSP \n" //; read MSP
354 "B Get_LR_and_Branch \n"
355 );
356}
357
368void HardFault_Handler(void)
369{
370 asm("MOVS r0, #4 \n"
371 "MOV r1, LR \n"
372 "TST r0, r1 \n" //; check LR bit 2
373 "BEQ Stack_Use_MSP \n" //; stack use MSP
374 "MRS R0, PSP \n" //; stack use PSP, read PSP
375 "B Get_LR_and_Branch \n"
376 );
377
378 while(1);
379}
380
381# else
382
393__asm int32_t HardFault_Handler(void)
394{
395 MOVS r0, #4
396 MOV r1, LR
397 TST r0, r1 //; check LR bit 2
398 BEQ Stack_Use_MSP //; stack use MSP
399 MRS R0, PSP //; stack use PSP, read PSP
400 B Get_LR_and_Branch
401Stack_Use_MSP
402 MRS R0, MSP //; read MSP
403Get_LR_and_Branch
404 MOV R1, LR //; LR current value
405 LDR R2,=__cpp(Hard_Fault_Handler) //; branch to Hard_Fault_Handler
406 BX R2
407}
408
409#endif
410
411#endif
412
413
423#ifndef NONBLOCK_PRINTF
424void SendChar_ToUART(int ch)
425{
426 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
427
428 DEBUG_PORT->DAT = ch;
429 if(ch == '\n')
430 {
431 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
432 DEBUG_PORT->DAT = '\r';
433 }
434}
435
436#else
437/* Non-block implement of send char */
438#define BUF_SIZE 2048
439void SendChar_ToUART(int ch)
440{
441 static uint8_t u8Buf[BUF_SIZE] = {0};
442 static int32_t i32Head = 0;
443 static int32_t i32Tail = 0;
444 int32_t i32Tmp;
445
446 /* Only flush the data in buffer to UART when ch == 0 */
447 if(ch)
448 {
449 // Push char
450 i32Tmp = i32Head+1;
451 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
452 if(i32Tmp != i32Tail)
453 {
454 u8Buf[i32Head] = ch;
455 i32Head = i32Tmp;
456 }
457
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 else
470 {
471 if(i32Tail == i32Head)
472 return;
473 }
474
475 // pop char
476 do
477 {
478 i32Tmp = i32Tail + 1;
479 if(i32Tmp > BUF_SIZE) i32Tmp = 0;
480
481 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
482 {
483 DEBUG_PORT->DAT = u8Buf[i32Tail];
484 i32Tail = i32Tmp;
485 }
486 else
487 break; // FIFO full
488 }while(i32Tail != i32Head);
489}
490#endif
491
501void SendChar(int ch)
502{
503#if defined(DEBUG_ENABLE_SEMIHOST)
504 g_buf[g_buf_len++] = ch;
505 g_buf[g_buf_len] = '\0';
506 if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
507 {
508 /* Send the char */
509 if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
510 {
511 g_buf_len = 0;
512 return;
513 }
514 else
515 {
516 g_buf_len = 0;
517 }
518 }
519#else
520 SendChar_ToUART(ch);
521#endif
522}
523
533char GetChar(void)
534{
535#ifdef DEBUG_ENABLE_SEMIHOST
536# if defined (__CC_ARM)
537 int nRet;
538 while(SH_DoCommand(0x101, 0, &nRet) != 0)
539 {
540 if(nRet != 0)
541 {
542 SH_DoCommand(0x07, 0, &nRet);
543 return (char)nRet;
544 }
545 }
546# else
547 int nRet;
548 while(SH_DoCommand(0x7, 0, &nRet) != 0)
549 {
550 if(nRet != 0)
551 return (char)nRet;
552 }
553# endif
554 return (0);
555#else
556
557 while(1)
558 {
559 if((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
560 {
561 return (DEBUG_PORT->DAT);
562 }
563 }
564
565#endif
566}
567
579int kbhit(void)
580{
581 return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0);
582}
595{
596 return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) != 0);
597}
598
609void _ttywrch(int ch)
610{
611 SendChar(ch);
612 return;
613}
614
615
634int fputc(int ch, FILE *stream)
635{
636 SendChar(ch);
637 return ch;
638}
639
640#if defined ( __GNUC__ )
641
642int _write (int fd, char *ptr, int len)
643{
644 int i = len;
645
646 while(i--) {
647 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
648
649 DEBUG_PORT->DAT = *ptr++;
650
651 if(*ptr == '\n') {
652 while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
653 DEBUG_PORT->DAT = '\r';
654 }
655 }
656 return len;
657}
658
659int _read (int fd, char *ptr, int len)
660{
661
662 while((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
663 *ptr = DEBUG_PORT->DAT;
664 return 1;
665
666
667}
668
669#else
681int fgetc(FILE *stream)
682{
683 return (GetChar());
684}
685
701int ferror(FILE *stream)
702{
703 return EOF;
704}
705#endif
706#ifdef DEBUG_ENABLE_SEMIHOST
707# ifdef __ICCARM__
708void __exit(int return_code)
709{
710
711 /* Check if link with ICE */
712 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
713 {
714 /* Make sure all message is print out */
715 while(IsDebugFifoEmpty() == 0);
716 }
717label:
718 goto label; /* endless loop */
719}
720# else
721void _sys_exit(int return_code)
722{
723
724 /* Check if link with ICE */
725 if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
726 {
727 /* Make sure all message is print out */
728 while(IsDebugFifoEmpty() == 0);
729 }
730label:
731 goto label; /* endless loop */
732}
733# endif
734#endif
#define UART_FIFOSTS_TXFULL_Msk
Definition: M471M_R1_S.h:12041
#define UART_FIFOSTS_TXEMPTYF_Msk
Definition: M471M_R1_S.h:12047
#define UART_FIFOSTS_RXEMPTY_Msk
Definition: M471M_R1_S.h:12029
NuMicro peripheral access layer header file.
#define NULL
Definition: M471M_R1_S.h:13908
@ pc
Definition: retarget.c:33
@ r0
Definition: retarget.c:33
@ r2
Definition: retarget.c:33
@ lr
Definition: retarget.c:33
@ r3
Definition: retarget.c:33
@ r1
Definition: retarget.c:33
@ r12
Definition: retarget.c:33
@ psr
Definition: retarget.c:33
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:609
__asm int32_t HardFault_Handler(void)
This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr.
Definition: retarget.c:393
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:634
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:701
int IsDebugFifoEmpty(void)
Check if debug message finished.
Definition: retarget.c:594
void SendChar_ToUART(int ch)
Routine to send a char.
Definition: retarget.c:424
int kbhit(void)
Check any char input from UART.
Definition: retarget.c:579
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:681
FILE __stdin
Definition: retarget.c:31
void Hard_Fault_Handler(uint32_t stack[])
Hard fault handler.
Definition: retarget.c:59
void SendChar(int ch)
Routine to send a char.
Definition: retarget.c:501
FILE __stdout
Definition: retarget.c:30
char GetChar(void)
Routine to get a char.
Definition: retarget.c:533
static void stackDump(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:41
return value
Definition: semihosting.h:98
int handle
Definition: retarget.c:27
#define DEBUG_PORT