1 #include <unistd.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <libgen.h>
9 #include <simavr/sim_avr.h>
10 #include <simavr/sim_gdb.h>
11 #include <simavr/avr_ioport.h>
12 #include <simavr/sim_elf.h>
13 #include <simavr/avr_uart.h>
14
15 static avr_t *g_avr;
16 static avr_irq_t *g_uart_irq;
17
18 static struct {
19 uint8_t argc;
20 char args[3][16];
21 } g_args;
22 static int g_args_idx;
23 static bool g_uart_xon;
24 static bool g_status_ok;
25
uart_tx_hook(struct avr_irq_t * irq,uint32_t value,void * param)26 static void uart_tx_hook(struct avr_irq_t * irq, uint32_t value, void * param)
27 {
28 fputc(value, stdout);
29 fflush(stdout);
30 }
31
stdin_can_read()32 static bool stdin_can_read()
33 {
34 struct timeval tv;
35 fd_set fds;
36 tv.tv_sec = 0;
37 tv.tv_usec = 0;
38 FD_ZERO(&fds);
39 FD_SET(STDIN_FILENO, &fds);
40 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
41 return (FD_ISSET(0, &fds));
42 }
43
avr_logger(avr_t * avr,const int level,const char * format,va_list ap)44 static void avr_logger(avr_t * avr, const int level, const char * format, va_list ap)
45 {
46 if ((!avr && level <= LOG_WARNING) || (avr && avr->log >= level)) {
47 vfprintf(stderr , format, ap);
48 }
49 }
50
uart_xon_hook(struct avr_irq_t * irq,uint32_t value,void * param)51 static void uart_xon_hook(struct avr_irq_t * irq, uint32_t value, void * param)
52 {
53 g_uart_xon = true;
54 int v;
55
56 if (feof(stdin))
57 {
58 avr_raise_irq(&g_uart_irq[1], UART_INPUT_FE);
59 return;
60 }
61
62 while (g_uart_xon)
63 {
64 if (g_args_idx < sizeof(g_args))
65 {
66 v = ((char*)&g_args)[g_args_idx++];
67 }
68 else if (stdin_can_read())
69 {
70 v = fgetc(stdin);
71 }
72 else
73 {
74 break;
75 }
76
77 if (v != EOF)
78 {
79 avr_raise_irq(&g_uart_irq[1], v);
80 }
81 else
82 {
83 avr_raise_irq(&g_uart_irq[1], UART_INPUT_FE);
84 break;
85 }
86 }
87 }
88
uart_xoff_hook(struct avr_irq_t * irq,uint32_t value,void * param)89 static void uart_xoff_hook(struct avr_irq_t * irq, uint32_t value, void * param)
90 {
91 g_uart_xon = false;
92 }
93
init_uart()94 void init_uart()
95 {
96 const char *irq_names[2] = {"8<uart_in", "8>uart_out"};
97 g_uart_irq = avr_alloc_irq(&g_avr->irq_pool, 0, 2, irq_names);
98 avr_irq_register_notify(&g_uart_irq[0], &uart_tx_hook, NULL);
99
100 uint32_t flags = 0;
101 avr_ioctl(g_avr, AVR_IOCTL_UART_GET_FLAGS('0'), &flags);
102 flags &= ~AVR_UART_FLAG_STDIO;
103 flags &= ~AVR_UART_FLAG_POLL_SLEEP;
104 avr_ioctl(g_avr, AVR_IOCTL_UART_SET_FLAGS('0'), &flags);
105
106 avr_irq_t *src = avr_io_getirq(g_avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT);
107 avr_irq_t *dst = avr_io_getirq(g_avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT);
108 avr_connect_irq(src, &g_uart_irq[0]);
109 avr_connect_irq(&g_uart_irq[1], dst);
110
111 avr_irq_t *xon = avr_io_getirq(g_avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUT_XON);
112 avr_irq_t *xoff = avr_io_getirq(g_avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUT_XOFF);
113 avr_irq_register_notify(xon, uart_xon_hook, NULL);
114 avr_irq_register_notify(xoff, uart_xoff_hook, NULL);
115 }
116
status_ok_hook(struct avr_irq_t * irq,uint32_t value,void * param)117 static void status_ok_hook(struct avr_irq_t * irq, uint32_t value, void * param)
118 {
119 g_status_ok = value;
120 }
121
main(int argc,char * argv[])122 int main(int argc, char *argv[])
123 {
124 avr_global_logger_set(&avr_logger);
125 g_avr = avr_make_mcu_by_name("atmega1284");
126 if (!g_avr)
127 {
128 fprintf(stderr, "avr_make_mcu_by_name failed\n");
129 return 1;
130 }
131
132 if (argc < 2)
133 {
134 fprintf(stderr, "Usage: %s [-g] binary [args ...]\n", argv[0]);
135 return 2;
136 }
137
138 const char *filename = argv[1];
139 bool enable_gdb = false;
140 int argc_offset = 2;
141
142 if (strcmp(filename, "-g") == 0)
143 {
144 enable_gdb = true;
145 argc_offset = 3;
146 filename = argv[2];
147 }
148
149 elf_firmware_t firmware;
150 elf_read_firmware(filename, &firmware);
151 avr_init(g_avr);
152 avr_load_firmware(g_avr, &firmware);
153 g_avr->frequency = 8000000;
154
155 if (enable_gdb)
156 {
157 g_avr->state = cpu_Stopped;
158 g_avr->gdb_port = 1234;
159 avr_gdb_init(g_avr);
160 }
161
162 init_uart();
163
164 avr_irq_register_notify(avr_io_getirq(g_avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 1), status_ok_hook, NULL);
165
166 // Pass the rest of arguments to application inside simulator
167 g_args.argc = argc - argc_offset;
168 if (g_args.argc > 3) g_args.argc = 3;
169 for (int i = 0; i < g_args.argc; i++)
170 {
171 strncpy(g_args.args[i], argv[i + argc_offset], 15);
172 }
173
174 while (1)
175 {
176 int state = avr_run(g_avr);
177 if (state == cpu_Done)
178 break;
179
180 if (state == cpu_Crashed)
181 {
182 fprintf(stderr, "CPU Crashed\n");
183 return 3;
184 }
185 }
186
187 if (g_status_ok)
188 {
189 return 0;
190 }
191 else
192 {
193 fprintf(stderr, "Received error status from simulation\n");
194 return 5;
195 }
196 }
197