You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.8 KiB
141 lines
3.8 KiB
/**
|
|
* @file TeensyDebug.cpp
|
|
* @author Fernando Trias
|
|
* @brief Implement GDB stub using TeensyDebug interface
|
|
* @version 0.1
|
|
* @date 2020-06-09
|
|
*
|
|
* @copyright Copyright (c) 2020 Fernando Trias
|
|
*
|
|
*/
|
|
|
|
#ifndef TEENSY_DEBUG_H
|
|
#define TEENSY_DEBUG_H
|
|
|
|
// is this a Teensy 3.2? If so, we can support hardware interrupts
|
|
// and should hijack setup() to set that up.
|
|
#ifdef __MK20DX256__
|
|
#define HAS_FP_MAP
|
|
#endif
|
|
|
|
//
|
|
// Need to know where RAM starts/stops so we know where
|
|
// software breakpoints are possible
|
|
//
|
|
|
|
#ifdef __MK20DX256__
|
|
#define RAM_START ((void*)0x1FFF8000)
|
|
#define RAM_END ((void*)0x2FFFFFFF)
|
|
#endif
|
|
|
|
#ifdef __IMXRT1062__
|
|
#define RAM_START ((void*)0x00000020)
|
|
#define RAM_END ((void*)0x20280000)
|
|
#endif
|
|
|
|
|
|
#if defined(GDB_DUAL_SERIAL) && ! defined(CDC2_DATA_INTERFACE)
|
|
#error "You must use Dual Serial or Triple Serial to enable GDB on Dual Serial."
|
|
#endif
|
|
|
|
#if defined(GDB_TAKE_OVER_SERIAL) && ! defined(CDC_DATA_INTERFACE)
|
|
#error "You must use a USB setup with Serial to enable GDB to take over a Serial interface."
|
|
#endif
|
|
|
|
#if defined(HAS_FP_MAP) || defined(GDB_DUAL_SERIAL) || defined(GDB_TAKE_OVER_SERIAL)
|
|
#define REMAP_SETUP
|
|
#endif
|
|
|
|
// If this is used internally, not need to remap
|
|
#ifdef GDB_DEBUG_INTERNAL
|
|
|
|
|
|
#else
|
|
|
|
#ifdef REMAP_SETUP
|
|
// rename the original setup() because we need to hijack it
|
|
#define setup setup_main
|
|
#endif
|
|
|
|
#ifdef GDB_TAKE_OVER_SERIAL
|
|
#define Serial debug
|
|
#endif
|
|
|
|
#endif
|
|
|
|
int hcdebug_isEnabled(int n);
|
|
int hcdebug_setBreakpoint(int n);
|
|
|
|
// int debug_setBreakpoint(void *p, int n);
|
|
// int debug_clearBreakpoint(void *p, int n);
|
|
// void debug_setCallback(void (*c)());
|
|
// uint32_t debug_getRegister(const char *reg);
|
|
|
|
size_t gdb_out_write(const uint8_t *msg, size_t len);
|
|
int gdb_file_io(const char *msg);
|
|
extern int file_io_errno;
|
|
extern int gdb_active_flag;
|
|
|
|
#define O_CREAT 0x200
|
|
#define O_APPEND 8
|
|
#define O_RDONLY 0
|
|
#define O_WRONLY 1
|
|
#define O_RDWR 2
|
|
class DebugFileIO {
|
|
private:
|
|
char gdb_io[256];
|
|
public:
|
|
int file_errno() { return file_io_errno; }
|
|
int file_open(const char *file, int flags = O_CREAT | O_RDWR, int mode = 0644) {
|
|
sprintf(gdb_io, "Fopen,%x/%x,%x,%x", (unsigned int)file, strlen(file), flags, mode);
|
|
return gdb_file_io(gdb_io);
|
|
}
|
|
int file_close(int fd) {
|
|
sprintf(gdb_io, "Fclose,%x", fd);
|
|
return gdb_file_io(gdb_io);
|
|
}
|
|
int file_read(int fd, void *buf, unsigned int count) {
|
|
sprintf(gdb_io, "Fread,%x,%x,%x", fd, (unsigned int)buf, count);
|
|
return gdb_file_io(gdb_io);
|
|
}
|
|
int file_write(int fd, const void *buf, unsigned int count) {
|
|
sprintf(gdb_io, "Fwrite,%x,%x,%x", fd, (unsigned int)buf, count);
|
|
return gdb_file_io(gdb_io);
|
|
}
|
|
int file_system(const char *buf) {
|
|
sprintf(gdb_io, "Fsystem,%x/%x", (unsigned int)buf, strlen(buf));
|
|
return gdb_file_io(gdb_io);
|
|
}
|
|
};
|
|
|
|
class Debug : public Print, public DebugFileIO {
|
|
public:
|
|
int begin(Stream *device = NULL);
|
|
int begin(Stream &device) { return begin(&device); }
|
|
int setBreakpoint(void *p, int n=1);
|
|
int clearBreakpoint(void *p, int n=1);
|
|
void setCallback(void (*c)());
|
|
uint32_t getRegister(const char *reg);
|
|
int setRegister(const char *reg, uint32_t value);
|
|
int restoreRunMode();
|
|
int isGDBConnected() { return gdb_active_flag; }
|
|
|
|
virtual size_t write(uint8_t b) {
|
|
return write(&b, 1);
|
|
};
|
|
virtual size_t write(const uint8_t *buffer, size_t size) {
|
|
return gdb_out_write(buffer, size);
|
|
}
|
|
virtual int availableForWrite(void) { return 128; }
|
|
virtual void flush() { }
|
|
};
|
|
|
|
extern Debug debug;
|
|
|
|
#define breakpoint(n) {if (hcdebug_isEnabled(n)) {asm volatile("svc #0x11");}}
|
|
#define breakpoint_enable(n) {hcdebug_setBreakpoint(n);}
|
|
#define halt() {asm volatile("svc #0x11");}
|
|
// #define triggerBreakpoint() { NVIC_SET_PENDING(IRQ_SOFTWARE); }
|
|
#define DEBUGRUN __attribute__ ((section(".fastrun"), noinline, noclone ))
|
|
|
|
#endif
|
|
|