1 //========================================================================
5 // ICE debugging support for V850 processors
7 //========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================
41 //#####DESCRIPTIONBEGIN####
43 // Author(s): jlarmour
47 // Description: ICE debugging support for V850 processors
50 //####DESCRIPTIONEND####
52 //========================================================================
54 #include <pkgconf/hal.h>
56 #ifdef CYGDBG_HAL_V850_ICE
59 #include <cyg/infra/cyg_type.h>
60 #include <cyg/hal/dbg-threads-api.h>
61 #include <cyg/hal/nec-stub.h>
62 #include <cyg/hal/hal_arch.h>
67 #include <cyg/infra/diag.h>
70 /* ----------------------------------------------------------------------- */
71 /* Common ICE syscall information */
73 /* Magic area for syscall information, from vectors.S */
74 __externC char hal_v85x_ice_syscall_info[];
76 /* Syscall operation codes. This is a "contract" with the host. */
78 #define V850ICE_SYSCALL_GET_THREADNEXT 1
79 #define V850ICE_SYSCALL_GET_THREADREGS 2
80 #define V850ICE_SYSCALL_SET_THREADREGS 3
81 #define V850ICE_SYSCALL_GET_CURRTHREAD 4
82 #define V850ICE_SYSCALL_GET_THREADINFO 5
83 #define V850ICE_SYSCALL_CONSOLE_INPUT 6
85 /* System call information area layout */
86 #define ICE_SYSCALL_INFO_VALIDATOR (*(int *)&hal_v85x_ice_syscall_info[0])
87 #define ICE_SYSCALL_INFO_STARTPC (*(int *)&hal_v85x_ice_syscall_info[4])
88 #define ICE_SYSCALL_INFO_ENDPC (*(int *)&hal_v85x_ice_syscall_info[8])
89 #define ICE_SYSCALL_INFO_STACK (*(int *)&hal_v85x_ice_syscall_info[12])
90 #define ICE_SYSCALL_INFO_IOBUF (*(int *)&hal_v85x_ice_syscall_info[16])
91 #define ICE_SYSCALL_INFO_DIAGOUTPC (*(int *)&hal_v85x_ice_syscall_info[20])
92 #define ICE_SYSCALL_INFO_DIAGOUTBUF (*(int *)&hal_v85x_ice_syscall_info[24])
93 #define ICE_SYSCALL_INFO_DIAGOUTBUFEND (*(int *)&hal_v85x_ice_syscall_info[28])
95 /* We can't use normal memcpy when invoked via the ICE. It may be unsafe. */
97 my_memcpy( void *vd, const void *vs, int n)
100 char *s = (char *)vs;
107 my_memset( void *vs, char c, int n)
109 char *s = (char *)vs;
115 /* ----------------------------------------------------------------------- */
116 /* Support for diag output via ICE */
118 #ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG
120 #include <cyg/hal/hal_if.h>
122 static volatile cyg_uint8 v850ice_output_buf[128];
123 static volatile cyg_uint8 *v850ice_output_end = v850ice_output_buf;
124 #define OUTPUT_BUF_END (&v850ice_output_buf[ sizeof(v850ice_output_buf)])
125 static volatile cyg_uint8 v850ice_input_buf[128];
126 #define INPUT_BUF_END (&v850ice_input_buf[ sizeof(v850ice_input_buf)])
127 static volatile cyg_uint8 *v850ice_input_ptr_put = v850ice_input_buf;
128 static volatile cyg_uint8 *v850ice_input_ptr_get = v850ice_input_buf;
129 static volatile cyg_uint8 v850ice_input_buf_bytes_used = 0;
131 __externC void hal_v850_ice_output_break(void);
134 hal_v850_ice_indicate_output(void)
136 HAL_BREAKPOINT(hal_v850_ice_output_break);
139 // Actually write character
141 cyg_hal_plf_diag_ice_putc(void* __ch_data, cyg_uint8 c)
143 CYGARC_HAL_SAVE_GP();
146 *v850ice_output_end++ = c;
149 v850ice_output_end == OUTPUT_BUF_END) {
150 hal_v850_ice_indicate_output();
151 v850ice_output_end = v850ice_output_buf;
154 CYGARC_HAL_RESTORE_GP();
158 cyg_hal_plf_diag_ice_getc_nonblock(void* __ch_data, cyg_uint8* ch)
160 if ( v850ice_input_buf_bytes_used == 0 )
161 return false; // buffer empty
163 *ch = *v850ice_input_ptr_get++;
164 if ( v850ice_input_ptr_get == INPUT_BUF_END ) {
165 v850ice_input_ptr_get = v850ice_input_buf;
168 v850ice_input_buf_bytes_used--;
174 cyg_hal_plf_diag_ice_getc(void* __ch_data)
177 CYGARC_HAL_SAVE_GP();
179 while(!cyg_hal_plf_diag_ice_getc_nonblock(__ch_data, &ch));
181 CYGARC_HAL_RESTORE_GP();
186 cyg_hal_plf_diag_ice_receive_char(cyg_uint8 ch)
189 if ( v850ice_input_buf_bytes_used == sizeof(v850ice_input_buf) )
192 *v850ice_input_ptr_put++ = ch;
194 if ( v850ice_input_ptr_put == INPUT_BUF_END ) {
195 v850ice_input_ptr_put = v850ice_input_buf;
201 cyg_hal_plf_diag_ice_write(void* __ch_data, const cyg_uint8* __buf,
204 CYGARC_HAL_SAVE_GP();
206 #define MIN(__x, __y) ((__x) < (__y) ? (__x) : (__y))
209 int copylen = MIN(__len,
210 (cyg_uint32) (OUTPUT_BUF_END - v850ice_output_end));
212 my_memcpy( (void *)v850ice_output_buf, __buf, copylen );
214 v850ice_output_end += copylen;
215 hal_v850_ice_indicate_output();
216 v850ice_output_end = v850ice_output_buf;
219 CYGARC_HAL_RESTORE_GP();
223 cyg_hal_plf_diag_ice_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
225 CYGARC_HAL_SAVE_GP();
228 *__buf++ = cyg_hal_plf_diag_ice_getc(__ch_data);
230 CYGARC_HAL_RESTORE_GP();
233 static cyg_int32 msec_timeout = 1000;
236 cyg_hal_plf_diag_ice_getc_timeout(void* __ch_data, cyg_uint8* ch)
238 int delay_count = msec_timeout * 10; // delay in .1 ms steps
240 CYGARC_HAL_SAVE_GP();
243 res = cyg_hal_plf_diag_ice_getc_nonblock(__ch_data, ch);
244 if (res || 0 == delay_count--)
247 CYGACC_CALL_IF_DELAY_US(100);
250 CYGARC_HAL_RESTORE_GP();
255 cyg_hal_plf_diag_ice_control(void *__ch_data, __comm_control_cmd_t __func, ...)
257 static int irq_state = 0;
259 CYGARC_HAL_SAVE_GP();
262 case __COMMCTL_IRQ_ENABLE:
265 case __COMMCTL_IRQ_DISABLE:
269 case __COMMCTL_DBG_ISR_VECTOR:
272 case __COMMCTL_SET_TIMEOUT:
276 va_start(ap, __func);
279 msec_timeout = va_arg(ap, cyg_uint32);
286 CYGARC_HAL_RESTORE_GP();
291 cyg_hal_plf_diag_ice_isr(void *__ch_data, int* __ctrlc,
292 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
294 CYGARC_HAL_SAVE_GP();
296 CYGARC_HAL_RESTORE_GP();
301 cyg_hal_plf_ice_diag_init()
303 hal_virtual_comm_table_t* comm;
304 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
307 ICE_SYSCALL_INFO_DIAGOUTPC = (int)&hal_v850_ice_output_break;
308 ICE_SYSCALL_INFO_DIAGOUTBUF = (int)&v850ice_output_buf[0];
309 ICE_SYSCALL_INFO_DIAGOUTBUFEND = (int)&v850ice_output_end;
311 // Setup procs in the vector table
314 CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
315 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
316 CYGACC_COMM_IF_CH_DATA_SET(*comm, 0);
317 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_diag_ice_write);
318 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_diag_ice_read);
319 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_diag_ice_putc);
320 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_diag_ice_getc);
321 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_diag_ice_control);
322 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_diag_ice_isr);
323 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_diag_ice_getc_timeout);
325 // Restore original console
326 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
329 #endif // ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG
332 /* ----------------------------------------------------------------------- */
333 /* Support for debugging via ICE */
335 #define ICE_STACK_SIZE 1024/sizeof(int)
336 static int ice_stack[ICE_STACK_SIZE]; // ints so as to ensure alignment
337 static int ice_iobuf[128];
340 hal_v85x_ice_syscall_end(void)
346 hal_v85x_ice_syscall(void)
352 case V850ICE_SYSCALL_GET_THREADNEXT:
355 threadref currthread, nextthread;
358 /* Unmarshall thread ref */
359 my_memcpy( &currthread, &ice_iobuf[2], 8 );
361 diag_printf("*NEXTTHREAD* currthread=%08x,%08x\n",
362 *(int *)&currthread[0],
363 *(int *)(((char *)&currthread[0])+4));
366 if ((ice_iobuf[2] == 0) &&
367 (ice_iobuf[3] == 0)) {
369 diag_printf("null threadref\n");
371 ret = dbg_threadlist( 1, NULL, &nextthread );
374 diag_printf("non-null threadref\n");
376 ret = dbg_threadlist( 0, &currthread, &nextthread );
379 diag_printf("*NEXTTHREAD* nextthread=%08x,%08x\n",
380 *(int *)&nextthread[0],
381 *(int *)(((char *)&nextthread[0])+4));
383 if (ret) { // if valid thread found
384 thread_id = dbg_thread_id( &nextthread );
385 /* Returns 0 on error */
386 if (thread_id != 0) {
387 ice_iobuf[1] = thread_id;
388 my_memcpy( &ice_iobuf[2], nextthread, 8 );
390 // set return data size to 12
396 diag_printf("%x, ", ice_iobuf[i]);
406 my_memset( &ice_iobuf[1], 0, 12 );
410 case V850ICE_SYSCALL_GET_THREADREGS:
415 /* Unmarshall thread ref */
416 my_memcpy( &thread, &ice_iobuf[2], 8 );
418 diag_printf("*GTHREADREGS* thread=%08x,%08x\n", *(int *)&thread[0],
419 *(int *)(((char *)&thread[0])+4));
421 ret = dbg_getthreadreg( &thread, NUMREGS, &ice_iobuf[1]);
423 ice_iobuf[0] = NUMREGS * 4;
429 case V850ICE_SYSCALL_SET_THREADREGS:
434 /* Unmarshall thread ref */
435 my_memcpy( &thread, &ice_iobuf[2], 8 );
437 diag_printf("*STHREADREGS* thread=%08x,%08x\n", *(int *)&thread[0],
438 *(int *)(((char *)&thread[0])+4));
440 ret = dbg_setthreadreg( &thread, NUMREGS, &ice_iobuf[4]);
447 case V850ICE_SYSCALL_GET_CURRTHREAD:
452 ret = dbg_currthread( &thread );
454 diag_printf("*CURRTHREAD* thread=%08x,%08x\n", *(int *)&thread[0],
455 *(int *)(((char *)&thread[0])+4));
459 thread_id = dbg_thread_id( &thread );
460 /* Returns 0 on error */
461 if (thread_id != 0) {
462 ice_iobuf[1] = thread_id;
463 my_memcpy( &ice_iobuf[2], thread, 8 );
475 case V850ICE_SYSCALL_GET_THREADINFO:
479 struct cygmon_thread_debug_info info;
480 char *s=(char *)&ice_iobuf[1], *p;
482 /* Unmarshall thread ref */
483 my_memcpy( &thread, &ice_iobuf[2], 8 );
485 diag_printf("*INFO* thread=%08x,%08x\n", *(int *)&thread[0],
486 *(int *)(((char *)&thread[0])+4));
489 ret = dbg_threadinfo( &thread, &info );
491 if (info.thread_display) {
492 my_memcpy (s, "State: ", 7);
494 p = info.thread_display;
500 if (info.unique_thread_name && info.unique_thread_name[0]) {
501 my_memcpy (s, ", Name: ", 8);
503 p = info.unique_thread_name;
509 if (info.more_display) {
510 my_memcpy (s, ", ", 2);
512 p = info.more_display;
521 ice_iobuf[0] = s - (char *)&ice_iobuf[1];
526 case V850ICE_SYSCALL_CONSOLE_INPUT:
528 #ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG
529 int len = ice_iobuf[0];
532 for (i=1; i <= len; i++) {
533 if (false == cyg_hal_plf_diag_ice_receive_char(ice_iobuf[i]))
543 // set return data size to 0
547 hal_v85x_ice_syscall_end();
550 class Cyg_dummy_ice_syscall_init_class {
552 Cyg_dummy_ice_syscall_init_class() {
554 const int valid_string = 0x45434956; // "VICE"
556 ICE_SYSCALL_INFO_STARTPC = (int)&hal_v85x_ice_syscall;
557 ICE_SYSCALL_INFO_ENDPC = (int)&hal_v85x_ice_syscall_end;
558 // top of stack, less 4 ints for parameter flushback area as per ABI
559 ICE_SYSCALL_INFO_STACK = (int)&ice_stack[ICE_STACK_SIZE-4];
560 ICE_SYSCALL_INFO_IOBUF = (int)&ice_iobuf[0];
562 HAL_REORDER_BARRIER();
564 // Leave validation string to last
565 ICE_SYSCALL_INFO_VALIDATOR = valid_string;
569 static Cyg_dummy_ice_syscall_init_class dummy_syscall_class;
571 #endif // ifdef CYGDBG_HAL_V850_ICE