Merge pull request #151 from gsmcmullin/self_semihost
Use semihosting for debug output if available.
This commit is contained in:
commit
1f3576928c
|
@ -26,6 +26,7 @@ struct exception *innermost_exception;
|
||||||
void raise_exception(uint32_t type, const char *msg)
|
void raise_exception(uint32_t type, const char *msg)
|
||||||
{
|
{
|
||||||
struct exception *e;
|
struct exception *e;
|
||||||
|
DEBUG("Exception: %s\n", msg);
|
||||||
for (e = innermost_exception; e; e = e->outer) {
|
for (e = innermost_exception; e; e = e->outer) {
|
||||||
if (e->mask & type) {
|
if (e->mask & type) {
|
||||||
e->type = type;
|
e->type = type;
|
||||||
|
|
|
@ -7,11 +7,17 @@ CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \
|
||||||
-Iplatforms/stm32
|
-Iplatforms/stm32
|
||||||
|
|
||||||
LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \
|
LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \
|
||||||
-Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \
|
-Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc \
|
||||||
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \
|
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \
|
||||||
-L../libopencm3/lib
|
-L../libopencm3/lib
|
||||||
LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000
|
LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_DEBUG), 1)
|
||||||
|
LDFLAGS += --specs=rdimon.specs
|
||||||
|
else
|
||||||
|
LDFLAGS += --specs=nosys.specs
|
||||||
|
endif
|
||||||
|
|
||||||
VPATH += platforms/stm32
|
VPATH += platforms/stm32
|
||||||
|
|
||||||
SRC += cdcacm.c \
|
SRC += cdcacm.c \
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include <libopencm3/stm32/f1/rcc.h>
|
#include <libopencm3/stm32/f1/rcc.h>
|
||||||
#include <libopencm3/cm3/scb.h>
|
#include <libopencm3/cm3/scb.h>
|
||||||
|
#include <libopencm3/cm3/scs.h>
|
||||||
#include <libopencm3/cm3/nvic.h>
|
#include <libopencm3/cm3/nvic.h>
|
||||||
#include <libopencm3/stm32/exti.h>
|
#include <libopencm3/stm32/exti.h>
|
||||||
#include <libopencm3/stm32/usart.h>
|
#include <libopencm3/stm32/usart.h>
|
||||||
|
@ -89,6 +90,12 @@ int platform_hwversion(void)
|
||||||
|
|
||||||
void platform_init(void)
|
void platform_init(void)
|
||||||
{
|
{
|
||||||
|
SCS_DEMCR |= SCS_DEMCR_VC_MON_EN;
|
||||||
|
#ifdef ENABLE_DEBUG
|
||||||
|
void initialise_monitor_handles(void);
|
||||||
|
initialise_monitor_handles();
|
||||||
|
#endif
|
||||||
|
|
||||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||||
|
|
||||||
/* Enable peripherals */
|
/* Enable peripherals */
|
||||||
|
@ -287,3 +294,57 @@ static void setup_vbus_irq(void)
|
||||||
exti15_10_isr();
|
exti15_10_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_DEBUG
|
||||||
|
enum {
|
||||||
|
RDI_SYS_OPEN = 0x01,
|
||||||
|
RDI_SYS_WRITE = 0x05,
|
||||||
|
RDI_SYS_ISTTY = 0x09,
|
||||||
|
};
|
||||||
|
|
||||||
|
int rdi_write(int fn, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
(void)fn;
|
||||||
|
if (debug_bmp)
|
||||||
|
return len - usbuart_debug_write(buf, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ex_frame {
|
||||||
|
union {
|
||||||
|
int syscall;
|
||||||
|
int retval;
|
||||||
|
};
|
||||||
|
const int *params;
|
||||||
|
uint32_t r2, r3, r12, lr, pc;
|
||||||
|
};
|
||||||
|
|
||||||
|
void debug_monitor_handler_c(struct ex_frame *sp)
|
||||||
|
{
|
||||||
|
/* Return to after breakpoint instruction */
|
||||||
|
sp->pc += 2;
|
||||||
|
|
||||||
|
switch (sp->syscall) {
|
||||||
|
case RDI_SYS_OPEN:
|
||||||
|
sp->retval = 1;
|
||||||
|
break;
|
||||||
|
case RDI_SYS_WRITE:
|
||||||
|
sp->retval = rdi_write(sp->params[0], (void*)sp->params[1], sp->params[2]);
|
||||||
|
break;
|
||||||
|
case RDI_SYS_ISTTY:
|
||||||
|
sp->retval = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sp->retval = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
asm(".globl debug_monitor_handler\n"
|
||||||
|
".thumb_func\n"
|
||||||
|
"debug_monitor_handler: \n"
|
||||||
|
" mov r0, sp\n"
|
||||||
|
" b debug_monitor_handler_c\n");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -149,9 +149,9 @@
|
||||||
|
|
||||||
#ifdef ENABLE_DEBUG
|
#ifdef ENABLE_DEBUG
|
||||||
extern bool debug_bmp;
|
extern bool debug_bmp;
|
||||||
void usbuart_debug_outf(const char *fmt, ...);
|
int usbuart_debug_write(const char *buf, size_t len);
|
||||||
|
|
||||||
#define DEBUG(...) if (debug_bmp) {usbuart_debug_outf("bmp: ");usbuart_debug_outf(__VA_ARGS__);}
|
#define DEBUG printf
|
||||||
#else
|
#else
|
||||||
#define DEBUG(...)
|
#define DEBUG(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -193,44 +193,19 @@ void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USBUART_DEBUG
|
#ifdef USBUART_DEBUG
|
||||||
#include <stdarg.h>
|
int usbuart_debug_write(const char *buf, size_t len)
|
||||||
|
|
||||||
/* Function to output debug data to usbuart port (ttyACM1 on linux) */
|
|
||||||
void usbuart_debug_outf(const char *fmt, ...)
|
|
||||||
{
|
{
|
||||||
va_list ap;
|
for (size_t i = 0; i < len; i++) {
|
||||||
char *buf, *tmp;
|
if (buf[i] == '\n') {
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
if (vasprintf(&buf, fmt, ap) < 0)
|
|
||||||
return;
|
|
||||||
tmp = buf;
|
|
||||||
while( *tmp != 0 )
|
|
||||||
{
|
|
||||||
if( *tmp == '\n' && *(tmp-1) != '\r' )
|
|
||||||
{
|
|
||||||
/* insert into FIFO */
|
|
||||||
buf_rx[buf_rx_in++] = '\r';
|
buf_rx[buf_rx_in++] = '\r';
|
||||||
|
buf_rx_in %= FIFO_SIZE;
|
||||||
/* wrap out pointer */
|
|
||||||
if (buf_rx_in >= FIFO_SIZE)
|
|
||||||
{
|
|
||||||
buf_rx_in = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* insert into FIFO */
|
|
||||||
buf_rx[buf_rx_in++] = *(tmp++);
|
|
||||||
|
|
||||||
/* wrap out pointer */
|
|
||||||
if (buf_rx_in >= FIFO_SIZE)
|
|
||||||
{
|
|
||||||
buf_rx_in = 0;
|
|
||||||
}
|
}
|
||||||
|
buf_rx[buf_rx_in++] = buf[i];
|
||||||
|
buf_rx_in %= FIFO_SIZE;
|
||||||
}
|
}
|
||||||
/* enable deferred processing if we put data in the FIFO */
|
/* enable deferred processing if we put data in the FIFO */
|
||||||
timer_enable_irq(USBUSART_TIM, TIM_DIER_UIE);
|
timer_enable_irq(USBUSART_TIM, TIM_DIER_UIE);
|
||||||
free(buf);
|
return len;
|
||||||
va_end(ap);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,8 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
|
|
||||||
/* CIDR preamble sanity check */
|
/* CIDR preamble sanity check */
|
||||||
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
|
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
|
||||||
DEBUG("0x%X: 0x%X <- does not match preamble (0x%X)\n", addr, cidr, CID_PREAMBLE);
|
DEBUG("0x%"PRIx32": 0x%"PRIx32" <- does not match preamble (0x%X)\n",
|
||||||
|
addr, cidr, CID_PREAMBLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +294,8 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
* any components by other designers.
|
* any components by other designers.
|
||||||
*/
|
*/
|
||||||
if ((pidr & ~(PIDR_REV_MASK | PIDR_PN_MASK)) != PIDR_ARM_BITS) {
|
if ((pidr & ~(PIDR_REV_MASK | PIDR_PN_MASK)) != PIDR_ARM_BITS) {
|
||||||
DEBUG("0x%X: 0x%"PRIx64" <- does not match ARM JEP-106\n", addr, pidr);
|
DEBUG("0x%"PRIx32": 0x%"PRIx64" <- does not match ARM JEP-106\n",
|
||||||
|
addr, pidr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +307,7 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
|
for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
|
||||||
if (pidr_pn_bits[i].part_number == part_number) {
|
if (pidr_pn_bits[i].part_number == part_number) {
|
||||||
DEBUG("0x%X: %s - %s %s\n", addr,
|
DEBUG("0x%"PRIx32": %s - %s %s\n", addr,
|
||||||
cidc_debug_strings[cid_class],
|
cidc_debug_strings[cid_class],
|
||||||
pidr_pn_bits[i].type,
|
pidr_pn_bits[i].type,
|
||||||
pidr_pn_bits[i].full);
|
pidr_pn_bits[i].full);
|
||||||
|
@ -334,7 +336,7 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pidr_pn_bits[i].arch == aa_end) {
|
if (pidr_pn_bits[i].arch == aa_end) {
|
||||||
DEBUG("0x%X: %s - Unknown (PIDR = 0x%"PRIx64")\n", addr,
|
DEBUG("0x%"PRIx32": %s - Unknown (PIDR = 0x%"PRIx64")\n", addr,
|
||||||
cidc_debug_strings[cid_class], pidr);
|
cidc_debug_strings[cid_class], pidr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +379,7 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
|
||||||
ap->csw &= ~ADIV5_AP_CSW_TRINPROG;
|
ap->csw &= ~ADIV5_AP_CSW_TRINPROG;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(" AP %3d: IDR=%08X CFG=%08X BASE=%08X CSW=%08X\n",
|
DEBUG(" AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08"PRIx32" CSW=%08"PRIx32"\n",
|
||||||
apsel, ap->idr, ap->cfg, ap->base, ap->csw);
|
apsel, ap->idr, ap->cfg, ap->base, ap->csw);
|
||||||
|
|
||||||
return ap;
|
return ap;
|
||||||
|
|
|
@ -211,7 +211,8 @@ static uint32_t va_to_pa(target *t, uint32_t va)
|
||||||
if (par & 1)
|
if (par & 1)
|
||||||
priv->mmu_fault = true;
|
priv->mmu_fault = true;
|
||||||
uint32_t pa = (par & ~0xfff) | (va & 0xfff);
|
uint32_t pa = (par & ~0xfff) | (va & 0xfff);
|
||||||
DEBUG("%s: VA = 0x%08X, PAR = 0x%08X, PA = 0x%08X\n", __func__, va, par, pa);
|
DEBUG("%s: VA = 0x%08"PRIx32", PAR = 0x%08"PRIx32", PA = 0x%08"PRIX32"\n",
|
||||||
|
__func__, va, par, pa);
|
||||||
return pa;
|
return pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +413,7 @@ bool cortexa_attach(target *t)
|
||||||
dbgdscr |= DBGDSCR_HDBGEN | DBGDSCR_ITREN;
|
dbgdscr |= DBGDSCR_HDBGEN | DBGDSCR_ITREN;
|
||||||
dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_STALL;
|
dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_STALL;
|
||||||
apb_write(t, DBGDSCR, dbgdscr);
|
apb_write(t, DBGDSCR, dbgdscr);
|
||||||
DEBUG("DBGDSCR = 0x%08x\n", dbgdscr);
|
DEBUG("DBGDSCR = 0x%08"PRIx32"\n", dbgdscr);
|
||||||
|
|
||||||
target_halt_request(t);
|
target_halt_request(t);
|
||||||
tries = 10;
|
tries = 10;
|
||||||
|
@ -604,7 +605,7 @@ static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch)
|
||||||
if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */
|
if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */
|
||||||
return TARGET_HALT_RUNNING;
|
return TARGET_HALT_RUNNING;
|
||||||
|
|
||||||
DEBUG("%s: DBGDSCR = 0x%08x\n", __func__, dbgdscr);
|
DEBUG("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr);
|
||||||
/* Reenable DBGITR */
|
/* Reenable DBGITR */
|
||||||
dbgdscr |= DBGDSCR_ITREN;
|
dbgdscr |= DBGDSCR_ITREN;
|
||||||
apb_write(t, DBGDSCR, dbgdscr);
|
apb_write(t, DBGDSCR, dbgdscr);
|
||||||
|
@ -631,7 +632,7 @@ void cortexa_halt_resume(target *t, bool step)
|
||||||
if (step) {
|
if (step) {
|
||||||
uint32_t addr = priv->reg_cache.r[15];
|
uint32_t addr = priv->reg_cache.r[15];
|
||||||
uint32_t bas = bp_bas(addr, (priv->reg_cache.cpsr & CPSR_THUMB) ? 2 : 4);
|
uint32_t bas = bp_bas(addr, (priv->reg_cache.cpsr & CPSR_THUMB) ? 2 : 4);
|
||||||
DEBUG("step 0x%08x %x\n", addr, bas);
|
DEBUG("step 0x%08"PRIx32" %"PRIx32"\n", addr, bas);
|
||||||
/* Set match any breakpoint */
|
/* Set match any breakpoint */
|
||||||
apb_write(t, DBGBVR(0), priv->reg_cache.r[15] & ~3);
|
apb_write(t, DBGBVR(0), priv->reg_cache.r[15] & ~3);
|
||||||
apb_write(t, DBGBCR(0), DBGBCR_INST_MISMATCH | bas |
|
apb_write(t, DBGBCR(0), DBGBCR_INST_MISMATCH | bas |
|
||||||
|
@ -658,7 +659,7 @@ void cortexa_halt_resume(target *t, bool step)
|
||||||
do {
|
do {
|
||||||
apb_write(t, DBGDRCR, DBGDRCR_CSE | DBGDRCR_RRQ);
|
apb_write(t, DBGDRCR, DBGDRCR_CSE | DBGDRCR_RRQ);
|
||||||
dbgdscr = apb_read(t, DBGDSCR);
|
dbgdscr = apb_read(t, DBGDSCR);
|
||||||
DEBUG("%s: DBGDSCR = 0x%08x\n", __func__, dbgdscr);
|
DEBUG("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr);
|
||||||
} while (!(dbgdscr & DBGDSCR_RESTARTED));
|
} while (!(dbgdscr & DBGDSCR_RESTARTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -841,8 +841,8 @@ static int cortexm_hostio_request(target *t)
|
||||||
uint32_t syscall = arm_regs[0];
|
uint32_t syscall = arm_regs[0];
|
||||||
int32_t ret = 0;
|
int32_t ret = 0;
|
||||||
|
|
||||||
DEBUG("syscall 0x%x (%x %x %x %x)\n", syscall,
|
DEBUG("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n",
|
||||||
params[0], params[1], params[2], params[3]);
|
syscall, params[0], params[1], params[2], params[3]);
|
||||||
switch (syscall) {
|
switch (syscall) {
|
||||||
case SYS_OPEN:{ /* open */
|
case SYS_OPEN:{ /* open */
|
||||||
/* Translate stupid fopen modes to open flags.
|
/* Translate stupid fopen modes to open flags.
|
||||||
|
|
|
@ -254,7 +254,7 @@ bool sam3x_probe(target *t)
|
||||||
static int
|
static int
|
||||||
sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg)
|
sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg)
|
||||||
{
|
{
|
||||||
DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n",
|
DEBUG("%s: base = 0x%08"PRIx32" cmd = 0x%02X, arg = 0x%06X\n",
|
||||||
__func__, base, cmd, arg);
|
__func__, base, cmd, arg);
|
||||||
target_mem_write32(t, EEFC_FCR(base),
|
target_mem_write32(t, EEFC_FCR(base),
|
||||||
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
|
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
|
||||||
|
|
Loading…
Reference in New Issue