(all the code below needs unistd.h and tm.h)
Threads are created with the execi() call. It takes 3 arguments:
pid_t t1...tn;
int stop_process(void);
int main(void) {
t1=execi(&stop_process,1,DEFAULT_STACK_SIZE); /* handle the "run" button
to stop the program */
tn=execi(...) /* all the other threads in the system */
tm_start(); /* start the threads running */
return 0;
}
The code within the stop_process() call tree would handle the shutdown
of the other threads (more on this in a bit).
Threads should be nice to each other and release their timeslice when they are done with their processing. If a thread is waiting on an event there are ways to test the event and then quickly hand control to another thread. For front panel buttons:
#include "direct-button.h"
wakeup_t button_press_wakeup(wakeup_t data) {
return(PRESSED(button_state(),data));
}
wakeup_t button_release_wakeup(wakeup_t data) {
return(RELEASED(button_state(),data));
}
int stop_process(void) {
wait_event(&button_release_wakeup,BUTTON_RUN);
msleep(250); /* debounce the button */
wait_event(&button_press_wakeup,BUTTON_RUN);
kill(t1); /* stop the other threads */
...
kill(tn);
return(0);
}
For sensors:
#include "direct-sensor.h"
#include "direct-motor.h"
wakeup_t bumper_hit(wakeup_t data) {
return (data<32768);
}
int hit_something(void) {
wait_event(&bumper_hit,SENSOR_1);
motor_a_dir(off);
}
The wait_event call will poll the function until it returns non-zero.
(this is actually handled within the thread scheduler, so is fairly
efficient)
For threads that wish to release their timeslice directly there is the yield() call.
To stop a thread from within the thread a call to exit(return_code) is used. To kill a thread from another thread the kill(thread_handle) call is used. Remember that stuff like motor states are not associated with any thread and will only be automatically stopped when the main program calls exit().
Here is a test program for the floating point routines. It solves for the square root of 2 and prints it on the display.
#include "conio.h"
#include "unistd.h"
#include "direct-button.h"
#include "sys/tm.h"
pid_t t1,t2;
wakeup_t button_press_wakeup(wakeup_t data) {
return PRESSED(button_state(),data);
}
wakeup_t button_release_wakeup(wakeup_t data) {
return RELEASED(button_state(),data);
}
#define ABS(x) (((x)<0)?(-(x)):(x))
#define TOLERANCE 0.00001 /* display is only 4 digits wide anyway */
int root_solver(void) {
float value=2.0;
float x=value/2.0,delta=1.0;
int count=0;
/* use a Newtonian root solver to get sqrt(value) */
while ((ABS(delta)>TOLERANCE) && (count++<100))
x+=(delta=(value-x*x)/(2.0*x));
lcd_number((int)(x*1000),sign,e_3);
lcd_refresh();
return(0);
}
int prog_stopper(void) {
wait_event(&button_release_wakeup,BUTTON_RUN);
msleep(200);
wait_event(&button_press_wakeup,BUTTON_RUN);
kill(t1);
return(0);
}
int main(void) {
lcd_clear();
lcd_refresh();
t1=execi(&root_solver ,1,DEFAULT_STACK_SIZE);
t2=execi(&prog_stopper,2,DEFAULT_STACK_SIZE);
tm_start();
return 0;
}
|
| Previous - Downloading the SREC Files to the Brick | Main | Next - Sensors |