> >Unfortunately, no PIC (not even the 17Cxx) can at present handle the > >general case of cooperative multi-tasking, where either/any process may > >execute a yield() from within nested procedures. The normal method for > > However, if one is wise, he will write his procedures such that the process > in question is safely completed, and he may with a state machine pick up > where he left off. > > This is how I do it, anyway. Right; sometimes that works well. On the other hand, which is easier to read [compressed to save vertical space]: /*** EXAMPLE ONE ***/ void out_char(char ch) { while (IO_busy) yield(); IO_serial_out = ch; } void out_string(char *ch) { while (*ch) out_char(*ch++); } void delay(unsigned int t) { unsigned int start=systime; while (((unsigned int)(systime-start)) < t) yield(); } void test(void) { while(1) { out_string("Hello there!"); delay(50); out_string("This was a test!"); delay(500); } } ... or this ... /*** EXAMPLE TWO ***/ (void)(*curr_function)(); (void)(*next_function)(); char *str_p; unsigned int delay_start, delay_time; void func_out_string(void) { if (IO_busy) return; IO_serial_out = *str_p++; if (!*str_p) curr_function = next_function; } void out_string(char *st) { curr_function = func_out_string; str_p = st; } void func_wait(void) { if (((unsigned int)(systime-delay_start)) >= delay_time) curr_function = next_function; } void delay(unsigned int t) { curr_function = func_wait; delay_start = systime; delay_time = t; } void func_test1(void) { out_string("Hello there!"); next_function = func_test2(); } void func_test2(void) { delay(50); next_function = func_test3(); } void func_test3(void) { out_string("This was a test!"); next_function = func_test4; } void func_test4(void) { delay(500); next_function = func_test1; } void start_test(void) { curr_function = func_test1; } void yield(void) /* Called by other procedure */ { curr_function(); } While this particular instance of Example Two could have been done somewhat more nicely (taking advantage of the simplicity of 'test', adding more functions to test (e.g. wait until character is input) would make the Example Two method significantly more complicated while requiring only simple additions to the code in Example One. On machines that support it, cooperative multitasking via stack-switching can be an efficient way to produce complex systems with reasonable, readable code. The biggest wrinkle often comes with 'smart' compilers: rather than using stack frames, many compilers use one of several algorithms to allocate variables statically. Unfortunately, if such a compiler isn't made aware that two routines may indirectly call each other, it may overlay those routines' variables. Such errors can cause many types of bizarre failures and can be hard to track down. Nonetheless, when used as part of a sound design, cooperative multitasking on CPU's that support it is often a good way to make systems both efficient and maintainable.