WXK
2024-12-16 78e84fcf264afd731cd66c807d9fcb690fe12126
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
/**************************************************************************//**
 * @file     retarget.c
 * @version  V1.00
 * $Revision: 2 $
 * $Date: 15/02/06 7:41p $
 * @brief    PN020 series retarget source file
 *
 * @note
 * Copyright (C) 2016 Panchip Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "PanSeries.h"
 
#define UART0_ENABLE (1)
 
#if defined ( __CC_ARM   )
#if (__ARMCC_VERSION < 400000)
#else
/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
#pragma import _printf_widthprec
#endif
#endif
 
//#define DEBUG_ENABLE_UART1
 
#ifdef DEBUG_ENABLE_UART1
#define DEBUG_PORT         UART1
#else
#define DEBUG_PORT         UART0
#endif
 
/* Un-comment this line to disable all printf and getchar. getchar() will always return 0x00*/
//#define DISABLE_UART
 
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
 
 
//#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
//struct __FILE { int handle; /* Add whatever you need here */ };
//#endif
//FILE __stdout;
//FILE __stdin;
 
enum { r0, r1, r2, r3, r12, lr, pc, psr};
 
void stackDump(uint32_t stack[])
{
    printf("r0  = 0x%x\r\n", stack[r0]);
    printf("r1  = 0x%x\r\n", stack[r1]);
    printf("r2  = 0x%x\r\n", stack[r2]);
    printf("r3  = 0x%x\r\n", stack[r3]);
    printf("r12 = 0x%x\r\n", stack[r12]);
    printf("lr  = 0x%x\r\n", stack[lr]);
    printf("pc  = 0x%x\r\n", stack[pc]);
    printf("psr = 0x%x\r\n", stack[psr]);
 
}
 
void Hard_Fault_Handler(uint32_t stack[])
{
    printf("In Hard Fault Handler\r\n");
 
    stackDump(stack);
 
    //Chip Reset
    //SYS_UnlockReg();
    //SYS->IPRSTC1 |= SYS_IPRSTC1_CHIP_RST_Msk;
 
    while(1);
}
 
 
#if defined(DEBUG_ENABLE_SEMIHOST)
/* The static buffer is used to speed up the semihost */
static char g_buf[16];
static char g_buf_len = 0;
 
# if defined(__ICCARM__)
 
 
/**
 * @brief    This HardFault handler is implemented to support semihost
 *
 * @param    None
 *
 * @returns  None
 *
 * @details  This function is implement to support semihost message print.
 *
 */
void HardFault_Handler(void)
{
    asm("MOV     R0, lr        \n"
        "LSLS    R0, #29       \n"        //; Check bit 2
        "BMI     SP_is_PSP     \n"        //; previous stack is PSP
        "MRS     R0, MSP       \n"        //; previous stack is MSP, read MSP
        "B       SP_Read_Ready \n"
        "SP_is_PSP:            \n"
        "MRS     R0, PSP       \n"        //; Read PSP
        "SP_Read_Ready:        \n"
        "LDR     R1, [R0, #24] \n"        //; Get previous PC
        "LDRH    R3, [R1]      \n"        //; Get instruction
        "LDR     R2, [pc, #8]  \n"        //; The special BKPT instruction
        "CMP     R3, R2        \n"        //; Test if the instruction at previous PC is BKPT
        "BNE     HardFault_Handler_Ret\n" //; Not BKPT
        "ADDS    R1, #4        \n"        //; Skip BKPT and next line
        "STR     R1, [R0, #24] \n"        //; Save previous PC
        "BX      lr            \n"        //; Return
        "DCD     0xBEAB        \n"        //; BKPT instruction code
        "HardFault_Handler_Ret:\n"
        "MOVS    r0, #4                        \n"
        "MOV     r1, LR                        \n"
        "TST     r0, r1                        \n"
        "BEQ     Stack_Use_MSP                 \n"
        "MRS     R0, PSP                       \n" //; stack use PSP
        "B       Get_LR_and_Branch             \n"
        "Stack_Use_MSP:                        \n"
        "MRS     R0, MSP                       \n" //; stack use MSP
        "Get_LR_and_Branch:                    \n"
        "MOV     R1, LR                        \n" //; LR current value
        "B Hard_Fault_Handler        \n"
       );
 
    while(1);
}
 
/**
 *
 * @brief      The function to process semihosted command
 * @param[in]  n32In_R0  : semihost register 0
 * @param[in]  n32In_R1  : semihost register 1
 * @param[out] pn32Out_R0: semihost register 0
 * @retval     0: No ICE debug
 * @retval     1: ICE debug
 *
 */
int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
{
    asm("BKPT   0xAB    \n"       //; This instruction will cause ICE trap or system HardFault
        "B      SH_ICE  \n"
        "SH_HardFault:  \n"       //; Captured by HardFault
        "MOVS   R0, #0  \n"       //; Set return value to 0
        "BX     lr      \n"       //; Return
        "SH_ICE:        \n"       //; Captured by ICE
        "CMP    R2, #0  \n"
        "BEQ    SH_End  \n"
        "STR    R0, [R2]\n"       //; Save the return value to *pn32Out_R0
        "SH_End:        \n");
 
    return 1;                 //; Return 1 when it is trap by ICE
 
}
 
 
# else
 
/**
 * @brief    This HardFault handler is implemented to support semihost
 *
 * @param    None
 *
 * @returns  None
 *
 * @details  This function is implement to support semihost message print.
 *
 */
__asm int32_t HardFault_Handler(void)
{
 
    MOV     R0, LR
    LSLS    R0, #29               //; Check bit 2
    BMI     SP_is_PSP             //; previous stack is PSP
    MRS     R0, MSP               //; previous stack is MSP, read MSP
    B       SP_Read_Ready
SP_is_PSP
    MRS     R0, PSP               //; Read PSP
 
SP_Read_Ready
    LDR     R1, [R0, #24]         //; Get previous PC
    LDRH    R3, [R1]              //; Get instruction
    LDR     R2, =0xBEAB           //; The special BKPT instruction
                 CMP     R3, R2                //; Test if the instruction at previous PC is BKPT
                 BNE     HardFault_Handler_Ret //; Not BKPT
 
                 ADDS    R1, #4                //; Skip BKPT and next line
                 STR     R1, [R0, #24]         //; Save previous PC
 
                 BX      LR                    //; Return
HardFault_Handler_Ret
 
    /* TODO: Implement your own hard fault handler here. */
    MOVS    r0, #4
    MOV     r1, LR
    TST     r0, r1
    BEQ     Stack_Use_MSP
    MRS     R0, PSP ;stack use PSP
    B       Get_LR_and_Branch
Stack_Use_MSP
    MRS     R0, MSP ; stack use MSP
Get_LR_and_Branch
    MOV     R1, LR ; LR current value
    LDR     R2,=__cpp(Hard_Fault_Handler)
    BX      R2
 
                 B       .
 
                 ALIGN
}
 
/**
 *
 * @brief      The function to process semihosted command
 * @param[in]  n32In_R0  : semihost register 0
 * @param[in]  n32In_R1  : semihost register 1
 * @param[out] pn32Out_R0: semihost register 0
 * @retval     0: No ICE debug
 * @retval     1: ICE debug
 *
 */
__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
{
    BKPT   0xAB          //; Wait ICE or HardFault
    //; ICE will step over BKPT directly
    //; HardFault will step BKPT and the next line
    B      SH_ICE
 
SH_HardFault             //; Captured by HardFault
    MOVS   R0, #0        //; Set return value to 0
    BX     lr            //; Return
 
SH_ICE                   //; Captured by ICE
    //; Save return value
    CMP    R2, #0
    BEQ    SH_End
    STR    R0, [R2]      //; Save the return value to *pn32Out_R0
 
SH_End
    MOVS   R0, #1        //; Set return value to 1
    BX     lr            //; Return
}
#endif
 
#else
 
# if defined(__ICCARM__)
 
/**
 * @brief    This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
 *
 * @param    None
 *
 * @returns  None
 *
 * @details  This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
 *
 */
void HardFault_Handler(void)
{
    asm("MOVS    r0, #4                        \n"
        "MOV     r1, LR                        \n"
        "TST     r0, r1                        \n"
        "BEQ     Stack_Use_MSP                 \n"
        "MRS     R0, PSP                       \n" //; stack use PSP
        "B       Get_LR_and_Branch             \n"
        "Stack_Use_MSP:                        \n"
        "MRS     R0, MSP                       \n" //; stack use MSP
        "Get_LR_and_Branch:                    \n"
        "MOV     R1, LR                        \n" //; LR current value
        "B Hard_Fault_Handler                  \n"
       );
 
    while(1);
}
 
# else
 
/**
 * @brief    This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
 *
 * @param    None
 *
 * @returns  None
 *
 * @details  This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr
 *
 */
// #if !(defined(__ICCARM__) && (__VER__ >= 6100100))
 #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
void HardFault_Handler(void)
{
    __asm("MOVS    r0, #4                        \n"
        "MOV     r1, LR                        \n"
        "TST     r0, r1                        \n"
        "BEQ     Stack_Use_MSP                 \n"
        "MRS     R0, PSP                       \n" //; stack use PSP
        "B       Get_LR_and_Branch             \n"
        "Stack_Use_MSP:                        \n"
        "MRS     R0, MSP                       \n" //; stack use MSP
        "Get_LR_and_Branch:                    \n"
        "MOV     R1, LR                        \n" //; LR current value
        "B Hard_Fault_Handler                  \n"
       );
}
#else
__asm int32_t HardFault_Handler(void)
{
    MOVS    r0, #4
    MOV     r1, LR
    TST     r0, r1
    BEQ     Stack_Use_MSP
    MRS     R0, PSP ;stack use PSP
    B       Get_LR_and_Branch
Stack_Use_MSP
    MRS     R0, MSP ; stack use MSP
Get_LR_and_Branch
    MOV     R1, LR ; LR current value
    LDR     R2,=__cpp(Hard_Fault_Handler)
    BX      R2
}
#endif
 
#endif
 
#endif
 
 
/**
  * @brief  Write a char to UART.
  * @param  ch The character sent to UART.
  * @return None
  */
 
void SendChar_ToUART(int ch)
{
#ifndef DISABLE_UART
 
#if (UART0_ENABLE)
        while(UART_IsTxFifoFull(DEBUG_PORT));
        DEBUG_PORT->RBR_THR_DLL = ch;
#endif //UART0_ENABLE
    
#endif //DISABLE_UART
}
 
 
/**
  * @brief  Write a char to debug console.
  * @param  ch The character sent to debug console
  * @return None
  */
 
__WEAK void SendChar(int ch)
{
#if defined(DEBUG_ENABLE_SEMIHOST)
    g_buf[g_buf_len++] = ch;
    g_buf[g_buf_len] = '\0';
    if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
    {
        /* Send the char */
 
        if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
        {
            g_buf_len = 0;
            return;
        }
        else
        {
            int i;
 
            for(i=0;i<g_buf_len;i++)
                SendChar_ToUART(g_buf[i]);
            g_buf_len = 0;
        }
    }
#else
    SendChar_ToUART(ch);
#endif
}
 
 
/**
  * @brief  Read a char from debug console.
  * @param  None
  * @return Received character from debug console
  * @note   This API waits until UART debug port or semihost input a character
  */
 
__WEAK char GetChar(void)
{
#if defined(DEBUG_ENABLE_SEMIHOST)
#if defined ( __CC_ARM   )
    int nRet;
    while(SH_DoCommand(0x101, 0, &nRet) != 0)
    {
        if(nRet != 0)
        {
            SH_DoCommand(0x07, 0, &nRet);
            return (char)nRet;
        }
    }
#else
    int nRet;
    while(SH_DoCommand(0x7, 0, &nRet) != 0)
    {
        if(nRet != 0)
            return (char)nRet;
    }
#endif
#endif
#ifndef DISABLE_UART
        while (1)
        {
            if((DEBUG_PORT->USR & UART_USR_RFNE_Msk))
            {
                return (DEBUG_PORT->RBR_THR_DLL);
            }
        }
#else
    return(0);
#endif
}
 
 
/**
  * @brief  Check whether UART receive FIFO is empty or not.
  * @param  None
  * @return UART Rx FIFO empty status
  * @retval 1 Indicates at least one character is available in UART Rx FIFO
  * @retval 0 UART Rx FIFO is empty
  */
int kbhit(void)
{
#ifndef DISABLE_UART
    return (DEBUG_PORT->USR & UART_USR_RFNE_Msk);
#else
    return(0);
#endif
}
 
/**
  * @brief  Check whether UART transmit FIFO is empty or not.
  * @param  None
  * @return UART Tx FIFO empty status
  * @retval 1 UART Tx FIFO is empty
  * @retval 0 UART Tx FIFO is not empty
  */
int IsDebugFifoEmpty(void)
{
#ifndef DISABLE_UART
    return (DEBUG_PORT->USR & UART_USR_TFE_Msk) ? 1 : 0;
#else
    return(1);
#endif
}
 
/*---------------------------------------------------------------------------------------------------------*/
/* C library retargetting                                                                                  */
/*---------------------------------------------------------------------------------------------------------*/
void _ttywrch(int ch)
{
  SendChar(ch);
  return;
}
 
int fputc(int ch, FILE *f)
{
  SendChar(ch);
  return ch;
}
 
int fgetc(FILE *f) {
   return (GetChar());
}
 
 
int ferror(FILE *f) {
  return EOF;
}
 
#ifdef DEBUG_ENABLE_SEMIHOST
# ifdef __ICCARM__
void __exit(int return_code) {
 
    /* Check if link with ICE */
 
    if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
    {
        /* Make sure all message is print out */
 
        while(IsDebugFifoEmpty() == 0);
    }
label:  goto label;  /* endless loop */
}
# else
void _sys_exit(int return_code) {
 
    /* Check if link with ICE */
    if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
    {
        /* Make sure all message is print out */
        while(IsDebugFifoEmpty() == 0);
    }
label:  goto label;  /* endless loop */
}
# endif
#endif
/*** (C) COPYRIGHT 2016 Panchip Technology Corp. ***/