summaryrefslogtreecommitdiff
path: root/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S
blob: f00e99da2baaf44e07a3e597cfef1ade3828ac21 (plain)
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
/** @file debug_runlooptasks.S
 *  @brief GDB Server platform Run Loop
 *
 */

/* Copyright (C) 2007-2011 the NxOS developers
 *
 * Module Developed by: TC Wan <tcwan@cs.usm.my>
 *
 * See AUTHORS for a full list of the developers.
 *
 * See COPYING for redistribution license
 *
 */

/*
 * This file contains platform specific code.
 * This include ABORT Mode Debugger Run Loop operation,
 * as well as Debugger Interfacing code to the platform code.
 */

/*
 * The Debugger has to implement a Run Loop in ABORT mode
 * since the hardware is still running. Consequently,
 * the communications subsystems such as USB (and Bluetooth?)
 * which is used to communicate with the Host needs to be
 * serviced in order for actual data transmission and reception
 * to take place. Currently we're reusing the platform's
 * communication routines to do the actual tx/rx, so it means
 * that it is not possible to set breakpoints in those modules.
 * In addition, since the platform communication modules may
 * handle other tasks, it is currently possible to enter an
 * indeterminate state where certain communication messages trigger
 * a platform response which cannot be handled by the Debugger Run Loop.
 * The alternative is to implement our own communications routines, but
 * that will take even more code.
 *
 * FIXME: It may become necessary to hack the platform communications
 * routines to detect that we're in the Debugger Run Loop and not the
 * normal run loop to avoid system crashes, but the current goal is to
 * have as minimal changes to the platform code as possible.
 *
 * Since there are two Run Loops for the platform, the way in which
 * they interact is as follows:
 *
 * [Platform Run Loop]  - DBG_INIT/ GDB Cmd/ BKPT ->  [Debugger Run Loop]
 *                    \ <------ GO/ STEP/ CONT ----- /
 *        ...                                                 ...
 *        ...                                         Handle GDB Cmd/Resp
 *        ...                                                 ...
 *   {normal runloop                                  {communications /
 *    processing}                                      watchdog routines}
 * ^-------v                                                      v-------^
 *
 * The Platform will invoke dbg__bkpt_init() after hardware and system initialization,
 * before entering the Platform Run Loop. This configures the Debugger, but does not
 * invoke the Debugger Run Loop unless a Manual Breakpoint is found in the platform code.
 *
 * Subsequently, the Debugger Run Loop will be triggered by Breakpoints, or
 * when the communications subsystem receives a GDB Command.
 *
 * The Debugger Run Loop is actually dbg__bkpt_waitCMD(), this file contains
 * the Run Loop Tasks which needs to be invoked periodically by the Run Loop,
 * to minimize the coupling between the ARMDEBUG modules and the Platform.
 *
 * Note: The Debugger Run Loop does not handle Hardware Shutdown, it is
 * assumed that we wouldn't need to do so in Debug Mode.
 *
 */
#define __ASSEMBLY__

#include "debug_internals.h"
#include "debug_macros.h"
#include "debug_stub.h"

	.code 32
	.align 4
    .global dbg__runloopTasks
	.global	dbg__reboot

#ifdef __NXOS__
/****************************************************************************
 *
 * NxOS Run Loop
 *
 ****************************************************************************/
dbg__runloopTasks:
/* Currently, there's nothing that needs to be done in the NxOS Run Loop */
    bx      lr

#else
/****************************************************************************
 *
 * NXT Firmware Run Loop
 *
 ****************************************************************************/
    .extern cCommCtrl

dbg__runloopTasks:
    push    {lr}
    /* FIXME: Add necessary cXXXCtrl calls here */
    bl      cCommCtrl
    /* OSWatchdogWrite is a NULL function in the NXT Firmware?! */
    pop     {pc}
#endif

#ifdef __NXOS__
	.extern 	nx_core_reset
/****************************************************************************
 *
 * NxOS Reboot Routine
 *
 ****************************************************************************/
 dbg__reboot:
	b	    nx_core_reset		/* Reboot Brick, won't return */

#else
	.extern dIOCtrlSetPower
	.extern dIOCtrlSetPwm
	.extern dIOCtrlTransfer
	.equ	BOOT, 0xA55A
	.equ	POWERDOWN, 0x5A00
/****************************************************************************
 *
 * NXT Firmware Reboot Routine
 *
 ****************************************************************************/
dbg__reboot:
	/* Powerdown Sequence
      	dIOCtrlSetPower((POWERDOWN>>8));
		dIOCtrlTransfer();

	   Reboot Sequence
      	dIOCtrlSetPower((UBYTE)(BOOT>>8));
      	dIOCtrlSetPwm((UBYTE)BOOT);
  		dIOCtrlTransfer();
	*/

	/* We implement the powerdown sequence for now */

#if 1
	/* Powerdown sequence */
	ldr		r0, =((POWERDOWN >> 8) & 0xFF)
	ldr		r1, =dIOCtrlSetPower
	mov		lr,pc
	bx		r1
#endif

#if 0
	/* Reboot sequence: this forces SAMBA mode??!! */
	ldr		r0, =((BOOT >> 8) & 0xFF)
	ldr		r1, =dIOCtrlSetPower
	mov		lr,pc
	bx		r1

	ldr		r0, =(BOOT & 0xFF)
	ldr		r1, =dIOCtrlSetPwm
	mov		lr,pc
	bx		r1
#endif

_dbg__reboot_wait:
	ldr		r1, =dIOCtrlTransfer
	mov		lr,pc
	bx		r1

	b		_dbg__reboot_wait						/* Wait for AVR... */
#endif


#ifdef __NXOS__
/****************************************************************************
 *
 * GDB Debugger Invocation Routine for NxOS
 *
 ****************************************************************************/
	.code 32
	.align 4

	.extern dbg__install_singlestep
	.extern dbg__activate_singlestep
	.extern irq_stack_frame_address
	.global nxos__handleDebug
/* nxos__handleDebug
 * 		Prepare to switch to Debug Mode
 * int nxos__handleDebug(comm_chan_t channel);
 *
 * This routine is called from NxOS Fantom library to setup
 * Single Step Breakpoint in preparation for Debugger invocation if we're in
 * normal execution mode.
 *
 * It returns to complete the IRQ handling normally, after which the single
 * step breakpoint will be triggered, and the incoming GDB message will then
 * be processed in the dbg__bkpt_waitCMD() loop.
 *
 * If we're in Debugger Mode already, then just return and let the
 * dbg__bkpt_waitCMD() loop handle it normally.
 *
 * If we're operating in normal NxOS mode, return True (!0)
 * If we're already in Debugger Mode, return False (0)
 */
nxos__handleDebug:
		push {lr}
		/* This routine is called from nx__irq_handler() via fantom_filter_packet().
		 * The operating mode should already have been configured by the IRQ interrupt handler.
		 *
		 * The IRQ Stack Frame Pointer will contains the LR and SPSR from the topmost interrupted task
		 * if it is non-zero (NxOS supports nested IRQs)
		 */

		ldr		r3, =debug_nxtCommChannel
		str		r0, [r3]				/* Keep track of which communications link was used (USB/Bluetooth) */

        /* Check our current operating mode */
 		mov		r0, #FALSE				/* Setup Default Return value (False) */
		mrs		r3, cpsr				/* Copy CPSR to r3 */
 		and 	r3, r3, #CPSR_MODE		/* Get current mode */
 		teq		r3, #MODE_ABT			/* Are we in Abort (Debug) mode? */
 		beq		exit_nxos__handleDebug	/* Yes, return False */

		/* Retrieve ISR Return Address */
        ldr     r3, =irq_stack_frame_address
        ldr		r3, [r3]				/* Get Interrupt Stack Pointer */
        teq		r3, #0
        beq		exit_nxos__handleDebug	/* NULL Interrupt Stack Frame Pointer, exit (status: False) */

nxos_switch2debug:
		/* Since the Interrupt Stack Frame Pointer points to the top of the stack frame,
		 * we'll have to use Load Empty Ascending Stack (LDMEA == LDMDB) to access the variables
		 */
        ldmdb   r3, {r1,r2}				/* R1: LR, R2: SPSR */
 		tst		r2, #CPSR_THUMB			/* Check for Thumb Mode */
 		orrne	r1, r1, #1				/* Configure for Thumb Single Step Breakpoint */
	    bl  	dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
		bl		dbg__activate_singlestep
		mov	    r0, #TRUE				/* We're going to switch to Debug Mode (via Single Step Breakpoint) */

exit_nxos__handleDebug:
		pop	  {r1}
    	bx    r1						/* In case we have Interworking from different caller mode */

#else

/****************************************************************************
 *
 * GDB Debugger Invocation Routine for NXT Firmware
 *
 ****************************************************************************/
    .code 16
    .align 2

    .extern dbg__copyNxtDebugMsg
    .global cCommHandleDebug
    .thumb_func
/* cCommHandleDebug
 * Switch Mode to Debugger.
 *      Used by NXT Firmware only
 *
 * UWORD cCommHandleDebug(UBYTE *pInBuf, UBYTE CmdBit, UWORD MsgLength);
 *
 * This routine is called from cCommInterprete either in normal operation mode (SVC)
 * or else when we're in debug mode (ABORT) which uses the cCommCtrl() routine to handle
 * I/O with the Host.
 *
 * On entry, the message is copied from the NXT buffer into our own buffers.
 *
 * If this is accessed from normal operation mode, we need to switch mode to
 * ABORT mode to handle the incoming message using a Manual Breakpoint instruction.
 * When DEBUG is exited, the execution resumes from the instruction following the Breakpoint.
 */
cCommHandleDebug:
/* Arg Registers are not preserved since this is invoked explicitly */
        push  {lr}                      /* store arg registers */
        bl    dbg__copyNxtDebugMsg  	/* setup Debugger Message Buffers, validate input, CPSR returned in R0 */
        _dbg_getmode r0             	/* Get Debug Mode */
        cmp   r0, #(TRUE & BYTE0)		/* Confine it to Byte size */

        /* If Debug Mode is TRUE, this means that we're already running the Debugger */
		beq	  _cCommHandleDebug_cont
        /* Else, we're in normal operation mode (SVC), or other mode (??!) and need to force a switch to Debug mode */
        dbg__bkpt_thumb
_cCommHandleDebug_cont:
        mov   r0, #0                   /* FIXME: Return Status */
        pop	  {r1}					   /* Can't Pop LR directly */
        bx    r1					   /* Safe code: actually we should be able to Pop PC since the caller is Thumb Mode */

        .ltorg
#endif