From d50dd5ab9567cc308e412c5e9e775dc8e15fb509 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan Date: Fri, 3 Feb 2012 23:57:04 +0100 Subject: merge armdebug rc1 This enables the use of GDB or GDB based debuggers to debug the code running on the NXT brick using the USB connection. --- .../armdebug/Debugger/debug_runlooptasks.S | 415 +++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S (limited to 'AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S') diff --git a/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S b/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S new file mode 100644 index 0000000..3bcf35a --- /dev/null +++ b/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S @@ -0,0 +1,415 @@ +/** @file debug_runlooptasks.S + * @brief GDB Server platform Run Loop + * + */ + +/* Copyright (C) 2007-2011 the NxOS developers + * + * Module Developed by: TC Wan + * + * 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__ + +#define REBOOT_POWERDOWN +#include "debug_runlooptasks.h" + +#include "debug_internals.h" +#include "debug_macros.h" +#include "debug_stub.h" + + .code 32 + .align 4 + .global dbg__runloopTasks + .global dbg__reboot + .global dbg__display_abort_info + .global dbg__sendCommMsg + +#ifdef __NXOS__ +/**************************************************************************** + * + * NxOS Run Loop + * + ****************************************************************************/ +dbg__runloopTasks: +/* Currently, there's nothing that needs to be done in the NxOS Run Loop */ + push {lr} + mov r0, #1 /* 1 ms delay */ + bl nx_systick_wait_ms + pop {pc} + +#else +/**************************************************************************** + * + * NXT Firmware Run Loop + * + ****************************************************************************/ +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__ +/**************************************************************************** + * + * NxOS Reboot Routine + * + ****************************************************************************/ + dbg__reboot: +#ifdef REBOOT_POWERDOWN + b nx_core_halt /* Shutdown Brick, won't return */ +#else + b nx_core_reset /* Reboot Brick, won't return */ +#endif + +#else +/**************************************************************************** + * + * 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 */ + +#ifdef REBOOT_POWERDOWN + /* Powerdown sequence */ + ldr r0, =((POWERDOWN >> 8) & 0xFF) + ldr r1, =dIOCtrlSetPower + mov lr,pc + bx r1 +#else + /* 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__ +/**************************************************************************** + * + * NxOS Abort Info LCD Display Routine + * + ****************************************************************************/ +/* On entry: + * r0: abort type + * On exit: + * r0-r3: destroyed + */ +dbg__display_abort_info: + push {lr} + _getdbgregister DBGSTACK_USERPC_INDEX, r1 /* Retrieve User PC into R2 */ + _getdbgregister DBGSTACK_USERCPSR_INDEX, r2 /* Retrieve User CPSR into R2 */ + bl nx__abort_info /* void nx__abort_info(U32 data, U32 pc, U32 cpsr); */ + pop {pc} + +#else +/**************************************************************************** + * + * NXT Firmware Abort Info LCD Display Routine + * + ****************************************************************************/ +dbg__display_abort_info: +/* FIXME: Inteface with NXT Firmware LCD Display routines */ + push {lr} + pop {pc} +#endif + +#ifdef __NXOS__ + .extern debug_OutCommBuf +/**************************************************************************** + * + * NxOS Communications Driver Interface Routine + * + ****************************************************************************/ +/* dbg__sendCommMsg + * Internal send routine (interfaces with drivers). + * On entry: + * R0: Total Message Buffer length + * On exit: + * R0: Tx Status (TRUE if data sent) + * R1-R3: Destroyed + */ +dbg__sendCommMsg: + stmfd sp!, {r4, lr} + mov r4, r0 /* Keep Comm Buffer length in R4 */ + /* Check USB bus status, transmit message if possible */ + bl nx_usb_is_connected /* R0 = TRUE (#1) if USB is ready */ + teq r0, #0 /* FALSE == #0; + We can't check for True condition since values + used by C-Compiler & ARMDEBUG are different */ + beq dbg__sendCommMsgFailed + + /* Actual transmission (blocking) */ + ldr r0, =debug_OutCommBuf /* data pointer parameter */ + mov r1, r4 /* Comm buffer length */ + bl nx_usb_write + +1: bl nx_usb_data_written /* R0 = True if data has been sent */ + teq r0, #0 /* FALSE == #0; + We can't check for True condition since values + used by C-Compiler & ARMDEBUG are different */ + /* FIXME: implement timeout */ + beq 1b /* Busy Wait Loop */ + + mov r0, #TRUE + b exit_dbg__sendCommMsg +dbg__sendCommMsgFailed: + mov r0, #FALSE + +exit_dbg__sendCommMsg: + ldmfd sp!, {r4, pc} + + +#else +/**************************************************************************** + * + * NXT Firmware Communications Driver Interface Routine + * + ****************************************************************************/ +/* dbg__sendCommMsg + * Internal send routine (interfaces with drivers). + * On entry: + * R0: Total Message Buffer length + * On exit: + R0: Tx Status (TRUE if data sent) + */ +dbg__sendCommMsg: + stmfd sp!, {r4, lr} + mov r4, r0 /* Keep Comm Buffer length in R4 */ + ldr r0, =debug_nxtCommChannel + ldr r0, [r0] /* Get Channel Enum */ + teq r0, #BT_CMD_READY + beq dbg__sendBTMsg + teq r0, #USB_CMD_READY + beq dbg__sendUSBMsg + b dbg__sendCommMsgFailed /* Channel Enum Doesn't Match, shouldn't happen? */ + +dbg__sendBTMsg: + /* NXT BT routines do not have any configuration checks */ + ldr r0, =debug_OutCommBuf /* data pointer parameter */ + mov r1, r4 /* BT Bytes to Send */ + mov r2, r4 /* BT Message Size */ + bl dBtSendMsg /* Send it via Bluetooth (complete message) */ + mov r0, #TRUE /* Always flag Success */ + b exit_dbg__sendCommMsg + +dbg__sendUSBMsg: + /* Check USB bus status, transmit message if possible */ + bl dUsbIsConfigured /* R0: UByte status, TRUE / FALSE */ + teq r0, #nxt_UBYTE_TRUE + bne dbg__sendCommMsgFailed + + /* Actual transmission (blocking) */ + ldr r0, =debug_OutCommBuf /* data pointer parameter */ + mov r1, r4 /* Comm buffer length */ + bl dUsbWrite /* call NXT Firmware USB driver, return 0: done, !0: remaining chars */ + teq r0, #0 /* Tx done if returned length is 0 */ + moveq r0, #TRUE /* Convert NXT firmware return value to our Status (TRUE/FALSE) */ + beq exit_dbg__sendCommMsg +dbg__sendCommMsgFailed: + mov r0, #FALSE + +exit_dbg__sendCommMsg: + ldmfd sp!, {r4, pc} +#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(U8 *buffer, comm_chan_t channel, U32 length); + * + * 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) + */ + bl dbg__copyNxtDebugMsg /* Copy to Debugger Message Buffer, Remember Comm Channel */ + mov r0, #FALSE /* Setup Default Return value (False) */ + _dbg_getmode r1 /* Get Debug Mode */ + cmp r1, #(TRUE & BYTE0) /* Confine it to Byte size */ + /* If Debug Mode is TRUE, this means that we're already running the Debugger */ + 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 /* Copy to Debugger Message Buffer, Remember Comm Channel */ + _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 -- cgit v1.2.3