OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb-stub/] [main.c] - Blame information for rev 22

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 22 jlechner
/* Copyright (C) 2010, 2011 Embedded Computing Systems Group,
2
Department of Computer Engineering, Vienna University of Technology.
3
Contributed by Martin Walter <mwalter@opencores.org>
4
 
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published
7
by the Free Software Foundation, either version 2.1 of the License, or
8
(at your option) any later version.
9
 
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU Lesser General Public License for more details.
14
 
15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
 
18
 
19
#include <inttypes.h>
20
#include <signal.h>
21
#include <stdint.h>
22
#include <string.h>
23
#include <machine/interrupt.h>
24
#include <machine/modules.h>
25
#include "breakpoint/breakpoint.h"
26
 
27
#if defined __SCARTS_16__
28
  #include "scarts_16-tdep.h"
29
  #define SCARTS_ADDR_CTYPE  uint16_t
30
#elif defined __SCARTS_32__
31
  #include "scarts_32-tdep.h"
32
  #define SCARTS_ADDR_CTYPE  uint32_t
33
#else
34
  #error "Unsupported target machine type"
35
#endif
36
 
37
typedef struct
38
{
39
  uint8_t is_used;
40
  uint8_t type; // 2 := write, 3 := read, 4 := access
41
  SCARTS_ADDR_CTYPE address;
42
  SCARTS_ADDR_CTYPE length;
43
} watchpoint_entry_t;
44
 
45
#define NUMREGS 17
46
#define DEBUG_INT 11
47
#define REG_TYPE SCARTS_ADDR_CTYPE
48
 
49
/* Macros for boolean datatype definition. */
50
#define BOOL  uint8_t
51
#define TRUE  1
52
#define FALSE 0
53
 
54
/* Macros for bit manipulations. */
55
#define read_bit(regfile, bitpos) (((regfile) >> (bitpos)) & 1)
56
#define write_bit(regfile, bitpos, value) (void)((value) ? ((regfile) |= (1 << (bitpos))) : ((regfile) &= ~(1 << (bitpos))))
57
 
58
#define NUM_WATCHPOINTS 3
59
 
60
static int read_status_to_reset_ei_flag;
61
static watchpoint_entry_t watchpoints[NUM_WATCHPOINTS];
62
 
63
/* Number of bytes of registers.  */
64
#define NUMREGBYTES (NUMREGS * SCARTS_WORD_SIZE)
65
 
66
/************************************************************************/
67
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
68
/* at least NUMREGBYTES*2 are needed for register packets */
69
#define BUFMAX 256
70
 
71
#define CTRL_C 0x03
72
 
73
static uint8_t msg_buffer[BUFMAX+1], *msg_tx, *msg_write;
74
static int msg_size = 0; //Pointing to first free byte in buffer.
75
static volatile enum recv_states { recv_start, recv_data, recv_chk1, recv_chk2,
76
        recv_transmit_start, recv_transmit_data }
77
        recv_state = recv_start;
78
 
79
#define SAVED_FPY (*(REG_TYPE*)(SCARTS_DATAMEM_SIZE - SCARTS_WORD_SIZE * (NUMREGS)))
80
#define SAVED_FPZ (*(REG_TYPE*)(SCARTS_DATAMEM_SIZE - SCARTS_WORD_SIZE * (NUMREGS+1)))
81
/* Points to the register values stored by ASM_SAVE_REG */
82
static REG_TYPE* const saved_registers = (REG_TYPE*)(SCARTS_DATAMEM_SIZE - SCARTS_WORD_SIZE * (NUMREGS-1));//[NUMREGS-1]; /*Without PC. */
83
static REG_TYPE stop_pc;
84
static BOOL is_stopped = FALSE,
85
        stop_reply_pending = FALSE,
86
        app_loaded = FALSE; /* Has an application been transfered to the target? */
87
 
88
static BOOL wp_hit(REG_TYPE addr);
89
static BOOL wp_add(uint8_t type, REG_TYPE addr, REG_TYPE length);
90
static BOOL wp_remove(uint8_t type, REG_TYPE addr, REG_TYPE length);
91
static BOOL bp_remove(void* addr);
92
static BOOL bp_add(void* addr);
93
static void** bp_find(void* addr);
94
static void send_stop_reply();
95
void miniuart_isr1();
96
void miniuart_isr();
97
extern void stub_init();
98
 
99
 
100
int main() {
101
        stub_init();
102
 
103
        /* Wait for application download */
104
 
105
        stop_pc = 0;
106
        is_stopped = TRUE;
107
 
108
        FPY = 0; //Frameptr
109
        FPZ = 0; //Stackptr
110
 
111
        asm("main_endles_loop: jmpi main_endles_loop\n");
112
 
113
        return 0;
114
}
115
 
116
/* Saves all register values to the location directed by FPX.
117
 * Saved registers can be accessed through the global saved_registers. */
118
#define ASM_SAVE_REG \
119
";Save all registers\n\
120
stfpx_dec r15,-1\n\
121
stfpx_dec r14,-1\n\
122
stfpx_dec r13,-1\n\
123
stfpx_dec r12,-1\n\
124
stfpx_dec r11,-1\n\
125
stfpx_dec r10,-1\n\
126
stfpx_dec r9,-1\n\
127
stfpx_dec r8,-1\n\
128
stfpx_dec r7,-1\n\
129
stfpx_dec r6,-1\n\
130
stfpx_dec r5,-1\n\
131
stfpx_dec r4,-1\n\
132
stfpx_dec r3,-1\n\
133
stfpx_dec r2,-1\n\
134
stfpx_dec r1,-1\n\
135
stfpx_dec r0,-1\n"
136
 
137
#define ASM_SAVE_FPYZ \
138
";save Stack- and Frame-Pointer\n\
139
ldli r1, -16 ;FPY\n\
140
ldw r0,r1\n\
141
stfpx_dec r0,-1\n\
142
ldli r1, -12 ;FPZ\n\
143
ldw r0,r1\n\
144
stfpx_dec r0,-1\n"
145
 
146
#define ASM_INIT_STACK \
147
";Set Stack-Start into Stub-Memory\n\
148
ldli r3, -20 ;FPX\n\
149
ldw r2,r3\n\
150
ldli r1, -12 ;FPZ\n\
151
stw r2,r1 ;FPZ=FPX\n\
152
ldli r1, -16 ;FPY\n\
153
stw r2,r1 ;FPY=FPX\n"
154
 
155
 
156
#define ASM_RESTORE_FPYZ \
157
";restore Stack- and Frame-Pointer\n\
158
ldli r0, -12 ;FPZ\n\
159
ldfpx_inc r1, 0\n\
160
stw r1, r0\n\
161
ldli r0, -16 ;FPY\n\
162
ldfpx_inc r1, 0\n\
163
stw r1, r0\n"
164
 
165
#define ASM_RESTORE_REG \
166
";restore all registers\n\
167
ldfpx_inc r0, 0\n\
168
ldfpx_inc r1, 0\n\
169
ldfpx_inc r2, 0\n\
170
ldfpx_inc r3, 0\n\
171
ldfpx_inc r4, 0\n\
172
ldfpx_inc r5, 0\n\
173
ldfpx_inc r6, 0\n\
174
ldfpx_inc r7, 0\n\
175
ldfpx_inc r8, 0\n\
176
ldfpx_inc r9, 0\n\
177
ldfpx_inc r10, 0\n\
178
ldfpx_inc r11, 0\n\
179
ldfpx_inc r12, 0\n\
180
ldfpx_inc r13, 0\n\
181
ldfpx_inc r14, 0\n\
182
ldfpx_inc r15, 0\n"
183
 
184
 
185
static void STOP_HERE() {
186
        if(!is_stopped)
187
                stop_pc = (saved_registers)[SCARTS_RTE_REGNUM]; //Dont loose PC when called twice.
188
 
189
        is_stopped = TRUE;
190
asm(ASM_RESTORE_FPYZ);
191
asm(ASM_RESTORE_REG);
192
asm("ldhi r15, 4th(__stop_here_enable_gie)\n"
193
"ldliu r15, 3rd(__stop_here_enable_gie)\n"
194
"sli r15, 8\n"
195
"ldliu r15, hi(__stop_here_enable_gie)\n"
196
"sli r15, 8\n"
197
"ldliu r15, lo(__stop_here_enable_gie)\n"
198
"rte                    ; Enable GIE\n"
199
"__stop_here_enable_gie: jmpi __stop_here_enable_gie\n");
200
}
201
 
202
/* Convert ch from a hex digit to an int */
203
static int
204
hex (unsigned char ch)
205
{
206
  if (ch >= 'a' && ch <= 'f')
207
    return ch-'a'+10;
208
  if (ch >= '0' && ch <= '9')
209
    return ch-'0';
210
  if (ch >= 'A' && ch <= 'F')
211
    return ch-'A'+10;
212
  return -1;
213
}
214
 
215
const char hexchars[]="0123456789abcdef";
216
 
217
 
218
static inline void uart_recv_mode() {
219
        MINI_UART_CMD = 0x60; //Start Receiver, Event-Selector = 0!! Required to Start receiver.
220
        //Receiver is now active, set EVS next.
221
        MINI_UART_CMD = 0x64; //Start Receiver, Enable Interrupt when receive complete!!
222
}
223
 
224
static inline void uart_stop() {
225
        MINI_UART_CMD = 0x0;
226
}
227
 
228
 
229
static void send_byte(uint8_t send) {
230
        MINI_UART_CMD = 0x0;
231
 
232
          /* Zu sendende Nachricht in Messageregister laden */
233
    MINI_UART_MSG_L = send;
234
 
235
          /* Starte Transmitter (ERRI=0, EI=1, AsA="011", EvS="11")*/
236
    MINI_UART_CMD = 0x58;
237
    MINI_UART_CMD = 0x5E;
238
}
239
 
240
static void byte_received(uint8_t byte);
241
 
242
#ifdef TARGET_SIM
243
 
244
typedef struct {void* start,*end; } mem_region;
245
static mem_region valid_regions[] = {
246
        {(void*)SCARTS_DATAMEM_LMA, (void*)SCARTS_DATAMEM_SIZE }, //Data
247
        {(void*)PROC_CTRL_BADDR, (void*)(PROC_CTRL_BADDR + PROC_CTRL_SIZE) }, //Sysctrl 
248
        {(void*)DISP7SEG_BADDR, (void*)(DISP7SEG_BADDR+DISP7SEG_SIZE) }, //Display 
249
        {(void*)MINI_UART_BADDR, (void*)(MINI_UART_BADDR+MINI_UART_SIZE }, //miniUART 
250
        {0,0}};
251
 
252
int is_valid_mem(void* addr) {
253
        mem_region* rgn = valid_regions;
254
        while(rgn->start != rgn->end) {
255
                if(addr >= rgn->start && addr < rgn->end)
256
                        return 1;
257
 
258
                ++rgn;
259
        }
260
        return 0;
261
}
262
#endif//TARGET_SIM
263
 
264
char *
265
mem2hex(uint8_t *mem, char *buf, int count)
266
{
267
  unsigned char ch;
268
 
269
  while (count-- > 0)
270
    {
271
#ifdef TARGET_SIM         
272
      ch = is_valid_mem(mem) ? *mem : 0;
273
#else//TARGET_SIM
274
      ch = *mem;
275
#endif//TARGET_SIM
276
      *buf++ = hexchars[ch >> 4];
277
      *buf++ = hexchars[ch & 0xf];
278
      mem++;
279
    }
280
 
281
  return buf;
282
}
283
 
284
 
285
 
286
asm("miniuart_isr:\n");
287
asm(ASM_SAVE_REG);
288
asm(ASM_SAVE_FPYZ);
289
asm(ASM_INIT_STACK);
290
asm(";call actual interrupt handler\n\
291
ldhi  r0,4th(miniuart_isr1)\n\
292
ldliu r0,3rd(miniuart_isr1)\n\
293
sli   r0,8\n\
294
ldliu r0,hi(miniuart_isr1)\n\
295
sli   r0,8\n\
296
ldliu r0,lo(miniuart_isr1)\n\
297
jsr r0\n");
298
asm(ASM_RESTORE_FPYZ);
299
asm(ASM_RESTORE_REG);
300
asm("rte;\n");
301
 
302
 
303
void miniuart_isr1() {
304
 
305
        if (read_bit(BREAKPOINT_STATUS, BREAKPOINT_STATUS_INT)) {
306
                //Handle single-step interrupt.
307
 
308
                //Interrupt Ack.
309
                BREAKPOINT_CONFIG |= (1 << BREAKPOINT_CONFIG_INTA);
310
 
311
                send_stop_reply();
312
                STOP_HERE();
313
        } else if (read_bit(MINI_UART_STATUS, MINI_UART_STATUS_INT)) {
314
                //Handle miniUART interrupt.
315
 
316
                read_status_to_reset_ei_flag = MINI_UART_STATUS; //Reading status resets EI-Flag
317
 
318
                //Interrupt Ack.
319
                MINI_UART_CONFIG |= (1 << MINI_UART_CONFIG_INTA);
320
 
321
                switch(recv_state) {
322
                case recv_transmit_data:
323
                        if(msg_tx >= msg_write) {
324
                                msg_write = msg_buffer;
325
                                recv_state = recv_start;
326
                                uart_recv_mode(); //Put UART-HW in receive mode.
327
                        } else {
328
                                send_byte(*msg_tx++);
329
                        }
330
                        break;
331
                default: //receive      
332
                        byte_received(MINI_UART_MSG_L);
333
                        break;
334
                }
335
 
336
                if (recv_state == recv_start
337
                        && stop_reply_pending) {
338
                        send_stop_reply();
339
                }
340
        }
341
}
342
 
343
static uint8_t checksum, pkgchecksum;
344
 
345
#define start_send() recv_state = recv_transmit_data; msg_tx = msg_buffer; send_byte(*msg_tx++);
346
 
347
void add_chk(uint8_t* msg_start_chk) {
348
        uint8_t checksum = 0;
349
        while(msg_start_chk < msg_write)
350
                checksum += *msg_start_chk++;
351
 
352
        *msg_write++ = '#';
353
        *msg_write++ = hexchars[checksum >> 4];
354
        *msg_write++ = hexchars[checksum & 0xf];
355
}
356
 
357
 
358
static void request_received();
359
static void ctrl_c_received();
360
 
361
static void byte_received(uint8_t byte) {
362
 
363
        switch(recv_state) {
364
        case recv_start:
365
                if (byte == '$') {
366
restart_receive:
367
                        msg_write = msg_buffer;
368
                        checksum = 0;
369
                        recv_state = recv_data;
370
                } else if (byte == CTRL_C) {
371
                        ctrl_c_received();
372
                }
373
                break;
374
        case recv_data:
375
                if (byte == '$') //$ must noch occur in package data.
376
                        goto restart_receive;
377
                else if (msg_write >= msg_buffer + BUFMAX) { //request too large
378
                        msg_write = msg_buffer;
379
                        *msg_write++ = '+';
380
                        start_send()
381
                } else if (byte == '#') {
382
                        recv_state = recv_chk1;
383
                } else {
384
                        *msg_write++ = byte;
385
                        checksum += byte;
386
                }
387
                break;
388
        case recv_chk1:
389
                pkgchecksum = hex(byte) << 4;
390
                recv_state = recv_chk2;
391
                break;
392
        case recv_chk2:
393
                pkgchecksum += hex(byte);
394
 
395
                if(checksum != pkgchecksum) { //Checksum error.
396
                        msg_write = msg_buffer;
397
                        *msg_write++ = '-';  //NACK
398
                        start_send();
399
                } else {
400
                        msg_size = msg_write - msg_buffer;
401
                        *msg_write = '\0'; //Terminate for mem2hex
402
                        msg_write = msg_buffer; //Place response in the same buffer;
403
                        request_received();
404
                }
405
                break;
406
        case recv_transmit_start:
407
        case recv_transmit_data:
408
                break; //Should not happen.
409
        }
410
}
411
 
412
int hexToInt(uint8_t **ptr, SCARTS_ADDR_CTYPE *intValue)
413
{
414
  int numChars = 0;
415
  int hexValue;
416
 
417
  *intValue = 0;
418
 
419
  while (**ptr)
420
    {
421
      hexValue = hex(**ptr);
422
      if (hexValue < 0)
423
        break;
424
 
425
      *intValue = (*intValue << 4) | hexValue;
426
      numChars ++;
427
 
428
      (*ptr)++;
429
    }
430
 
431
  return (numChars);
432
}
433
 
434
static void send_stop_reply() {
435
        stop_reply_pending = FALSE;
436
 
437
        *msg_write++ = '$';
438
        uint8_t* start_chk = msg_write;
439
        *msg_write++ = 'S';
440
        *msg_write++ = '0'; //Signal value
441
        *msg_write++ = '5'; //Signal value
442
 
443
        add_chk(start_chk);
444
        start_send();
445
}
446
 
447
REG_TYPE tmp_regval14, tmp_regval15;
448
 
449
static void ctrl_c_received() {
450
        if (is_stopped)
451
                return; //Already stopped. Ignore further Ctrl+C requests.
452
 
453
        msg_write = msg_buffer;
454
 
455
        send_stop_reply();
456
        STOP_HERE();
457
}
458
 
459
// Complete Request is in msg_buffer now. Craft a response.
460
static void request_received() {
461
 
462
        if(msg_size < 1) { //Emypt request ???
463
                *msg_write++ = '+';
464
                start_send();
465
                return;
466
        }
467
 
468
        uint8_t* ptr = msg_buffer;
469
        uint8_t pkg_type = *ptr++;
470
        *msg_write++ = '+'; //Overwrites pkg_type-
471
 
472
        switch(pkg_type) {
473
 
474
        case '?': /* Indicate halt reason */
475
        {
476
                if(is_stopped) {
477
                        send_stop_reply();
478
                } else {
479
                        stop_reply_pending = TRUE;
480
                }
481
        }
482
        break;
483
 
484
        case 'c': //"c [addr]" Continue. addr is address to resume.
485
        {
486
                SCARTS_ADDR_CTYPE addr;
487
                if(hexToInt(&ptr, &addr))
488
                        (saved_registers)[SCARTS_RTE_REGNUM] = addr; //Continue at specified program adress.
489
                else if (is_stopped)
490
                        (saved_registers)[SCARTS_RTE_REGNUM] = stop_pc;
491
 
492
                is_stopped = FALSE;
493
                start_send();
494
                //send_stop_replay as soon as stopping.
495
        }
496
        break;
497
 
498
        case 'g': /* Read general registers */
499
        {
500
                *msg_write++ = '$';
501
                uint8_t* chk_start = msg_write;
502
 
503
                uint8_t* preg = (uint8_t*)saved_registers;
504
                int i;
505
                for (i = 0; i < (NUMREGS-1)*SCARTS_WORD_SIZE; ++i) {
506
                        *msg_write++ = hexchars[*preg >> 4];
507
                        *msg_write++ = hexchars[*preg & 0xf];
508
                        ++preg;
509
                }
510
 
511
                //PC = RTE
512
                if(is_stopped)
513
                        preg = (uint8_t*)&stop_pc;
514
                else
515
                        preg = (uint8_t*)(saved_registers + SCARTS_RTE_REGNUM);
516
 
517
                for (i = 0; i < SCARTS_WORD_SIZE; ++i) {
518
                        *msg_write++ = hexchars[*preg >> 4];
519
                        *msg_write++ = hexchars[*preg & 0xf];
520
                        ++preg;
521
                }
522
 
523
                add_chk(chk_start);
524
                start_send();
525
        }
526
        break;
527
 
528
        case 'G': /* Write general registers. */
529
        {
530
                uint8_t* chk_start;
531
 
532
                if(msg_size <  1/*G*/ + NUMREGS * SCARTS_WORD_SIZE * 2) {
533
                        /* Message doesnt contain data for all registers! */
534
                        *msg_write++ = '$';
535
                        chk_start = msg_write;
536
                        *msg_write++ = 'E';
537
                        *msg_write++ = '0';
538
                        *msg_write++ = '1';
539
                } else {
540
                        /* Set Registers. */
541
                        int lonib, hinib;
542
                        uint8_t* preg = (uint8_t*)saved_registers;
543
 
544
                        int i;
545
                        for (i = 0; i < (NUMREGS-1)*SCARTS_WORD_SIZE; ++i) {
546
                                hinib = hex(*ptr++);
547
                                lonib = hex(*ptr++);
548
                                *preg++ = (hinib << 4) | lonib;
549
                        }
550
 
551
                        /* Set PC */
552
                        if(is_stopped)
553
                                preg = (uint8_t*)&stop_pc;
554
                        else
555
                                preg = (uint8_t*)(saved_registers + SCARTS_RTE_REGNUM);
556
 
557
                        for (i = 0; i < SCARTS_WORD_SIZE; ++i) {
558
                                hinib = hex(*ptr++);
559
                                lonib = hex(*ptr++);
560
                                *preg++ = (hinib << 4) | lonib;
561
                        }
562
 
563
                        *msg_write++ = '$';
564
                        chk_start = msg_write;
565
                        *msg_write++ = 'O';
566
                        *msg_write++ = 'K';
567
                }
568
 
569
                add_chk(chk_start);
570
                start_send();
571
        }
572
        break;
573
 
574
        case 'm': //"m addr,length" Read length bytes of memory starting at address addr
575
        {
576
                uint8_t* chk_start;
577
 
578
                SCARTS_ADDR_CTYPE addr,length;
579
                if (hexToInt(&ptr, &addr)
580
                        && *ptr++ == ','
581
                        && hexToInt(&ptr, &length)) {
582
 
583
                        *msg_write++ = '$';
584
                        chk_start = msg_write;
585
 
586
                        if(addr == PROC_CTRL_FPY_BADDR && length <= 4)//Return Saved Frame-pointer. 
587
                                msg_write = (uint8_t*)mem2hex((uint8_t*)&SAVED_FPY, (char*)msg_write, length);
588
                        else if(addr == PROC_CTRL_FPZ_BADDR && length <= 4)//Return Saved Stack-pointer. 
589
                                msg_write = (uint8_t*)mem2hex((uint8_t*)&SAVED_FPZ, (char*)msg_write, length);
590
                        else
591
                                msg_write = (uint8_t*)mem2hex((uint8_t*)addr, (char*)msg_write, length);
592
                } else {
593
                        *msg_write++ = '$';
594
                        chk_start = msg_write;
595
                        *msg_write++ = 'E';
596
                        *msg_write++ = '0';
597
                        *msg_write++ = '1';
598
                }
599
 
600
                add_chk(chk_start);
601
                start_send();
602
        }
603
        break;
604
 
605
        case 'M': //"M addr,length:XX" Write length bytes of memory starting at address addr
606
        {
607
                SCARTS_ADDR_CTYPE addr,length;
608
                int lonib, hinib;
609
                uint8_t w_byte;
610
 
611
                uint8_t* chk_start;
612
 
613
                if (hexToInt(&ptr, &addr)
614
                        && *ptr++ == ','
615
                        && hexToInt(&ptr, &length)
616
                        && *ptr++ == ':') {
617
 
618
                        while(length > 0
619
                                && (hinib = hex(*ptr++)) != -1
620
                                && (lonib = hex(*ptr++)) != -1) {
621
 
622
                                w_byte = (hinib << 4) | lonib;
623
 
624
                                if (addr >= SCARTS_CODEMEM_LMA && addr <= SCARTS_CODEMEM_LMA + SCARTS_CODEMEM_SIZE * SCARTS_INSN_SIZE) {
625
                                // Write to instruction-memory. Use Programmer-Module!
626
                                        if(addr % 2 == 0) {
627
                                                /* Store first byte (LSB) in programmer-module. Wait for 2nd byte. */
628
                                                *(uint8_t*)(PROGRAMMER_BADDR+8) = w_byte; //LSB
629
                                        } else {
630
                                                /* 16-Bit word complete. Execute write. */
631
                                                *(uint8_t*)(PROGRAMMER_BADDR+9) = w_byte; //MSB
632
                                                PROGRAMMER_ADDRESS = addr / 2; //Address
633
 
634
                                                PROGRAMMER_CONFIG_C |= (1 << PROGRAMMER_CONFIG_C_PREXE); //Prog Exe
635
 
636
                                                app_loaded = TRUE;
637
                                        }
638
                                } else {
639
                                //Write to data-memory
640
                                        *(uint8_t*)addr = w_byte;
641
                                }
642
 
643
                                ++addr;
644
                                --length;
645
                        }
646
 
647
                        if(length == 0) {
648
                                *msg_write++ = '$';
649
                                chk_start = msg_write;
650
                                *msg_write++ = 'O';
651
                                *msg_write++ = 'K';
652
                        } else {
653
                                *msg_write++ = '$';
654
                                chk_start = msg_write;
655
                                *msg_write++ = 'E';
656
                                *msg_write++ = '0';
657
                                *msg_write++ = '3';
658
                        }
659
                } else {
660
                        *msg_write++ = '$';
661
                        chk_start = msg_write;
662
                        *msg_write++ = 'E';
663
                        *msg_write++ = '0';
664
                        *msg_write++ = '4';
665
                }
666
 
667
                add_chk(chk_start);
668
                start_send();
669
        }
670
        break;
671
 
672
        case 's': //"s [addr]" Single Step.
673
        {
674
                uart_stop();
675
                /* If there is an interrupt request protocoled, throw it away.
676
                Even though there should be no request until this one ins served.
677
                If this is not done, after the RTE at the end of this function,
678
                there would no single step in the application code happen,
679
                but instead control would return to the isr immediately. */
680
                if(PROC_CTRL_INTPROT & (1<<DEBUG_INT)) {
681
                        MINI_UART_CONFIG |= (1 << MINI_UART_CONFIG_INTA);
682
                }
683
 
684
                SCARTS_ADDR_CTYPE addr;
685
                if(hexToInt(&ptr, &addr))
686
                        (saved_registers)[SCARTS_RTE_REGNUM] = addr; //Step at specified program adress.
687
                else if (is_stopped)
688
                        (saved_registers)[SCARTS_RTE_REGNUM] = stop_pc;
689
 
690
                is_stopped = FALSE;
691
 
692
                //Prepare register values for the breakpoint/single-step module.
693
                //Execute 4 instructions before generating an interrupt.
694
                tmp_regval14 = BREAKPOINT_SET_STEP_COUNT(BREAKPOINT_CONFIG_C, 4);
695
                tmp_regval15 = (REG_TYPE)&(BREAKPOINT_CONFIG_C); //CONFIG_C in breakpoint module.
696
 
697
//tmp_regval14 -> r14
698
asm("\
699
ldhi  r0,4th(tmp_regval14)\n\
700
ldliu r0,3rd(tmp_regval14)\n\
701
sli   r0,8\n\
702
ldliu r0,hi(tmp_regval14)\n\
703
sli   r0,8\n\
704
ldliu r0,lo(tmp_regval14)\n\
705
ldw r14,r0\n");
706
//tmp_regval15 -> r15
707
asm("\
708
ldhi  r0,4th(tmp_regval15)\n\
709
ldliu r0,3rd(tmp_regval15)\n\
710
sli   r0,8\n\
711
ldliu r0,hi(tmp_regval15)\n\
712
sli   r0,8\n\
713
ldliu r0,lo(tmp_regval15)\n\
714
ldw r15,r0\n");
715
asm(ASM_RESTORE_FPYZ);
716
asm("\
717
;restore all registers\n\
718
ldfpx_inc r0, 0\n\
719
ldfpx_inc r1, 0\n\
720
ldfpx_inc r2, 0\n\
721
ldfpx_inc r3, 0\n\
722
ldfpx_inc r4, 0\n\
723
ldfpx_inc r5, 0\n\
724
ldfpx_inc r6, 0\n\
725
ldfpx_inc r7, 0\n\
726
ldfpx_inc r8, 0\n\
727
ldfpx_inc r9, 0\n\
728
ldfpx_inc r10, 0\n\
729
ldfpx_inc r11, 0\n\
730
ldfpx_inc r12, 0\n\
731
ldfpx_inc r13, 0\n\
732
stb r14, r15 ;Start Single-Stepping\n\
733
ldfpx_inc r14, 0 ; -- 1 --\n\
734
ldfpx_inc r15, 0 ; -- 2 --\n\
735
\n\
736
rte; ; -- 3 --\n");
737
        }
738
        break;
739
 
740
        case 'Z': //Insert breakpoint/watchpoint
741
        case 'z': //Remove breakpoint/watchpoint
742
        {
743
                uint8_t bp_type = *ptr++;
744
                *msg_write++ = '$';
745
                uint8_t* chk_start = msg_write;
746
 
747
                switch(bp_type) { /* msg_buffer[1] */
748
                case '0': //"Z0,addr,length" Insert or remove a memory breakpoint.
749
                case '2': /* write watchpoint */
750
                case '3': /* read watchpoint */
751
                case '4': /* access watchpoint */
752
                {
753
 
754
                        SCARTS_ADDR_CTYPE addr,length;
755
                        if (*ptr++ == ','
756
                                && hexToInt(&ptr, &addr)
757
                                && *ptr++ == ','
758
                                && hexToInt(&ptr, &length)) {
759
 
760
                                if(bp_type == '0') { /* Breakpoint */
761
                                        if(addr < SCARTS_CODEMEM_LMA)
762
                                                goto bp_error;
763
 
764
                                        addr = (addr - SCARTS_CODEMEM_LMA) / 2;
765
 
766
                                        if((pkg_type == 'Z' && !bp_add((void*)addr))
767
                                                || (pkg_type == 'z' && !bp_remove((void*)addr)))
768
                                                goto bp_error;
769
                                } else { /* Watchpoint */
770
                                        if((pkg_type == 'Z' && !wp_add(bp_type, addr, length))
771
                                                || (pkg_type == 'z' && !wp_remove(bp_type, addr, length)))
772
                                                goto bp_error;
773
                                }
774
 
775
                                *msg_write++ = 'O';
776
                                *msg_write++ = 'K';
777
                        } else {
778
bp_error:
779
                                *msg_write++ = 'E';
780
                                *msg_write++ = '0';
781
                                *msg_write++ = '2';
782
                        }
783
                        add_chk(chk_start);
784
                        start_send();
785
                }
786
                break;
787
                default: goto packet_not_supported;
788
                }
789
        }
790
        break;
791
 
792
        default:
793
packet_not_supported:  //Reply: "Not supported"  "+$#00"
794
                *msg_write++ = '$';
795
                add_chk(msg_write);
796
                start_send();
797
                break;
798
        }
799
 
800
}
801
 
802
static BOOL wp_remove(uint8_t type, REG_TYPE addr, REG_TYPE length) {
803
        watchpoint_entry_t* wp = watchpoints;
804
        int i;
805
        for(i = 0; i < NUM_WATCHPOINTS; ++i, ++wp)
806
                if(wp->is_used
807
                        && wp->type == type
808
                        && wp->address == addr
809
                        && wp-> length == length) {
810
                        wp->is_used = FALSE;
811
                        WATCHPOINT_CONFIG_C &= ~(0x3<<(i*2));
812
                        return TRUE;
813
                }
814
 
815
        return FALSE;
816
}
817
 
818
static BOOL wp_add(uint8_t type, REG_TYPE addr, REG_TYPE length) {
819
        watchpoint_entry_t* wp = watchpoints;
820
        int i,bitnum;
821
        for(i = 0; i < NUM_WATCHPOINTS; ++i, ++wp)
822
                if(!wp->is_used) {
823
                        wp->is_used = TRUE;
824
                        wp->type = type;
825
                        wp->address = addr;
826
                        wp->length = length;
827
 
828
                        uint8_t bits = 0;
829
                        switch(type) {
830
                        case '2': bits = 0x2; break; /* write */
831
                        case '3': bits = 0x1; break; /* read */
832
                        case '4': bits = 0x3; break; /* access */
833
                        }
834
 
835
                        REG_TYPE mask = addr + length - 1;
836
                        mask ^= addr; /* all bits different in start and end address. */
837
 
838
                        bitnum = SCARTS_WORD_SIZE*8;
839
                        while(bitnum-->0)
840
                                if(mask & (1<<bitnum))
841
                                        break; /* Find highest bit that is 1 */
842
 
843
                        /* Set all lower bits */
844
                        while(bitnum-->0)
845
                                mask |= (1<<bitnum);
846
 
847
                        *(&(WATCHPOINT_ADDR0) + i) = addr;
848
                        *(&(WATCHPOINT_MASK0) + i) = mask;
849
 
850
                        WATCHPOINT_CONFIG_C |= bits<<(i*2);
851
                        return TRUE;
852
                }
853
 
854
        return FALSE;
855
}
856
 
857
static BOOL wp_hit(REG_TYPE addr) {
858
        watchpoint_entry_t* wp = watchpoints;
859
        int i;
860
        for(i = 0; i < NUM_WATCHPOINTS; ++i, ++wp)
861
                if(wp->is_used
862
                        && addr >= wp->address
863
                        && addr < wp->address + wp->length)
864
                        return TRUE;
865
 
866
        return FALSE;
867
}
868
 
869
 
870
#define BP_NUM 7
871
#define BP_START ((void**)(BREAKPOINT_BADDR+4))
872
 
873
static void** bp_find(void* addr){
874
 
875
        void** bp_end = BP_START + BREAKPOINT_GET_BP_COUNT(BREAKPOINT_CONFIG_C);
876
        void** ptr = BP_START;
877
        while(ptr < bp_end) {
878
                if(*ptr == addr)
879
                        return ptr;
880
                ++ptr;
881
        }
882
 
883
        return NULL;
884
}
885
 
886
static BOOL bp_add(void* addr) {
887
        int count = BREAKPOINT_GET_BP_COUNT(BREAKPOINT_CONFIG_C);
888
        if (count >= BP_NUM)
889
                return FALSE; //BP-Limit exceeded.
890
 
891
        BP_START[count] = addr;
892
        BREAKPOINT_CONFIG_C = BREAKPOINT_SET_BP_COUNT(BREAKPOINT_CONFIG_C, count + 1);
893
        return TRUE;
894
}
895
 
896
static BOOL bp_remove(void* addr) {
897
        void** ptr = bp_find(addr);
898
        if(ptr == NULL) //Breakpoint at addr doeesnt exists. 
899
                return FALSE;
900
 
901
        int count = BREAKPOINT_GET_BP_COUNT(BREAKPOINT_CONFIG_C);
902
        void** bp_end = BP_START + count;
903
 
904
        while(ptr < bp_end) {
905
                *ptr = *(ptr + 1);
906
                ++ptr;
907
        }
908
 
909
        BREAKPOINT_CONFIG_C = BREAKPOINT_SET_BP_COUNT(BREAKPOINT_CONFIG_C, count - 1);
910
 
911
        return TRUE;
912
}
913
 
914
 
915
 
916
 
917
void trap0();
918
void trap0_c();
919
 
920
 
921
asm("trap0:\n");
922
asm(ASM_SAVE_REG);
923
asm(ASM_SAVE_FPYZ);
924
asm(ASM_INIT_STACK);
925
asm(";call actual interrupt handler\n\
926
ldhi  r0,4th(trap0_c)\n\
927
ldliu r0,3rd(trap0_c)\n\
928
sli   r0,8\n\
929
ldliu r0,hi(trap0_c)\n\
930
sli   r0,8\n\
931
ldliu r0,lo(trap0_c)\n\
932
jsr r0\n");
933
asm(ASM_RESTORE_FPYZ);
934
asm(ASM_RESTORE_REG);
935
asm("rte;\n");
936
 
937
/* TRAP0. Called when a breakpoint is hit. */
938
void trap0_c() {
939
        /* Trap may have been triggered by watchpoint-module. */
940
        if(read_bit(WATCHPOINT_STATUS, WATCHPOINT_STATUS_INT)) {
941
                /* Int-Ack */
942
                WATCHPOINT_CONFIG |= (1 << WATCHPOINT_CONFIG_INTA);
943
 
944
                --saved_registers[SCARTS_RTE_REGNUM]; /* Execute the instruction that has been replaced by the TRAP. */
945
 
946
                if(!wp_hit(WATCHPOINT_ACCESS_ADDR)) {
947
                        return; /* Watchpoint triggered by an access that didnt fall into watched area. */
948
                }
949
        }
950
 
951
        if(recv_state != recv_start) { /* Prevent overwriting of send-buffer. */
952
                stop_reply_pending = TRUE;
953
        }else {
954
                send_stop_reply();
955
        }
956
 
957
        STOP_HERE();
958
}
959
 
960
void stub_init() {
961
        /* When the Remote-stub is entered (by interrupt or trap),
962
         * the first task is to save all Register-Values (see ASM_SAVE_REG).
963
         * FPX is used as a pointer to the memory.where the registers are stored.
964
         * !!! FPX MUST NEVER BE MODIFIED BY THE DEBUGGED APPLICATION !!! */
965
        FPX = SCARTS_DATAMEM_SIZE;
966
 
967
        /* NO Parity, 1 Stopbits, TrCtrl=1, MsgLength=8 */
968
        MINI_UART_CFG = 0x07;
969
        /* Baud Rate 57600 bit/s at 40 MHz */
970
//      MINI_UART_UBRS_H = 0x2B;
971
//      MINI_UART_UBRS_L = 0x67;
972
        //14400 baud
973
//      MINI_UART_UBRS_H = 0x82;
974
//      MINI_UART_UBRS_L = 0x35;
975
        //115200 baud
976
        MINI_UART_UBRS_H = 0x15;
977
        MINI_UART_UBRS_L = 0xB3;
978
        //115200 baud @ 20mhz
979
//      MINI_UART_UBRS_H = 0x0A;
980
//      MINI_UART_UBRS_L = 0xDA;
981
 
982
        STVEC(miniuart_isr, DEBUG_INT - 16); //Interrupt-Vectors are stored from -16 to -1.
983
        STVEC(trap0, -16); // Trap 0. https://trac.ecs.tuwien.ac.at/SCARTS/ticket/3
984
 
985
        sei();
986
 
987
        //Make sure interrupt is not masked by GIM.
988
        PROC_CTRL_INTMASK &= ~(1<<DEBUG_INT);
989
 
990
        BREAKPOINT_CONFIG_C |= (1 << BREAKPOINT_CONFIG_C_EN); //Enable Breakpoints.
991
 
992
        uart_recv_mode();
993
}
994
 
995
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.