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>
52 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
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 static int lock_count = 0;
104 void hostsim_lock(void)
108 pthread_mutex_lock(&mut);
111 void hostsim_unlock(void)
113 if (lock_count-- == 1)
114 pthread_mutex_unlock(&mut);
117 int hostsim_islocked(void)
122 void host_wait_ms(int ms)
124 struct timeval tv, tv2, diff;
126 gettimeofday(&tv, NULL);
127 diff.tv_sec = (1000 * ms) / 1000000;
128 diff.tv_usec = (1000 * ms) % 1000000;
129 timeradd(&tv, &diff, &tv);
130 gettimeofday(&tv2, NULL);
132 while (timercmp(&tv2, &tv, <)) {
134 gettimeofday(&tv2, NULL);
139 /* sends signal to child */
140 void *parent(void *arg)
142 pthread_t thread = (pthread_t)arg;
143 struct timeval cur_tv, prev_tv, tv_millisec;
146 gettimeofday(&prev_tv, NULL);
150 gettimeofday(&cur_tv, NULL);
153 while (timercmp(&prev_tv, &cur_tv, <)) {
155 /* give some time between subsequent
160 pthread_mutex_lock(&mut);
162 pthread_kill(thread, SIGUSR1);
164 /* signal was acked */
165 tv_millisec.tv_sec = 0;
166 tv_millisec.tv_usec = 1000;
167 timeradd(&prev_tv, &tv_millisec, &prev_tv);
176 void *hostsim_uart_stdin(void *arg)
178 pthread_t thread = (pthread_t)arg;
182 /* read on old stdin and put it in pipe */
184 n = read(old_stdin, &c, 1);
188 pthread_mutex_lock(&mut);
189 g_msg.type = UART_RCV;
191 pthread_kill(thread, SIGUSR1);
193 write(stdin_pipe[1], &c, 1);
199 void *hostsim_uart_stdout(void *arg)
201 pthread_t thread = (pthread_t)arg;
205 /* read on our pipe, and forward it to the old stdout */
207 n = read(stdout_pipe[0], &c, 1);
211 pthread_mutex_lock(&mut);
212 g_msg.type = UART_SND;
214 pthread_kill(thread, SIGUSR1);
216 write(old_stdout, &c, 1);
222 int hostsim_uart_init(void)
226 tcgetattr(0, &oldterm);
227 memcpy(&term, &oldterm, sizeof(term));
228 term.c_lflag &= ~(ICANON | ECHO | ISIG);
229 tcsetattr(0, TCSANOW, &term);
231 /* duplicate stdin */
236 /* duplicate stdout */
242 if (pipe(stdin_pipe) < 0)
244 if (pipe(stdout_pipe) < 0)
247 /* replace file desc 0 (stdin) by our pipe */
248 if (dup2(stdin_pipe[0], 0) < 0)
250 close(stdin_pipe[0]);
252 /* replace file desc 1 (stdout) by our pipe */
253 if (dup2(stdout_pipe[1], 1) < 0)
255 close(stdout_pipe[1]);
257 setbuf(stdout, NULL);
262 int hostsim_init(void)
264 struct sigaction sigact;
265 pthread_t parent_id, child_id, child2_id, child3_id;
268 parent_id = pthread_self();
270 pthread_mutex_lock(&mut);
271 ret = pthread_create(&child_id, NULL, parent, (void *)parent_id);
273 printf("pthread_create() returned %d\n", ret);
274 pthread_mutex_unlock(&mut);
278 #ifdef CONFIG_MODULE_UART
279 if (hostsim_uart_init())
282 ret = pthread_create(&child2_id, NULL, hostsim_uart_stdin, (void *)parent_id);
284 printf("pthread_create() returned %d\n", ret);
285 pthread_mutex_unlock(&mut);
288 ret = pthread_create(&child3_id, NULL, hostsim_uart_stdout, (void *)parent_id);
290 printf("pthread_create() returned %d\n", ret);
291 pthread_mutex_unlock(&mut);
296 /* register a signal handler, which is interruptible */
297 memset(&sigact, 0, sizeof(sigact));
298 sigemptyset(&sigact.sa_mask);
299 sigact.sa_flags |= SA_NODEFER;
300 sigact.sa_sigaction = sigusr1;
301 sigaction(SIGUSR1, &sigact, NULL);
304 if (siginterrupt (SIGUSR1, 0) != 0)
307 pthread_mutex_unlock(&mut);
312 int hostsim_exit(void)
314 #ifdef CONFIG_MODULE_UART
315 tcsetattr(0, TCSANOW, &oldterm);
320 #endif /* HOST_VERSION */