MINI58_BSP V3.02.000
The Board Support Package for Mini58 Series MCU
retarget.c
Go to the documentation of this file.
1/**************************************************************************/
11#include <stdio.h>
12#include "Mini58Series.h"
13
14#if defined (__ICCARM__)
15 #pragma diag_suppress=Pm150
16#endif
17
18
19#if defined ( __CC_ARM )
20 #if (__ARMCC_VERSION < 400000)
21 #else
22 /* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
23 #pragma import _printf_widthprec
24 #endif
25#endif
26
27#ifdef DEBUG_ENABLE_UART1
28#define DEBUG_PORT UART1
29#else
30#define DEBUG_PORT UART0
31#endif
32
33# define BUF_SIZE 512
34
35
36/*---------------------------------------------------------------------------------------------------------*/
37/* Global variables */
38/*---------------------------------------------------------------------------------------------------------*/
39#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
40#if (__ARMCC_VERSION < 6040000)
41struct __FILE
42{
43 int handle; /* Add whatever you need here */
44};
45#else
46#if !defined(__MICROLIB)
47 #if (__OPTIMIZE__ == -O0)
48 __asm(".global __ARM_use_no_argv\n\t" "__ARM_use_no_argv:\n\t");
49 #endif /* (__OPTIMIZE__ == -O0) */
50#endif /* !defined(__MICROLIB) */
51#endif /* (__ARMCC_VERSION < 6040000) */
52
53#elif(__VER__ >= 8000000)
54struct __FILE
55{
56 int handle; /* Add whatever you need here */
57};
58#endif /* !(defined(__ICCARM__) && (__VER__ >= 6010000)) */
59
62
63#if defined (__ARMCC_VERSION) || defined (__ICCARM__)
64 extern int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0);
65
66 #if defined( __ICCARM__ )
67 __WEAK
68 #else
69 __attribute__((weak))
70 #endif
71
72 uint32_t ProcessHardFault(uint32_t lr, uint32_t msp, uint32_t psp);
73#endif
74
75int kbhit(void);
76int IsDebugFifoEmpty(void);
77void _ttywrch(int ch);
78int fputc(int ch, FILE *stream);
79
80#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
81 #if !defined (OS_USE_SEMIHOSTING)
82 int _read(int fd, char *ptr, int len);
83 #endif
84
85 int _write(int fd, char *ptr, int len);
86#endif
87
88#if defined (__ARMCC_VERSION) || defined (__ICCARM__)
89 int fgetc(FILE *stream);
90 int ferror(FILE *stream);
91#endif
92
93char GetChar(void);
94void SendChar_ToUART(int ch);
95void SendChar(int ch);
96static volatile int32_t g_ICE_Conneced = 1;
97enum { r0, r1, r2, r3, r12, lr, pc, psr};
98
99
106static void DumpStack(uint32_t stack[])
107{
108 /*
109 printf("r0 =0x%x\n", stack[r0]);
110 printf("r1 =0x%x\n", stack[r1]);
111 printf("r2 =0x%x\n", stack[r2]);
112 printf("r3 =0x%x\n", stack[r3]);
113 printf("r12=0x%x\n", stack[r12]);
114 printf("lr =0x%x\n", stack[lr]);
115 printf("pc =0x%x\n", stack[pc]);
116 printf("psr=0x%x\n", stack[psr]);
117 */
118}
119
120
121#if defined(DEBUG_ENABLE_SEMIHOST)
122
123/* The static buffer is used to speed up the semihost */
124static char g_buf[16];
125static char g_buf_len = 0;
126
137int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
138{
139 if (g_ICE_Conneced)
140 {
141 if (pn32Out_R0)
142 *pn32Out_R0 = n32In_R0;
143
144 return 1;
145 }
146
147 return 0;
148}
149
150
151#else // defined(DEBUG_ENABLE_SEMIHOST)
152
153#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
154
165__attribute__((weak)) void HardFault_Handler(void)
166{
167 asm("MOV R0, LR \n"
168 "MRS R1, MSP \n"
169 "MRS R2, PSP \n"
170 "LDR R3, =ProcessHardFault \n"
171 "BLX R3 \n"
172 "BX R0 \n"
173 );
174}
175
176#else
177int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0);
178int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
179{
180 return 0;
181}
182#endif
183
184#endif /* defined(DEBUG_ENABLE_SEMIHOST) */
185
186
187#if defined( __ICCARM__ )
188 __WEAK
189#else
191#endif
192uint32_t ProcessHardFault(uint32_t lr, uint32_t msp, uint32_t psp)
193{
194 uint32_t *sp;
195 uint32_t inst;
196
197 /* It is casued by hardfault. Just process the hard fault */
198 /* TODO: Implement your hardfault handle code here */
199
200 /* Check the used stack */
201#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
202
203 if (lr & 0x40UL)
204 {
205#endif
206
207 /* Secure stack used */
208 if (lr & 4UL)
209 {
210 sp = (uint32_t *)psp;
211 }
212 else
213 {
214 sp = (uint32_t *)msp;
215 }
216
217#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
218 }
219 else
220 {
221 /* Non-secure stack used */
222 if (lr & 4)
223 sp = (uint32_t *)__TZ_get_PSP_NS();
224 else
225 sp = (uint32_t *)__TZ_get_MSP_NS();
226 }
227
228#endif
229
230 /* Get the instruction caused the hardfault */
231 inst = M16(sp[6]);
232
233 if (inst == 0xBEAB)
234 {
235 /*
236 If the instruction is 0xBEAB, it means it is caused by BKPT without ICE connected.
237 We still return for output/input message to UART.
238 */
239 g_ICE_Conneced = 0; // Set a flag for ICE offline
240 sp[6] += 2; // Return to next instruction
241 return lr; // Keep lr in R0
242 }
243
244 printf(" HardFault!\n\n");
245 DumpStack(sp);
246
247 /* Or *sp to remove compiler warning */
248 while (1U | *sp) {}
249
250 return lr;
251}
252
253
263#ifndef NONBLOCK_PRINTF
264void SendChar_ToUART(int ch)
265{
266 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) {}
267
268 if ((char)ch == '\n')
269 {
270 DEBUG_PORT->DAT = '\r';
271
272 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) {}
273
274 }
275
276 DEBUG_PORT->DAT = (uint32_t)ch;
277}
278
279#else
280
281/* Non-block implement of send char */
282void SendChar_ToUART(int ch)
283{
284 static uint8_t u8Buf[BUF_SIZE] = {0};
285 static int32_t i32Head = 0;
286 static int32_t i32Tail = 0;
287 int32_t i32Tmp;
288
289 /* Only flush the data in buffer to UART when ch == 0 */
290 if (ch)
291 {
292 // Push char
293
294 if (ch == '\n')
295 {
296 i32Tmp = i32Head + 1;
297
298 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
299
300 if (i32Tmp != i32Tail)
301 {
302 u8Buf[i32Head] = '\r';
303 i32Head = i32Tmp;
304 }
305 }
306
307 i32Tmp = i32Head + 1;
308
309 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
310
311 if (i32Tmp != i32Tail)
312 {
313 u8Buf[i32Head] = ch;
314 i32Head = i32Tmp;
315 }
316 }
317 else
318 {
319 if (i32Tail == i32Head)
320 return;
321 }
322
323 // Pop char
324 do
325 {
326 i32Tmp = i32Tail + 1;
327
328 if (i32Tmp > BUF_SIZE) i32Tmp = 0;
329
330 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) == 0)
331 {
332 DEBUG_PORT->DAT = u8Buf[i32Tail];
333 i32Tail = i32Tmp;
334 }
335 else
336 break; // FIFO full
337 } while (i32Tail != i32Head);
338}
339#endif /* else for NONBLOCK_PRINTF */
340
341
352#if !defined( __ICCARM__ )
353 #define __WEAK __attribute__((weak))
354#endif
355__WEAK void SendChar(int ch)
356{
357#if defined(DEBUG_ENABLE_SEMIHOST)
358 g_buf[g_buf_len++] = ch;
359 g_buf[g_buf_len] = '\0';
360
361 if (g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
362 {
363 /* Send the char */
364 if (g_ICE_Conneced)
365 {
366
367 if (SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
368 {
369 g_buf_len = 0;
370
371 return;
372 }
373 }
374 else
375 {
376#if (DEBUG_ENABLE_SEMIHOST == 1) // Re-direct to UART Debug Port only when DEBUG_ENABLE_SEMIHOST=1
377 int i;
378
379 for (i = 0; i < g_buf_len; i++)
380 SendChar_ToUART(g_buf[i]);
381
382#endif
383 g_buf_len = 0;
384 }
385 }
386
387#else
388 SendChar_ToUART(ch);
389#endif /* DEBUG_ENABLE_SEMIHOST */
390}
391
392
402char GetChar(void)
403{
404#ifdef DEBUG_ENABLE_SEMIHOST
405
406 if (g_ICE_Conneced)
407 {
408#if defined (__ICCARM__)
409 int nRet;
410
411 while (SH_DoCommand(0x7, 0, &nRet) != 0)
412 {
413 if (nRet != 0)
414 return (char)nRet;
415 }
416
417#else
418 int nRet;
419
420 while (SH_DoCommand(0x101, 0, &nRet) != 0)
421 {
422 if (nRet != 0)
423 {
424 SH_DoCommand(0x07, 0, &nRet);
425 return (char)nRet;
426 }
427 }
428
429#endif
430
431 }
432 else
433 {
434
435#if (DEBUG_ENABLE_SEMIHOST == 1) // Re-direct to UART Debug Port only when DEBUG_ENABLE_SEMIHOST=1
436
437 /* Use debug port when ICE is not connected at semihost mode */
438 while (!g_ICE_Conneced)
439 {
440 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U)
441 {
442 return ((char)DEBUG_PORT->DAT);
443 }
444 }
445
446#endif
447 }
448
449 return (0);
450
451#else
452
453 while (1)
454 {
455 if ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U)
456 {
457 return ((char)DEBUG_PORT->DAT);
458 }
459 }
460
461#endif
462}
463
464
475int kbhit(void)
476{
477 return !((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0U);
478}
479
480
492{
493 return ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) != 0U);
494}
495
496
506void _ttywrch(int ch)
507{
508 SendChar(ch);
509 return;
510}
511
512
530int fputc(int ch, FILE *stream)
531{
532 SendChar(ch);
533 return ch;
534}
535
536
537#if defined ( __GNUC__ ) && !defined (__ARMCC_VERSION)
538
539#if defined (OS_USE_SEMIHOSTING)
540
541#else
542
543int _write(int fd, char *ptr, int len)
544{
545 int i = len;
546
547 while (i--)
548 {
549 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
550
551 if (*ptr == '\n')
552 {
553 DEBUG_PORT->DAT = '\r';
554
555 while (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
556 }
557
558 DEBUG_PORT->DAT = *ptr++;
559 }
560
561 return len;
562}
563
564
565int _read(int fd, char *ptr, int len)
566{
567 while ((DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) != 0);
568
569 *ptr = DEBUG_PORT->DAT;
570 return 1;
571}
572#endif
573
574#else
575
586int fgetc(FILE *stream)
587{
588 return ((int)GetChar());
589}
590
591
606int ferror(FILE *stream)
607{
608 return EOF;
609}
610#endif
611
612
613#ifdef DEBUG_ENABLE_SEMIHOST
614#ifdef __ICCARM__
615void __exit(int return_code)
616{
617 /* Check if link with ICE */
618 if (SH_DoCommand(0x18, 0x20026, NULL) == 0)
619 {
620 /* Make sure all message is print out */
621 while (IsDebugFifoEmpty() == 0);
622 }
623
624label:
625 goto label; /* Endless loop */
626}
627
628#else
629
630void _sys_exit(int return_code)
631{
632 /* Check if link with ICE */
633 if (SH_DoCommand(0x18, 0x20026, NULL) == 0)
634 {
635 /* Make sure all message is print out */
636 while (IsDebugFifoEmpty() == 0);
637 }
638
639label:
640 goto label; /* Endless loop */
641}
642
643#endif
644#endif
Mini58 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 M16(addr)
Get a 16-bit unsigned value from specified address.
#define NULL
NULL pointer.
@ pc
Definition: retarget.c:97
@ r0
Definition: retarget.c:97
@ r2
Definition: retarget.c:97
@ lr
Definition: retarget.c:97
@ r3
Definition: retarget.c:97
@ r1
Definition: retarget.c:97
@ r12
Definition: retarget.c:97
@ psr
Definition: retarget.c:97
static void DumpStack(uint32_t stack[])
Helper function to dump register while hard fault occurred.
Definition: retarget.c:106
int32_t SH_Return(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
Definition: retarget.c:178
void _ttywrch(int ch)
C library retargetting.
Definition: retarget.c:506
int fputc(int ch, FILE *stream)
Write character to stream.
Definition: retarget.c:530
void SendChar(int ch)
Definition: retarget.c:355
int ferror(FILE *stream)
Check error indicator.
Definition: retarget.c:606
int IsDebugFifoEmpty(void)
Check if debug message finished.
Definition: retarget.c:491
void SendChar_ToUART(int ch)
Routine to send a char.
Definition: retarget.c:264
#define BUF_SIZE
Definition: retarget.c:33
int kbhit(void)
Check any char input from UART.
Definition: retarget.c:475
int fgetc(FILE *stream)
Get character from UART debug port or semihosting input.
Definition: retarget.c:586
FILE __stdin
Definition: retarget.c:61
FILE __stdout
Definition: retarget.c:60
#define __WEAK
Routine to send a char.
Definition: retarget.c:353
char GetChar(void)
Routine to get a char.
Definition: retarget.c:402
#define DEBUG_PORT
Definition: retarget.c:30
static volatile int32_t g_ICE_Conneced
Definition: retarget.c:96
__attribute__((weak))
Definition: retarget.c:190
int handle
Definition: retarget.c:43