2 * Copyright Droids Corporation
3 * Olivier Matz <zer0@droids-corp.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Revision : $Id: main.c,v 1.10 2009-11-08 17:24:33 zer0 Exp $
25 * AVR simulator. This code is used on host (PC for instance) to
26 * generate a signal that will call other aversive modules like
27 * scheduler or uart. The goal is to simulate the behaviour of
28 * hardware interrupts in a unix application.
41 #include <sys/types.h>
45 #ifdef CONFIG_MODULE_SCHEDULER
46 #include <scheduler.h>
48 #ifdef CONFIG_MODULE_UART
49 #include <uart_host.h>
53 static volatile int cpt = 0;
55 static struct termios oldterm;
56 /* static */ int old_stdin, old_stdout;
57 static int stdin_pipe[2];
58 static int stdout_pipe[2];
70 static struct message g_msg;
73 static void sigusr1(__attribute__((unused)) int sig,
74 __attribute__((unused)) siginfo_t *info,
75 __attribute__((unused)) void *uc)
77 void sigusr1(__attribute__((unused)) int sig)
83 #ifdef CONFIG_MODULE_SCHEDULER
84 if (m.type == SCHED) {
85 pthread_mutex_unlock(&mut);
86 scheduler_interrupt();
90 #ifdef CONFIG_MODULE_UART
91 if (m.type == UART_RCV) {
92 uart_host_rx_event(m.c);
93 pthread_mutex_unlock(&mut);
95 if (m.type == UART_SND) {
96 uart_host_tx_event(m.c);
97 pthread_mutex_unlock(&mut);
102 void host_wait_ms(int ms)
104 struct timeval tv, tv2, diff;
106 gettimeofday(&tv, NULL);
107 diff.tv_sec = (1000 * ms) / 1000000;
108 diff.tv_usec = (1000 * ms) % 1000000;
109 timeradd(&tv, &diff, &tv);
110 gettimeofday(&tv2, NULL);
112 while (timercmp(&tv2, &tv, <)) {
114 gettimeofday(&tv2, NULL);
119 /* sends signal to child */
120 void *parent(void *arg)
122 pthread_t thread = (pthread_t)arg;
123 struct timeval cur_tv, prev_tv, tv_millisec;
126 gettimeofday(&prev_tv, NULL);
130 gettimeofday(&cur_tv, NULL);
133 while (timercmp(&prev_tv, &cur_tv, <)) {
135 /* give some time between subsequent
140 pthread_mutex_lock(&mut);
142 pthread_kill(thread, SIGUSR1);
144 /* signal was acked */
145 tv_millisec.tv_sec = 0;
146 tv_millisec.tv_usec = 1000;
147 timeradd(&prev_tv, &tv_millisec, &prev_tv);
156 void *hostsim_uart_stdin(void *arg)
158 pthread_t thread = (pthread_t)arg;
162 /* read on old stdin and put it in pipe */
164 n = read(old_stdin, &c, 1);
168 pthread_mutex_lock(&mut);
169 g_msg.type = UART_RCV;
171 pthread_kill(thread, SIGUSR1);
173 write(stdin_pipe[1], &c, 1);
179 void *hostsim_uart_stdout(void *arg)
181 pthread_t thread = (pthread_t)arg;
185 /* read on our pipe, and forward it to the old stdout */
187 n = read(stdout_pipe[0], &c, 1);
191 pthread_mutex_lock(&mut);
192 g_msg.type = UART_SND;
194 pthread_kill(thread, SIGUSR1);
196 write(old_stdout, &c, 1);
202 int hostsim_uart_init(void)
206 tcgetattr(0, &oldterm);
207 memcpy(&term, &oldterm, sizeof(term));
208 term.c_lflag &= ~(ICANON | ECHO | ISIG);
209 tcsetattr(0, TCSANOW, &term);
211 /* duplicate stdin */
216 /* duplicate stdout */
222 if (pipe(stdin_pipe) < 0)
224 if (pipe(stdout_pipe) < 0)
227 /* replace file desc 0 (stdin) by our pipe */
228 if (dup2(stdin_pipe[0], 0) < 0)
230 close(stdin_pipe[0]);
232 /* replace file desc 1 (stdout) by our pipe */
233 if (dup2(stdout_pipe[1], 1) < 0)
235 close(stdout_pipe[1]);
237 setbuf(stdout, NULL);
242 int hostsim_init(void)
244 struct sigaction sigact;
245 pthread_t parent_id, child_id, child2_id, child3_id;
248 pthread_mutex_init(&mut, NULL);
250 parent_id = pthread_self();
252 pthread_mutex_lock(&mut);
253 ret = pthread_create(&child_id, NULL, parent, (void *)parent_id);
255 printf("pthread_create() returned %d\n", ret);
256 pthread_mutex_unlock(&mut);
260 #ifdef CONFIG_MODULE_UART
261 if (hostsim_uart_init())
264 ret = pthread_create(&child2_id, NULL, hostsim_uart_stdin, (void *)parent_id);
266 printf("pthread_create() returned %d\n", ret);
267 pthread_mutex_unlock(&mut);
270 ret = pthread_create(&child3_id, NULL, hostsim_uart_stdout, (void *)parent_id);
272 printf("pthread_create() returned %d\n", ret);
273 pthread_mutex_unlock(&mut);
278 /* register a signal handler, which is interruptible */
279 memset(&sigact, 0, sizeof(sigact));
280 sigemptyset(&sigact.sa_mask);
281 sigact.sa_flags |= SA_NODEFER;
282 sigact.sa_sigaction = sigusr1;
283 sigaction(SIGUSR1, &sigact, NULL);
286 if (siginterrupt (SIGUSR1, 0) != 0)
289 pthread_mutex_unlock(&mut);
294 void hostsim_exit(void)
296 #ifdef CONFIG_MODULE_UART
297 tcsetattr(0, TCSANOW, &oldterm);
300 #endif /* HOST_VERSION */