Skip to content

Commit

Permalink
Backport realtime behavior in GDB mode
Browse files Browse the repository at this point in the history
  • Loading branch information
maxgerhardt committed May 12, 2022
1 parent 5616a10 commit e036e96
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 74 deletions.
74 changes: 29 additions & 45 deletions simavr/sim/sim_avr.c
Expand Up @@ -30,6 +30,7 @@
#include "sim_core.h"
#include "sim_time.h"
#include "sim_gdb.h"
#include "sim_gdb_types.h"
#include "avr_uart.h"
#include "sim_vcd_file.h"
#include "avr/avr_mcu_section.h"
Expand Down Expand Up @@ -287,51 +288,34 @@ void
avr_callback_run_gdb(
avr_t * avr)
{
avr_gdb_processor(avr, avr->state == cpu_Stopped ? 50000 : 0);

if (avr->state == cpu_Stopped)
return ;

// if we are stepping one instruction, we "run" for one..
int step = avr->state == cpu_Step;
if (step)
avr->state = cpu_Running;

avr_flashaddr_t new_pc = avr->pc;

if (avr->state == cpu_Running) {
new_pc = avr_run_one(avr);
#if CONFIG_SIMAVR_TRACE
avr_dump_state(avr);
#endif
}

// run the cycle timers, get the suggested sleep time
// until the next timer is due
avr_cycle_count_t sleep = avr_cycle_timer_process(avr);

avr->pc = new_pc;

if (avr->state == cpu_Sleeping) {
if (!avr->sreg[S_I]) {
if (avr->log)
AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n");
avr->state = cpu_Done;
return;
}
/*
* try to sleep for as long as we can (?)
*/
avr->sleep(avr, sleep);
avr->cycle += 1 + sleep;
}
// Interrupt servicing might change the PC too, during 'sleep'
if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
avr_service_interrupts(avr);

// if we were stepping, use this state to inform remote gdb
if (step)
avr->state = cpu_StepDone;
avr_gdb_t* g = avr->gdb;

if (avr->state == cpu_Running && gdb_watch_find(&g->breakpoints, avr->pc) != -1) {
gdb_send_quick_status(g, 0);
avr->state = cpu_Stopped;
} else if (avr->state == cpu_StepDone) {
gdb_send_quick_status(g, 0);
avr->state = cpu_Stopped;
}

// this also sleeps for a bit
// gdb_network_handler(g, 0);

if (avr->state == cpu_Stopped) {
gdb_network_handler(g, 0);
return;
}

// if we are stepping one instruction, we "run" for one..
int step = avr->state == cpu_Step;
if (step)
avr->state = cpu_Running;

avr_callback_run_raw(avr);

// if we were stepping, use this state to inform remote gdb
if (step)
avr->state = cpu_StepDone;
}

/*
Expand Down
32 changes: 3 additions & 29 deletions simavr/sim/sim_gdb.c
Expand Up @@ -36,36 +36,10 @@
// For debug printfs: "#define DBG(w) w"
#define DBG(w)

#define WATCH_LIMIT (32)

typedef struct {
uint32_t len; /**< How many points are taken (points[0] .. points[len - 1]). */
struct {
uint32_t addr; /**< Which address is watched. */
uint32_t size; /**< How large is the watched segment. */
uint32_t kind; /**< Bitmask of enum avr_gdb_watch_type values. */
} points[WATCH_LIMIT];
} avr_gdb_watchpoints_t;

typedef struct avr_gdb_t {
avr_t * avr;
int listen; // listen socket
int s; // current gdb connection

avr_gdb_watchpoints_t breakpoints;
avr_gdb_watchpoints_t watchpoints;

// These are used by gdb's "info io_registers" command.

uint16_t ior_base;
uint8_t ior_count, mad;
} avr_gdb_t;


/**
* Returns the index of the watchpoint if found, -1 otherwise.
*/
static int
int
gdb_watch_find(
const avr_gdb_watchpoints_t * w,
uint32_t addr )
Expand Down Expand Up @@ -230,7 +204,7 @@ gdb_send_stop_status(
gdb_send_reply(g, cmd);
}

static void
void
gdb_send_quick_status(
avr_gdb_t * g,
uint8_t signal )
Expand Down Expand Up @@ -780,7 +754,7 @@ gdb_handle_command(
}
}

static int
int
gdb_network_handler(
avr_gdb_t * g,
uint32_t dosleep )
Expand Down
6 changes: 6 additions & 0 deletions simavr/sim/sim_gdb.h
Expand Up @@ -26,6 +26,8 @@
extern "C" {
#endif

#include <sim_gdb_types.h>

/* Watchpoint types.
See GDB User Manual, Appendix E.2 */
enum avr_gdb_watch_type {
Expand All @@ -48,6 +50,10 @@ int avr_gdb_processor(avr_t * avr, int sleep);
void avr_gdb_handle_watchpoints(avr_t * g, uint16_t addr, enum avr_gdb_watch_type type);
void avr_gdb_handle_break(avr_t *);

int gdb_watch_find(const avr_gdb_watchpoints_t * w, uint32_t addr);
void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal);
int gdb_network_handler(avr_gdb_t * g, uint32_t dosleep);

#ifdef __cplusplus
};
#endif
Expand Down
31 changes: 31 additions & 0 deletions simavr/sim/sim_gdb_types.h
@@ -0,0 +1,31 @@
#ifndef AVR_GDB_H
#define AVR_GDB_H

#include <stdint.h>

#define WATCH_LIMIT (32)

typedef struct {
uint32_t len; /**< How many points are taken (points[0] .. points[len - 1]). */
struct {
uint32_t addr; /**< Which address is watched. */
uint32_t size; /**< How large is the watched segment. */
uint32_t kind; /**< Bitmask of enum avr_gdb_watch_type values. */
} points[WATCH_LIMIT];
} avr_gdb_watchpoints_t;

typedef struct avr_gdb_t {
avr_t * avr;
int listen; // listen socket
int s; // current gdb connection

avr_gdb_watchpoints_t breakpoints;
avr_gdb_watchpoints_t watchpoints;

// These are used by gdb's "info io_registers" command.

uint16_t ior_base;
uint8_t ior_count, mad;
} avr_gdb_t;

#endif

0 comments on commit e036e96

Please sign in to comment.