#include "simavr/simavr.h"
void printVersion () {
- printf("simuc V0.0.7 (%s,%s)\n", __DATE__, __TIME__);
+ printf("simuc V0.1 (%s,%s)\n", __DATE__, __TIME__);
}
void printHelp () {
printf("usage: simuc [options] elf-file [elf-file ...]\n\n");
printf(" available options (you can use file .simucinit instead):\n");
printf(" --port ... listining port for gdb (default 1234)\n");
- printf(" --board ... set board (arduino, sure, evws1)\n");
+ printf(" --board ... set board (arduino, nano-644, nano-1284, sure, evws1)\n");
printf(" --nosync do not sync elapsed µC-time with real time\n");
printf(" --mmcu ... set target device type\n");
printf(" --frequency ... set target frequency in Hz\n");
printf(" simuc --board arduino a.out\n\n");
}
+void printAvailableCommands (struct StartParameters ¶ms) {
+ printf("----------------------------------------------------------------------\n");
+ printf("available commands:\n");
+ printf(" h (help)\n");
+ printf(" b (break), n (stepi), c (continue), s (stack), r (reset), p (power), q (quit)\n");
+ if (params.board == BoardNano644 || params.board == BoardNano1284) {
+ printf(" 1 (SW2 not pressed), 2 (SW2 pressed)\n");
+ } else if (params.board == BoardSure) {
+ printf(" 1 (SW1 not pressed), 2 (SW1 pressed), 3 (SW2 not pressed), 4 (SW2 pressed)\n");
+ }
+ printf("----------------------------------------------------------------------\n");
+}
+
+EnumSimAvrCommand parseSimAvrCommand (struct StartParameters& params, char c) {
+ switch (c) {
+ case 'h': return CommandHelp;
+ case 'b': return CommandBreak;
+ case 'n': return CommandStepi;
+ case 'c': return CommandContinue;
+ case 's': return CommandStack;
+ case 'r': return CommandReset;
+ case 'p': return CommandPower;
+ case 'q': return CommandPower;
+ case '1': {
+ switch (params.board) {
+ case BoardSure: return CommandSW1Released;
+ case BoardNano644: case BoardNano1284: return CommandSW2Released;
+ default: break;
+ }
+ }
+ case '2': {
+ switch (params.board) {
+ case BoardSure: return CommandSW1Pressed;
+ case BoardNano644: case BoardNano1284: return CommandSW2Pressed;
+ default: break;
+ }
+ }
+ case '3': {
+ switch (params.board) {
+ case BoardSure: return CommandSW2Released;
+ default: break;
+ }
+ }
+ case '4': {
+ switch (params.board) {
+ case BoardSure: return CommandSW2Pressed;
+ default: break;
+ }
+ }
+ default: return ReadyForNewCommand;
+ }
+}
+
struct SimUcInit {
int argc;
char *argv[];
params.vcc = 5000;
params.avcc = 5000;
params.aref = 2500;
+
+ } else if (strcmp("nano-644", argv[i]) == 0) {
+ params.board = BoardNano644;
+ params.mmcu = "atmega644p";
+ params.frequency = 12000000;
+ params.vcc = 3300;
+ params.avcc = 3300;
+ params.aref = 1100;
+
+ } else if (strcmp("nano-1284", argv[i]) == 0) {
+ params.board = BoardNano1284;
+ params.mmcu = "atmega1284p";
+ params.frequency = 12000000;
+ params.vcc = 3300;
+ params.avcc = 3300;
+ params.aref = 1100;
+
} else if (strcmp("sure", argv[i]) == 0) {
params.board = BoardSure;
params.mmcu = "atmega16";
return 1;
}
printf("----------------------------------------------------------------------\n");
- printf("available commands:\n");
- printf(" b (break), c (continue), s (stack), r (reset), p (power), q (quit)\n");
- printf("----------------------------------------------------------------------\n");
- printf("init done - press key to start\n");
- char c = getchar();
- if (c != '\n') {
- getchar(); // remove line feed from stdin
- }
+ printf("init done\n");
+ printAvailableCommands(params);
+ printf("start simulator with command b (break)\n");
+ printf("ready for avr-gdb -> (gdb) target remote :%d\n", params.gdbPort);
printf("----------------------------------------------------------------------\n");
-
- switch (c) {
- case 'b': start(CommandBreak, NULL); break;
- case 's': start(CommandStack, NULL); break;
- case 'r': start(CommandReset, NULL); break;
- case 'p': start(CommandPower, NULL); break;
- case 'q': return 0;
- default: start(ReadyForNewCommand, NULL); break;
- }
-
- // int cnt = 0;
+
+ EnumSimAvrCommand cmd = CommandBreak;
+ start(CommandBreak, NULL);
+ EnumSimAvrCommand lastCmd = cmd;
+
char *line = NULL;
size_t size = 0;
int quit = 0;
while (!quit) {
- // struct SimAvrEvent ev = waitForEvent();
- // printf("%10.03lf: event %s (%d) received \r", ev.cycle / 20E6, eventText((EnumSimEvent)ev.event), ev.event);
- // fflush(stdout);
- // if (++cnt == 10000) {
- // stop();
- // shutdown();
- // break;
- // }
-
if (getline(&line, &size, stdin) > 0) {
- const char *commands[] = { "quit", "break", "continue", "stack", "reset", "power" };
try {
- int foundIndex = -1;
- int foundCnt = 0;
- size_t length = strlen(line) - 1;
- if (length > 0 && size >= (length + 1)) {
- line[length] = 0;
- for (long unsigned int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
- const char *cmd = commands[i];
- size_t max = strlen(cmd);
- bool ok = true;
- for (size_t j = 0; j < length; j++) {
- if (j >= max || line[j] != cmd[j]) {
- ok = false;
- break;
- }
- }
- if (ok) {
- foundCnt++;
- foundIndex = i;
- }
+ EnumSimAvrCommand cmd = ReadyForNewCommand;
+ if (strnlen(line, size) == 1) { // Enter pressed
+ switch (lastCmd) {
+ case CommandStepi: cmd = CommandStepi; break;
+ default: cmd = CommandStatus;
+ }
+ } else if (strnlen(line, size) == 2) {
+ cmd = parseSimAvrCommand(params, line[0]);
+ lastCmd = cmd;
+ if (cmd == CommandHelp) {
+ printAvailableCommands(params);
+ continue;
}
}
- // printf("foundCnt=%d foundIndex=%d command=%s\n", foundCnt, foundIndex, foundIndex >= 0 ? commands[foundIndex] : "");
- if (foundCnt == 1 || length == 0) {
- EnumSimAvrCommand cmd = (EnumSimAvrCommand)(foundCnt > 0 ? foundIndex + 2 : 1);
+
+ if (cmd != ReadyForNewCommand) {
struct SimAvrStatus status = getStatus();
if (cmd == CommandStatus && status.state == StateStopped) {
// ignore status command, because status was already printed
}
} else {
- printf("invalid command, valid commands are <Enter> for status and:");
- for (long unsigned int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
- printf(" %s", commands[i]);
- }
+ printf("invalid command, valid commands are <Enter> for status and:\n");
+ printAvailableCommands(params);
printf("\n");
continue;
}
}
}
-
}
- // while (1) {
- // struct SimAvrEvent ev = waitForEvent();
- // printf("event %s (%d) received\n", eventText((EnumSimEvent)ev.event), ev.event);
- // if (ev.event == EventShutdown) {
- // break;
- // }
- // }
if (simUcInit != NULL) {
for (int i = 0; i < simUcInit->argc; i++) {
#include <simavr/sim_avr.h>
#include <simavr/sim_core.h>
#include <simavr/avr_uart.h>
+#include <simavr/avr_ioport.h>
+
+typedef struct {
+ avr_t * avr;
+ int burst_count; // Current instruction burst size
+ int listen; // listen socket
+ int s; // current gdb connection
+} Gdb;
SimAvr::SimAvr () {
avr->gdb_port = params->gdbPort > 0 ? params->gdbPort : 1234;
avr_gdb_init(avr);
+ switch (params->board) {
+ case BoardSure: {
+ // SW1 and SW2 have external pullup resistors
+ avr_ioport_external_t io_ext = { 'C', 0xc0, 0xc0 }; // PC6 ... SW2, PC7...SW1
+ avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL('C'), &io_ext);
+ break;
+ }
+ default: break;
+
+ }
+
+
+
pthread_mutex_unlock(&lock);
} catch (std::exception& e) {
uint16_t nanos = time % 1000; time = time / 1000;
uint16_t micros = time % 1000; time = time / 1000;
uint16_t millis = time % 1000; time = time / 1000;
- uint16_t seconds = time % 1000; time = time / 1000;
- printf("cycle %" PRIu64 " = %ds %03dms %03dµs %03dns", avr->cycle, seconds, millis, micros, nanos);
+ uint16_t seconds = time % 60; time = time / 60;
+ uint16_t minutes = time % 60; time = time / 60;
+ uint32_t hours = (uint32_t)time; // time has after divisions max. 23 Bit
+ if (hours == 0) {
+ printf("cycle %010" PRIu64 " = %2dmin %2ds %03dms %03dµs %03dns", avr->cycle, minutes, seconds, millis, micros, nanos);
+ } else {
+ printf("cycle %010" PRIu64 " = %dhrs %2dmin %2ds %03dms %03dµs %03dns", avr->cycle, hours, minutes, seconds, millis, micros, nanos);
+ }
}
bool SimAvr::sprintfLedStatus (char *s, size_t size, bool onlyOnChange) {
int8_t nextLedL = -1;
if (ddrb & 0x20) {
nextLedL = portb & 0x20 ? 1 : 0;
+ } else {
+ nextLedL = -1;
}
if (!onlyOnChange || nextLedL != ledL) {
+ char c;
+ switch (nextLedL) {
+ case -1: c = '-'; break;
+ case 0: c = '.'; break;
+ case 1: c = 'X'; break;
+ default: c = '?'; break;
+ }
ledL = nextLedL;
- snprintf(s, size, "LED L = %c", ledL == 1 ? 'X' : '.');
+ snprintf(s, size, "LED L = %c", c);
+ rv = true;
+ }
+ break;
+ }
+ case BoardNano644: case BoardNano1284: {
+ static int8_t led[3] = { -1, -1, -1 }; // pin floating
+ static int8_t sw2 = -1;
+ static uint8_t mask[3] = { 0x04, 0x08, 0x10 }; // Bitmask for LED Red, Yellow, Green
+ int nextLed[3] = { -1, -1, -1 };
+ int nextSw2 = -1;
+ char cLed[3];
+ uint8_t pinc = avr->data[0x26];
+ uint8_t ddrc = avr->data[0x27];
+ uint8_t portc = avr->data[0x28];
+ int change = 0;
+ for (int i = 0; i < 3; i++) {
+ if (ddrc & mask[i]) {
+ nextLed[i] = portc & mask[i] ? 1 : 0;
+ } else {
+ nextLed[i] = -1;
+ }
+ if (!onlyOnChange || nextLed[i] != led[i]) {
+ change++;
+ }
+ }
+
+ if ((ddrc & 0x20) == 0 && ((portc & 0x20) == 0x20)) {
+ nextSw2 = (pinc & 0x20) == 0 ? 1 : 0; // 1 == pressed
+ } else {
+ nextSw2 = -1;
+ }
+ if (!onlyOnChange || nextSw2 != sw2) {
+ change++;
+ }
+
+ int l = 0;
+ if (change) {
rv = true;
+ switch (nextSw2) {
+ case 0: l += snprintf(&s[l], size - l, "SW2 ."); break;
+ case 1: l += snprintf(&s[l], size - l, "SW2 X"); break;
+ default: l += snprintf(&s[l], size - l, "SW2 ?"); break;
+ }
+ l += snprintf(&s[l], size - l, " LED RGB = ");
+ for (int i = 0; i < 3; i++) {
+ switch (nextLed[i]) {
+ case -1: cLed[i] = '-'; break;
+ case 0: cLed[i] = '.'; break;
+ case 1: cLed[i] = 'X'; break;
+ default: cLed[i] = '?'; break;
+ }
+ l += snprintf(&s[l], size - l, "%c", cLed[i]);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ if (nextLed[i] != led[i]) {
+ led[i] = nextLed[i];
+ switch (i) {
+ case 0: l += snprintf(&s[l], size - l, " -> Red = %c", cLed[i]); break;
+ case 1: l += snprintf(&s[l], size - l, " -> Yellow = %c", cLed[i]); break;
+ case 2: l += snprintf(&s[l], size - l, " -> Green = %c", cLed[i]); break;
+ }
+ }
+ }
+ if (nextSw2 != sw2) {
+ l += snprintf(&s[l], size - l, " SW2 %s", nextSw2 ? "pressed" : "not pressed");
+ sw2 = nextSw2;
+ }
}
break;
}
+
case BoardSure: {
static int8_t led[4] = { -1, -1, -1, -1 }; // pin floating
+ static uint8_t mask[4] = { 0x08, 0x04, 0x02, 0x01 }; // Bitmask for LED PA3, PA2, PA1, PA0
+ static int8_t sw[2] = { -1, -1 };
+ static uint8_t swMask[2] = { 0x80, 0x40 };
+ int nextLed[4] = { -1, -1, -1, -1 };
+ int nextSw[2] = { -1, -1 };
+ char cLed[4];
uint8_t ddra = avr->data[0x3a];
uint8_t porta = avr->data[0x3b];
+ uint8_t ddrc = avr->data[0x34];
+ uint8_t pinc = avr->data[0x33];
int change = 0;
for (int i = 0; i < 4; i++) {
- int8_t nextLed = -1;
- if (ddra & (1 << i)) {
- nextLed = porta & (1 << i) ? 0 : 1; // port output
+ if (ddra & mask[i]) {
+ nextLed[i] = porta & mask[i] ? 1 : 0;
} else {
- nextLed = 0; // port input _> led is off
+ nextLed[i] = -1;
}
- if (nextLed != led[i]) {
- change = 1;
- led[i] = nextLed;
+ if (!onlyOnChange || nextLed[i] != led[i]) {
+ change++;
+ rv = true;
}
}
- if (!onlyOnChange || change) {
- int n = snprintf(s, size, "LED PA[3210] =");
- for (int i = 3; i >= 0; i--) {
- n += snprintf(s + n, size - n, " %c", led[i] == 1 ? 'X' : '.');
+
+ for (int i = 0; i < 2; i++) {
+ if ((ddrc & swMask[i]) == 0) {
+ nextSw[i] = (pinc & swMask[i]) == 0 ? 1 : 0;
+ } else {
+ nextSw[i] = -1;
+ }
+ if (!onlyOnChange || nextSw[i] != sw[i]) {
+ change++;
+ rv = true;
+ }
+ }
+
+ int l = 0;
+ if (change) {
+ char c[2];
+ for (int i = 0; i < 2; i++){
+ switch (nextSw[i]) {
+ case 0: c[i] = '.';break;
+ case 1: c[i] = 'X'; break;
+ default: c[i] = '?'; break;
+ }
+ }
+ l += snprintf(&s[l], size - l, "SW1:2 = %c%c", c[0], c[1]);
+
+ l += snprintf(&s[l], size - l, " LED PA3:0 = ");
+ for (int i = 0; i < 4; i++) {
+ switch (nextLed[i]) {
+ case -1: cLed[i] = '-'; break;
+ case 0: cLed[i] = '.'; break;
+ case 1: cLed[i] = 'X'; break;
+ default: cLed[i] = '?'; break;
+ }
+ l += snprintf(&s[l], size - l, "%c", cLed[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ if (nextLed[i] != led[i]) {
+ led[i] = nextLed[i];
+ switch (i) {
+ case 0: l += snprintf(&s[l], l, " -> PA3 = %c", cLed[i]); break;
+ case 1: l += snprintf(&s[l], l, " -> PA2 = %c", cLed[i]); break;
+ case 2: l += snprintf(&s[l], l, " -> PA1 = %c", cLed[i]); break;
+ case 3: l += snprintf(&s[l], l, " -> PA0 = %c", cLed[i]); break;
+ }
+
+ }
+ }
+ for (int i = 0; i < 2; i++) {
+ if (sw[i] != nextSw[i]) {
+ sw[i] = nextSw[i];
+ l += snprintf(&s[l], size - l, " SW%d %s", i + 1, nextSw[i] ? "pressed" : "not pressed");
+ }
}
- rv = true;
}
break;
}
long cnt = 0;
int lastAvrState = -1;
_avr_sp_set(avr, 0);
- char led[80];
+ char led[120];
while (1) {
try {
if (sprintfLedStatus(led, sizeof(led), true)) {
lastAvrState = avr->state;
}
+ if (avr->gdb != NULL) {
+ static int session = -1;
+ void *p = (void *)avr->gdb;
+ Gdb *pg = (Gdb *)p;
+ if (pg->s != session) {
+ if (pg->s == -1) {
+ printf("\navr-gdb disconnected%s\n\n", avr->state == cpu_Stopped ? "" : " (CPU stopped)");
+
+ } else {
+ printf("\navr-gdb connected%s\n\n", avr->state == cpu_Stopped ? "" : " (CPU stopped)");
+ }
+ session = pg->s;
+ avr->state = cpu_Stopped;
+ }
+ }
+
if (cnt <= 0) {
// usleep(10000);
if (pthread_mutex_lock(&lock)) {
nextCommand = ReadyForNewCommand;
break;
}
+ case CommandStepi: {
+ if (avr->state != cpu_Step) {
+ avr->state = cpu_Step;
+ updateState = true;
+ }
+ nextCommand = ReadyForNewCommand;
+ break;
+ }
case CommandContinue: {
if (avr->state == cpu_Stopped) {
avr->state = cpu_Running;
break;
}
+ case CommandSW1Released: {
+ if (startParameters->board == BoardSure) {
+ uint8_t ddrc = avr->data[0x34]; // Atmega16
+ if ((ddrc & 0x80) == 0) {
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 7), 0x80);
+ }
+ }
+ nextCommand = ReadyForNewCommand;
+ break;
+ }
+
+ case CommandSW1Pressed: {
+ if (startParameters->board == BoardSure) {
+ uint8_t ddrc = avr->data[0x34]; // Atmega16
+ if ( (ddrc & 0x80) == 0) {
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 7), 0x00);
+ }
+ }
+ nextCommand = ReadyForNewCommand;
+ break;
+ }
+
+ case CommandSW2Released: {
+ if (startParameters->board == BoardNano644) {
+ uint8_t ddrc = avr->data[0x27]; // Atmega644P
+ uint8_t portc = avr->data[0x28]; // Atmega644P
+ if ( (ddrc & 0x20) == 0 && (portc & 0x20) == 0x20) { // internal pullup needed
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 5), 0x20);
+ }
+ } else if (startParameters->board == BoardSure) {
+ uint8_t ddrc = avr->data[0x34]; // Atmega16
+ if ( (ddrc & 0x40) == 0) {
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 6), 0x40);
+ }
+ }
+ nextCommand = ReadyForNewCommand;
+ break;
+ }
+
+ case CommandSW2Pressed: {
+ if (startParameters->board == BoardNano644 || startParameters->board == BoardNano1284) {
+ uint8_t ddrc = avr->data[0x27]; // Atmega644P
+ uint8_t portc = avr->data[0x28]; // Atmega644P
+ if ( (ddrc & 0x20) == 0 && (portc & 0x20) == 0x20) { // internal pullup needed
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 5), 0x00);
+ }
+ } else if (startParameters->board == BoardSure) {
+ uint8_t ddrc = avr->data[0x34]; // Atmega16
+ if ( (ddrc & 0x80) == 0) { // external pullup on board
+ avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 6), 0);
+ }
+
+ }
+ nextCommand = ReadyForNewCommand;
+ break;
+ }
+
default: {
nextCommand = ReadyForNewCommand;
break;