From: batt Date: Mon, 29 Mar 2010 13:55:34 +0000 (+0000) Subject: Merge from trunk. X-Git-Tag: 2.4.1~2 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=7b47f57c871da92ea81d28a18f91fae04f3072b3;p=bertos.git Merge from trunk. git-svn-id: https://src.develer.com/svnoss/bertos/branches/2.4@3296 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/arm/drv/adc_at91.c b/bertos/cpu/arm/drv/adc_at91.c index 7fd50ddf..fadaa4be 100644 --- a/bertos/cpu/arm/drv/adc_at91.c +++ b/bertos/cpu/arm/drv/adc_at91.c @@ -86,7 +86,7 @@ */ static DECLARE_ISR(adc_conversion_end_irq) { - sig_signal(adc_process, SIG_ADC_COMPLETE); + sig_post(adc_process, SIG_ADC_COMPLETE); /* Inform hw that we have served the IRQ */ AIC_EOICR = 0; diff --git a/bertos/cpu/arm/info/at91sam7.common b/bertos/cpu/arm/info/at91sam7.common index 3088ccff..00f3277b 100644 --- a/bertos/cpu/arm/info/at91sam7.common +++ b/bertos/cpu/arm/info/at91sam7.common @@ -78,7 +78,7 @@ MK_STOPDEBUG_SCRIPT = PRG_SCRIPTS_DIR + "arm/stopopenocd.sh" GDB_INIT_SCRIPT = PRG_SCRIPTS_DIR + "arm/openocd/gdbinit-sam7" # Common GCC flags. -MK_CPU_CPPAFLAGS = "-O0 -g -gdwarf-2 -g -gen-debug" +MK_CPU_CPPAFLAGS = "-g -gdwarf-2" MK_CPU_CPPFLAGS = "-O0 -g3 -gdwarf-2 -fverbose-asm -I" + CPU_DIR + "arm/" MK_CPU_LDFLAGS = "-nostartfiles -Wl,--no-warn-mismatch" diff --git a/bertos/cpu/avr/drv/adc_avr.c b/bertos/cpu/avr/drv/adc_avr.c index 20aa2a19..0aae6743 100644 --- a/bertos/cpu/avr/drv/adc_avr.c +++ b/bertos/cpu/avr/drv/adc_avr.c @@ -89,7 +89,7 @@ */ ISR(ADC_vect) { - sig_signal(adc_process, SIG_ADC_COMPLETE); + sig_post(adc_process, SIG_ADC_COMPLETE); } #endif /* CONFIG_KERN */ diff --git a/bertos/drv/ser.c b/bertos/drv/ser.c index a684ebba..dac277b0 100644 --- a/bertos/drv/ser.c +++ b/bertos/drv/ser.c @@ -410,6 +410,8 @@ static struct KFile *ser_reopen(struct KFile *fd) /** * Init serial driver for \a unit. + * + * Use values SER_UARTn as values for \a unit. */ void ser_init(struct Serial *fds, unsigned int unit) { @@ -476,6 +478,8 @@ static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size) /** * Init SPI serial driver \a unit in master mode. * + * Use SER_SPIn for \a unit parameter. + * * This interface implements the SPI master protocol over a serial SPI * driver. This is needed because normal serial driver send/receive data * at the same time. SPI slaves like memories and other peripherals diff --git a/bertos/drv/ser.h b/bertos/drv/ser.h index c264811e..fe05b4d5 100644 --- a/bertos/drv/ser.h +++ b/bertos/drv/ser.h @@ -62,10 +62,10 @@ #define SERRF_TXTIMEOUT BV(2) /**< Transmit timeout */ /* Hardware errors */ - #define SERRF_RXSROVERRUN 0 /**< Unsupported in emulated serial port. */ - #define SERRF_FRAMEERROR 0 /**< Unsupported in emulated serial port. */ - #define SERRF_PARITYERROR 0 /**< Unsupported in emulated serial port. */ - #define SERRF_NOISEERROR 0 /**< Unsupported in emulated serial port. */ + #define SERRF_RXSROVERRUN 0 /**< Rx shift register overrun, unsupported in emulated serial port. */ + #define SERRF_FRAMEERROR 0 /**< Stop bit missing, unsupported in emulated serial port. */ + #define SERRF_PARITYERROR 0 /**< Parity error, unsupported in emulated serial port. */ + #define SERRF_NOISEERROR 0 /**< Noise error, unsupported in emulated serial port. */ enum { @@ -93,8 +93,8 @@ | SERRF_RXSROVERRUN \ | SERRF_PARITYERROR \ | SERRF_FRAMEERROR \ - | SERRF_NOISEERROR) -#define SERRF_TX (SERRF_TXTIMEOUT) + | SERRF_NOISEERROR) /**< All possible rx errors */ +#define SERRF_TX (SERRF_TXTIMEOUT) /**< All possible tx errors */ /*\}*/ /** @@ -212,8 +212,8 @@ void spimaster_init(Serial *fds, unsigned int unit); * * \{ */ -#define ser_getstatus(h) ((h)->status) -#define ser_setstatus(h, x) ((h)->status = (x)) +#define ser_getstatus(serial) ((serial)->status) +#define ser_setstatus(serial, new_status) ((serial)->status = (new_status)) /* \} */ #endif /* DRV_SER_H */ diff --git a/bertos/kern/coop.c b/bertos/kern/coop.c index 1b2e1bb9..542ed678 100644 --- a/bertos/kern/coop.c +++ b/bertos/kern/coop.c @@ -57,14 +57,42 @@ */ void coop_yield(void); void coop_switch(void); +void coop_wakeup(Process *proc); +/** + * Give the control of the CPU to another process. + * + * \note Assume the current process has been already added to a wait queue. + * + * \warning This should be considered an internal kernel function, even if it + * is allowed, usage from application code is strongly discouraged. + */ void coop_switch(void) { - IRQ_ASSERT_ENABLED(); - ATOMIC(proc_schedule()); } +/** + * Immediately wakeup a process, dispatching it to the CPU. + */ +void coop_wakeup(Process *proc) +{ + ASSERT(proc_preemptAllowed()); + ASSERT(current_process); + IRQ_ASSERT_DISABLED(); + + if (prio_proc(proc) >= prio_curr()) + { + Process *old_process = current_process; + + SCHED_ENQUEUE(current_process); + current_process = proc; + proc_switchTo(current_process, old_process); + } + else + SCHED_ENQUEUE_HEAD(proc); +} + /** * Co-operative context switch */ diff --git a/bertos/kern/preempt.c b/bertos/kern/preempt.c index f77dd85e..1cb5e5a0 100644 --- a/bertos/kern/preempt.c +++ b/bertos/kern/preempt.c @@ -121,6 +121,7 @@ void preempt_yield(void); int preempt_needPreempt(void); void preempt_preempt(void); void preempt_switch(void); +void preempt_wakeup(Process *proc); void preempt_init(void); /** @@ -171,11 +172,32 @@ void preempt_preempt(void) void preempt_switch(void) { ASSERT(proc_preemptAllowed()); - IRQ_ASSERT_ENABLED(); ATOMIC(preempt_schedule()); } +/** + * Immediately wakeup a process, dispatching it to the CPU. + */ +void preempt_wakeup(Process *proc) +{ + ASSERT(proc_preemptAllowed()); + ASSERT(current_process); + IRQ_ASSERT_DISABLED(); + + if (prio_proc(proc) >= prio_curr()) + { + Process *old_process = current_process; + + SCHED_ENQUEUE(current_process); + _proc_quantum = CONFIG_KERN_QUANTUM; + current_process = proc; + proc_switchTo(current_process, old_process); + } + else + SCHED_ENQUEUE_HEAD(proc); +} + /** * Voluntarily release the CPU. */ diff --git a/bertos/kern/proc.c b/bertos/kern/proc.c index 623c1d3f..acaf4220 100644 --- a/bertos/kern/proc.c +++ b/bertos/kern/proc.c @@ -62,14 +62,6 @@ #define PROC_SIZE_WORDS (ROUND_UP2(sizeof(Process), sizeof(cpu_stack_t)) / sizeof(cpu_stack_t)) -/** - * CPU dependent context switching routines. - * - * Saving and restoring the context on the stack is done by a CPU-dependent - * support routine which usually needs to be written in assembly. - */ -EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp); - /* * The scheduer tracks ready processes by enqueuing them in the * ready list. @@ -428,15 +420,6 @@ void proc_exit(void) ASSERT(0); } - -/** - * Get the pointer to the user data of the current process - */ -iptr_t proc_currentUserData(void) -{ - return current_process->user_data; -} - /** * Call the scheduler and eventually replace the current running process. */ @@ -470,22 +453,7 @@ void proc_schedule(void) MEMORY_BARRIER; IRQ_DISABLE; } - /* - * Optimization: don't switch contexts when the active process has not - * changed. - */ - if (LIKELY(current_process != old_process)) { - cpu_stack_t *dummy; - - /* - * Save context of old process and switch to new process. If - * there is no old process, we save the old stack pointer into - * a dummy variable that we ignore. In fact, this happens only - * when the old process has just exited. - */ - asm_switch_context(¤t_process->stack, - old_process ? &old_process->stack : &dummy); - } + proc_switchTo(current_process, old_process); /* This RET resumes the execution on the new process */ LOG_INFO("resuming %p:%s\n", current_process, proc_currentName()); } diff --git a/bertos/kern/proc.h b/bertos/kern/proc.h index 390099da..bacd052b 100644 --- a/bertos/kern/proc.h +++ b/bertos/kern/proc.h @@ -148,6 +148,7 @@ void proc_exit(void); void proc_yield(void); void proc_preempt(void); int proc_needPreempt(void); +void proc_wakeup(Process *proc); /** * Dummy function that defines unimplemented scheduler class methods. @@ -167,6 +168,7 @@ INLINE void __proc_noop(void) * Preemptive scheduler: private methods. */ #define preempt_switch proc_switch + #define preempt_wakeup proc_wakeup #else /** * Co-operative scheduler: public methods. @@ -178,6 +180,7 @@ INLINE void __proc_noop(void) * Co-operative scheduler: private methods. */ #define coop_switch proc_switch + #define coop_wakeup proc_wakeup #endif void proc_rename(struct Process *proc, const char *name); @@ -191,7 +194,11 @@ const char *proc_currentName(void); * the returned pointer to the correct type. * \return Pointer to the user data of the current process. */ -iptr_t proc_currentUserData(void); +INLINE iptr_t proc_currentUserData(void) +{ + extern struct Process *current_process; + return current_process->user_data; +} int proc_testSetup(void); int proc_testRun(void); diff --git a/bertos/kern/proc_p.h b/bertos/kern/proc_p.h index 27d65fe2..85cb758f 100644 --- a/bertos/kern/proc_p.h +++ b/bertos/kern/proc_p.h @@ -50,6 +50,30 @@ #include // struct Process +/** + * CPU dependent context switching routines. + * + * Saving and restoring the context on the stack is done by a CPU-dependent + * support routine which usually needs to be written in assembly. + */ +EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp); + +/* + * Save context of old process and switch to new process. + */ +INLINE void proc_switchTo(Process *next, Process *prev) +{ + cpu_stack_t *dummy; + + if (UNLIKELY(next == prev)) + return; + /* + * If there is no old process, we save the old stack pointer into a + * dummy variable that we ignore. In fact, this happens only when the + * old process has just exited. + */ + asm_switch_context(&next->stack, prev ? &prev->stack : &dummy); +} /** * \name Flags for Process.flags. @@ -72,7 +96,8 @@ extern REGISTER List proc_ready_list; #if CONFIG_KERN_PRI #define prio_next() (LIST_EMPTY(&proc_ready_list) ? INT_MIN : \ ((PriNode *)LIST_HEAD(&proc_ready_list))->pri) - #define prio_curr() (current_process->link.pri) + #define prio_proc(proc) (proc->link.pri) + #define prio_curr() prio_proc(current_process) #define SCHED_ENQUEUE_INTERNAL(proc) \ LIST_ENQUEUE(&proc_ready_list, &(proc)->link) @@ -80,6 +105,7 @@ extern REGISTER List proc_ready_list; LIST_ENQUEUE_HEAD(&proc_ready_list, &(proc)->link) #else #define prio_next() 0 + #define prio_proc(proc) 0 #define prio_curr() 0 #define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&proc_ready_list, &(proc)->link) @@ -153,6 +179,9 @@ void proc_switch(void); /* Low level scheduling routine. */ void proc_schedule(void); +/* Low level context switch routine. */ +void proc_switchTo(Process *next, Process *prev); + /* Initialize a scheduler class. */ void proc_schedInit(void); diff --git a/bertos/kern/proc_test.c b/bertos/kern/proc_test.c index b8de22d7..b2319faa 100644 --- a/bertos/kern/proc_test.c +++ b/bertos/kern/proc_test.c @@ -296,7 +296,7 @@ static int preempt_worker_test(void) { \ struct Process *main_proc = (struct Process *) proc_currentUserData(); \ kputs("> Process: " #num "\n"); \ - sig_signal(main_proc, SIG_USER##num); \ + sig_send(main_proc, SIG_USER##num); \ } // Default priority is 0 diff --git a/bertos/kern/sem.c b/bertos/kern/sem.c index 53ef4cc1..3c645e95 100644 --- a/bertos/kern/sem.c +++ b/bertos/kern/sem.c @@ -157,6 +157,8 @@ void sem_obtain(struct Semaphore *s) */ void sem_release(struct Semaphore *s) { + Process *proc = NULL; + proc_forbid(); sem_verify(s); @@ -168,8 +170,6 @@ void sem_release(struct Semaphore *s) */ if (--s->nest_count == 0) { - Process *proc; - /* Disown semaphore */ s->owner = NULL; @@ -178,9 +178,10 @@ void sem_release(struct Semaphore *s) { s->nest_count = 1; s->owner = proc; - ATOMIC(SCHED_ENQUEUE(proc)); } } - proc_permit(); + + if (proc) + ATOMIC(proc_wakeup(proc)); } diff --git a/bertos/kern/signal.c b/bertos/kern/signal.c index 19941f94..71ccf67a 100644 --- a/bertos/kern/signal.c +++ b/bertos/kern/signal.c @@ -65,10 +65,38 @@ * particular event has occurred, because the same signal may be * delivered twice before the process can notice. * - * Any execution context, including an interrupt handler, can deliver - * a signal to a process using sig_signal(). Multiple independent signals - * may be delivered at once with a single invocation of sig_signal(), - * although this is rarely useful. + * Signals can be delivered synchronously via sig_send() or asynchronously via + * sig_post(). + * + * In the synchronous case the process is awakened if it was waiting for any + * signal and immediately dispatched for execution via a direct context switch, + * if its priority is greater than the running process. + * + *
+ * - Synchronous-signal delivery:
+ *
+ *     [P1]____sig_send()____proc_wakeup()____[P2]
+ * 
+ * + * In the asynchronous case, the process is scheduled for execution as a + * consequence of the delivery, but it will be dispatched by the scheduler as + * usual, according to the scheduling policy. + * + *
+ * - Asynchronous-signal delivery:
+ *
+ *     [P1]____sig_post()____[P1]____proc_schedule()____[P2]
+ * 
+ * + * In this way, any execution context, including an interrupt handler, can + * deliver a signal to a process. However, synchronous signal delivery from a + * non-sleepable context (like an interrupt handler) is forbidden in order to + * avoid potential deadlock conditions. Instead, sig_post() can be used from + * any context, expecially from interrupt context or when the preemption is + * disabled. + * + * Multiple independent signals may be delivered at once with a single + * invocation of sig_send() or sig_post(), although this is rarely useful. * * \section signal_allocation Signal Allocation * @@ -146,13 +174,13 @@ sigmask_t sig_wait(sigmask_t sigs) ASSERT(proc_preemptAllowed()); /* - * This is subtle: there's a race condition where a concurrent - * process or an interrupt may call sig_signal() to set a bit in - * Process.sig_recv just after we have checked for it, but before - * we've set Process.sig_wait to let them know we want to be awaken. + * This is subtle: there's a race condition where a concurrent process + * or an interrupt may call sig_send()/sig_post() to set a bit in + * Process.sig_recv just after we have checked for it, but before we've + * set Process.sig_wait to let them know we want to be awaken. * - * In this case, we'd deadlock with the signal bit already set - * and the process never being reinserted into the ready list. + * In this case, we'd deadlock with the signal bit already set and the + * process never being reinserted into the ready list. */ IRQ_DISABLE; @@ -165,20 +193,12 @@ sigmask_t sig_wait(sigmask_t sigs) */ current_process->sig_wait = sigs; - /* - * Go to sleep and proc_switch() to another process. - * - * We re-enable IRQs because proc_switch() does not - * guarantee to save and restore the interrupt mask. - */ - IRQ_ENABLE; + /* Go to sleep and proc_switch() to another process. */ proc_switch(); - IRQ_DISABLE; - /* * When we come back here, the wait mask must have been - * cleared by someone through sig_signal(), and at least - * one of the signals we were expecting must have been + * cleared by someone through sig_send()/sig_post(), and at + * least one of the signals we were expecting must have been * delivered to us. */ ASSERT(!current_process->sig_wait); @@ -227,18 +247,13 @@ sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout) #endif // CONFIG_TIMER_EVENTS - -/** - * Send the signals \a sigs to the process \a proc. - * The process will be awoken if it was waiting for any of them. - * - * \note This call is interrupt safe. - */ -void sig_signal(Process *proc, sigmask_t sigs) +INLINE void __sig_signal(Process *proc, sigmask_t sigs, bool wakeup) { cpu_flags_t flags; - /* See comment in sig_wait() for why this protection is necessary */ + if (UNLIKELY(proc == current_process)) + return; + IRQ_SAVE_DISABLE(flags); /* Set the signals */ @@ -247,17 +262,43 @@ void sig_signal(Process *proc, sigmask_t sigs) /* Check if process needs to be awoken */ if (proc->sig_recv & proc->sig_wait) { - /* - * Wake up process and enqueue in ready list. - * - * Move this process to the head of the ready list, so that it - * will be chosen at the next scheduling point. - */ proc->sig_wait = 0; - SCHED_ENQUEUE_HEAD(proc); + if (wakeup) + proc_wakeup(proc); + else + SCHED_ENQUEUE_HEAD(proc); } - IRQ_RESTORE(flags); } +/** + * Send the signals \a sigs to the process \a proc and immeditaly dispatch it + * for execution. + * + * The process will be awoken if it was waiting for any of them and immediately + * dispatched for execution. + * + * \note This function can't be called from IRQ context, use sig_post() + * instead. + */ +void sig_send(Process *proc, sigmask_t sigs) +{ + ASSERT_USER_CONTEXT(); + IRQ_ASSERT_ENABLED(); + ASSERT(proc_preemptAllowed()); + + __sig_signal(proc, sigs, true); +} + +/** + * Send the signals \a sigs to the process \a proc. + * The process will be awoken if it was waiting for any of them. + * + * \note This call is interrupt safe. + */ +void sig_post(Process *proc, sigmask_t sigs) +{ + __sig_signal(proc, sigs, false); +} + #endif /* CONFIG_KERN_SIGNALS */ diff --git a/bertos/kern/signal.h b/bertos/kern/signal.h index 9e6a9b09..bef44a9e 100644 --- a/bertos/kern/signal.h +++ b/bertos/kern/signal.h @@ -53,7 +53,16 @@ struct Process; /* Inter-process Communication services */ sigmask_t sig_check(sigmask_t sigs); -void sig_signal(struct Process *proc, sigmask_t sig); +void sig_send(struct Process *proc, sigmask_t sig); +void sig_post(struct Process *proc, sigmask_t sig); +/* + * XXX: this is provided for backword compatibility, consider to make this + * deprecated for the future. + */ +INLINE void sig_signal(struct Process *proc, sigmask_t sig) +{ + sig_post(proc, sig); +} sigmask_t sig_wait(sigmask_t sigs); sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout); diff --git a/bertos/kern/signal_test.c b/bertos/kern/signal_test.c index 484c0338..3b5ff1cb 100644 --- a/bertos/kern/signal_test.c +++ b/bertos/kern/signal_test.c @@ -76,29 +76,43 @@ sigmask_t sig_to_slave; * These macros generate the code needed to create the test process functions. */ #define PROC_TEST_SLAVE(index, signal) \ -static void NORETURN proc_signalTest##index(void) \ +static void proc_signalTest##index(void) \ { \ - for(;;) \ - { \ - kputs("> Slave [" #index "]: Wait signal [" #signal "]\n"); \ - sig_wait(signal); \ - kputs("> Slave [" #index "]: send signal [" #signal "]\n"); \ - sig_signal(proc_currentUserData(), signal); \ - } \ + kputs("> Slave [" #index "]: Wait signal [" #signal "]\n"); \ + sig_wait(signal); \ + kputs("> Slave [" #index "]: send signal [" #signal "]\n"); \ + sig_send(proc_currentUserData(), signal); \ } #define MAIN_CHECK_SIGNAL(index, slave) \ do { \ kprintf("> Main: send signal [%d]\n", test_signal[index]); \ - sig_signal(slave, test_signal[index]); \ + sig_send(slave, test_signal[index]); \ kprintf("> Main: wait signal [%d]\n", test_signal[index]); \ sig_wait(test_signal[index]); \ count++; \ } while(0) \ -#define PROC_TEST_SLAVE_STACK(index) PROC_DEFINE_STACK(proc_signal_test##index##_stack, KERN_MINSTACKSIZE); +#if CONFIG_KERN_HEAP + +#define PROC_TEST_SLAVE_INIT(index, master_process) proc_new(proc_signalTest##index, master_process, KERN_MINSTACKSIZE * 2, NULL) + +#else + +#define PROC_TEST_SLAVE_STACK(index) PROC_DEFINE_STACK(proc_signal_test##index##_stack, KERN_MINSTACKSIZE * 2); #define PROC_TEST_SLAVE_INIT(index, master_process) proc_new(proc_signalTest##index, master_process, sizeof(proc_signal_test##index##_stack), proc_signal_test##index##_stack) +PROC_TEST_SLAVE_STACK(0) +PROC_TEST_SLAVE_STACK(1) +PROC_TEST_SLAVE_STACK(2) +PROC_TEST_SLAVE_STACK(3) +PROC_TEST_SLAVE_STACK(4) +PROC_TEST_SLAVE_STACK(5) +PROC_TEST_SLAVE_STACK(6) +PROC_TEST_SLAVE_STACK(7) + +#endif + // Generate the code for signal test. PROC_TEST_SLAVE(0, SIG_USER0) PROC_TEST_SLAVE(1, SIG_USER1) @@ -109,15 +123,6 @@ PROC_TEST_SLAVE(5, SIG_SYSTEM5) PROC_TEST_SLAVE(6, SIG_SYSTEM6) PROC_TEST_SLAVE(7, SIG_SINGLE) -PROC_TEST_SLAVE_STACK(0) -PROC_TEST_SLAVE_STACK(1) -PROC_TEST_SLAVE_STACK(2) -PROC_TEST_SLAVE_STACK(3) -PROC_TEST_SLAVE_STACK(4) -PROC_TEST_SLAVE_STACK(5) -PROC_TEST_SLAVE_STACK(6) -PROC_TEST_SLAVE_STACK(7) - /** * Run signal test */ diff --git a/bertos/mware/event.c b/bertos/mware/event.c index a0419fbf..c596e12f 100644 --- a/bertos/mware/event.c +++ b/bertos/mware/event.c @@ -47,7 +47,7 @@ void event_hook_ignore(UNUSED_ARG(Event *, e)) #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS void event_hook_signal(Event *e) { - sig_signal((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit); + sig_post((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit); } #endif diff --git a/examples/at91sam7/at91sam7.c b/examples/at91sam7/at91sam7.c index 70e21f9c..b8ef86c8 100644 --- a/examples/at91sam7/at91sam7.c +++ b/examples/at91sam7/at91sam7.c @@ -50,6 +50,7 @@ #include #include +#include #include @@ -176,7 +177,13 @@ int main(void) kfile_printf(&ser_fd.fd, "ProcTest..ok!\n"); else kfile_printf(&ser_fd.fd, "ProcTest..FAIL!\n"); - + /* + * Run signal test. + */ + if(!signal_testRun()) + kfile_printf(&ser_fd.fd, "SignalTest..ok!\n"); + else + kfile_printf(&ser_fd.fd, "SignalTest..FAIL!\n"); kputs(AT91SAM7_MSG); diff --git a/examples/at91sam7/at91sam7s.mk b/examples/at91sam7/at91sam7s.mk index e0ada56b..0586ba45 100644 --- a/examples/at91sam7/at91sam7s.mk +++ b/examples/at91sam7/at91sam7s.mk @@ -31,6 +31,7 @@ at91sam7s_CSRC = \ bertos/kern/coop.c \ bertos/kern/preempt.c \ bertos/kern/proc_test.c \ + bertos/kern/signal_test.c \ bertos/kern/monitor.c \ bertos/kern/signal.c \ # diff --git a/examples/at91sam7/at91sam7x.mk b/examples/at91sam7/at91sam7x.mk index 77e45791..436c4445 100644 --- a/examples/at91sam7/at91sam7x.mk +++ b/examples/at91sam7/at91sam7x.mk @@ -32,6 +32,7 @@ at91sam7x_CSRC = \ bertos/kern/coop.c \ bertos/kern/preempt.c \ bertos/kern/proc_test.c \ + bertos/kern/signal_test.c \ bertos/kern/monitor.c \ bertos/kern/signal.c \ # diff --git a/examples/avr-kern/avr-kern.mk b/examples/avr-kern/avr-kern.mk index f241fd7f..d4e2891c 100644 --- a/examples/avr-kern/avr-kern.mk +++ b/examples/avr-kern/avr-kern.mk @@ -16,6 +16,7 @@ avr-kern_PROGRAMMER_PORT = none avr-kern_USER_CSRC = \ examples/avr-kern/main.c \ bertos/kern/proc_test.c \ + bertos/kern/signal_test.c \ bertos/mware/sprintf.c \ # diff --git a/examples/avr-kern/main.c b/examples/avr-kern/main.c index b1e502c3..ed2113e7 100644 --- a/examples/avr-kern/main.c +++ b/examples/avr-kern/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include static void init(void) @@ -27,6 +28,7 @@ int main(void) kputs("\n"); proc_testRun(); + signal_testRun(); while (1) cpu_relax(); diff --git a/examples/benchmark/kernel-core_avr/main.c b/examples/benchmark/kernel-core_avr/main.c index 190c3384..052e484d 100644 --- a/examples/benchmark/kernel-core_avr/main.c +++ b/examples/benchmark/kernel-core_avr/main.c @@ -49,7 +49,7 @@ int main(void) while (1) { - sig_signal(p, SIG_USER0); + sig_send(p, SIG_USER0); proc_yield(); } diff --git a/examples/benchmark/kernel-only_arm/main.c b/examples/benchmark/kernel-only_arm/main.c index 1c81b565..2455abf1 100644 --- a/examples/benchmark/kernel-only_arm/main.c +++ b/examples/benchmark/kernel-only_arm/main.c @@ -34,7 +34,7 @@ int main(void) Msg *msg_re = msg_get(&in_port); msg_reply(msg_re); // generate code for signals - sig_signal(p, SIG_USER0); + sig_send(p, SIG_USER0); sig_wait(SIG_USER0); return 0; diff --git a/wizard/BWizardPage.py b/wizard/BWizardPage.py index 980cb45c..be667562 100644 --- a/wizard/BWizardPage.py +++ b/wizard/BWizardPage.py @@ -33,12 +33,16 @@ # Author: Lorenzo Berni # +import os + from PyQt4.QtCore import * from PyQt4.QtGui import * from PyQt4 import uic import qvariant_converter +import const + class BWizardPage(QWizardPage): """ Base class for all the wizard pages. It has the utility method used in all @@ -47,7 +51,7 @@ class BWizardPage(QWizardPage): def __init__(self, wizardGui, parent = None): QWizardPage.__init__(self, parent) - self.pageContent = uic.loadUi(wizardGui, None) + self.pageContent = uic.loadUi(os.path.join(const.DATA_DIR, wizardGui), None) layout = QVBoxLayout() layout.addWidget(self.pageContent) self.setLayout(layout) diff --git a/wizard/bertos.py b/wizard/bertos.py index 05ecf7af..e4255177 100755 --- a/wizard/bertos.py +++ b/wizard/bertos.py @@ -61,6 +61,7 @@ from BFinalPage import BFinalPage from BEditingDialog import BEditingDialog, BVersionDialog, BToolchainDialog import bertos_utils +import const from LoadException import VersionException, ToolchainException @@ -79,7 +80,7 @@ def newProject(): relevant_file = relevant_files[ide] QProcess.startDetached(command_line, [relevant_file,]) sys.exit() - + def editProject(project_file): info_dict = {} while(True): @@ -119,19 +120,20 @@ def showStartPage(): QApplication.instance().dialog.show() def main(): - os.chdir(os.path.dirname(os.path.abspath(sys.argv[0]))) app = QApplication(sys.argv) app.settings = QSettings("Develer", "Bertos Configurator") app.project = BProject.BProject() # Development utility lines, to be removed for production - if not (hasattr(sys, "frozen") and sys.frozen) and newer("bertos.qrc", "bertos.rcc"): - os.system("rcc -binary bertos.qrc -o bertos.rcc") - QResource.registerResource("bertos.rcc") + datadir = const.DATA_DIR + qrc, rcc = os.path.join(datadir, 'bertos.qrc'), os.path.join(datadir, 'bertos.rcc') + if not (hasattr(sys, "frozen") and sys.frozen) and newer(qrc, rcc): + os.system("rcc -binary %s -o %s" %(qrc, rcc)) + QResource.registerResource(rcc) if len(sys.argv) == 3 and sys.argv[1] == "--edit": editProject(sys.argv[2]) else: newProject() - + if __name__ == '__main__': main() diff --git a/wizard/bertos_utils.py b/wizard/bertos_utils.py index 004e67bf..5fbd6914 100644 --- a/wizard/bertos_utils.py +++ b/wizard/bertos_utils.py @@ -167,7 +167,7 @@ def createBertosProject(project_info, edit=False): mergeSources(srcdir, sources_dir, old_sources_dir) # Destination makefile makefile = directory + "/Makefile" - makefile = open("mktemplates/Makefile").read() + makefile = open(os.path.join(const.DATA_DIR, "mktemplates/Makefile"), 'r').read() makefile = makefileGenerator(project_info, makefile) open(directory + "/Makefile", "w").write(makefile) # Destination project dir @@ -219,16 +219,16 @@ def createBertosProject(project_info, edit=False): f.close() if not edit: # Destination user mk file (only on project creation) - makefile = open("mktemplates/template.mk", "r").read() + makefile = open(os.path.join(const.DATA_DIR, "mktemplates/template.mk"), "r").read() makefile = mkGenerator(project_info, makefile) open(prjdir + "/" + os.path.basename(prjdir) + ".mk", "w").write(makefile) # Destination wizard mk file - makefile = open("mktemplates/template_wiz.mk", "r").read() + makefile = open(os.path.join(const.DATA_DIR, "mktemplates/template_wiz.mk"), "r").read() makefile = mkGenerator(project_info, makefile) open(prjdir + "/" + os.path.basename(prjdir) + "_wiz.mk", "w").write(makefile) # Destination main.c file if not edit: - main = open("srctemplates/main.c", "r").read() + main = open(os.path.join(const.DATA_DIR, "srctemplates/main.c"), "r").read() open(prjdir + "/main.c", "w").write(main) # Files for selected plugins relevants_files = {} diff --git a/wizard/const.py b/wizard/const.py index 4f226328..697cd463 100644 --- a/wizard/const.py +++ b/wizard/const.py @@ -33,6 +33,14 @@ # Author: Lorenzo Berni # +import os, sys + +_tmp = sys.argv[0] +if os.path.islink(_tmp): + _tmp = os.readlink(_tmp) +DATA_DIR = os.path.dirname(os.path.abspath(_tmp)) +del _tmp + CPU_DEF = { "CPU_NAME": "", "CPU_DIR": "", diff --git a/wizard/exception_handler.py b/wizard/exception_handler.py index 1dc3405c..9e54fa69 100644 --- a/wizard/exception_handler.py +++ b/wizard/exception_handler.py @@ -42,6 +42,8 @@ from PyQt4.QtGui import * def _excepthook(exc_type, exc_value, exc_traceback): project_dir = QApplication.instance().project.info("PROJECT_PATH") + if not project_dir: + project_dir = os.getcwd() file_name = os.path.join(project_dir, "wizard_error.log") if os.path.exists(file_name): content = open(file_name, "r").read() @@ -55,6 +57,7 @@ def _excepthook(exc_type, exc_value, exc_traceback): f.write(">"*80 + "\n") f.write(content) f.close() + print>>sys.stderr, message QMessageBox.critical( None, "Exception occurred", diff --git a/wizard/plugins/codelite.py b/wizard/plugins/codelite.py index f6555a8b..7f4daac8 100644 --- a/wizard/plugins/codelite.py +++ b/wizard/plugins/codelite.py @@ -99,7 +99,7 @@ def codeliteProjectGenerator(project_info): """ Returns the string rapresenting the codelite project. """ - template = open("cltemplates/bertos.project", "r").read() + template = open(os.path.join(const.DATA_DIR, "cltemplates/bertos.project"), "r").read() filelist = "\n".join(clFiles(findSources(project_info.info("PROJECT_PATH")), "")) debugger_path = project_info.info("TOOLCHAIN")["path"].replace("gcc", "gdb") init_script = project_info.info("CPU_INFOS")["GDB_INIT_SCRIPT"] @@ -118,7 +118,7 @@ def codeliteWorkspaceGenerator(project_info): """ Returns the string rapresentig the codelite workspace. """ - template = open("cltemplates/bertos.workspace", "r").read() + template = open(os.path.join(const.DATA_DIR, "cltemplates/bertos.workspace"), "r").read() project_name = os.path.basename(project_info.info("PROJECT_PATH")) while template.find("$project") != -1: template = template.replace("$project", project_name)