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