We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I'm trying to use multiple maibox for communication between a parent task to other tasks daughters. But my parent task can only communicate with a single child task, after which the system seems to stop.
/* Struct messages */ struct mbx_messages { u8 cmd, ok; u8 pack[10]; }; /* Mailbox declarations */ os_mbx_declare(mbx_task_master, 1); os_mbx_declare(mbx_task_slave_1, 1); os_mbx_declare(mbx_task_slave_2, 1); /* Memory pool */ _declare_box(mbx_pool, sizeof(struct mbx_messages), 6); /* Master task */ __task void master_task(void) { struct mbx_messages *snd_msg, *rcv_msg; os_dly_wait(4); while(1) { os_dly_wait(4); if(uart_2_read_byte() == 'S') { if(os_mbx_check(&mbx_qtotalizer_sweepfp) != 0) { snd_msg = _alloc_box(mbx_pool); snd_msg->cmd = 1; os_mbx_send(&mbx_task_slave_1, snd_msg, 10); if(os_mbx_wait(&mbx_task_master, (void *)&rcv_msg, 10) != OS_R_TMO) { if(rcv_msg->cmd == 2) { snd_msg = _alloc_box(mbx_pool); snd_msg->cmd = 3; os_mbx_send(&mbx_task_slave_2, snd_msg, 10); if(os_mbx_wait(&mbx_task_master, (void *)&rcv_msg, 10) != OS_R_TMO) { if(rcv_msg->cmd == 4) { uart_2_write_str("cmd = 4\n"); } } } else { uart_2_write_str("cmd != 2\n"); } } _free_box(pool_sweepfp, rcv_msg); } } } } /* Slave 1 task */ __task void slave_1_task(void) { struct mbx_messages *snd_msg, *rcv_msg; os_dly_wait(4); while(1) { if(os_mbx_wait(&mbx_task_slave_1, (void *)&rcv_msg, 10) != OS_R_TMO) { snd_msg = _alloc_box(mbx_pool); if(rcv_msg->cmd == 1) snd_msg->cmd = 2; else uart_2_write_str("cmd != 1\n"); os_mbx_send(&mbx_task_master, snd_msg, 10); } _free_box(pool_sweepfp, rcv_msg); } } /* Slave 2 task */ __task void slave_2_task(void) { struct mbx_messages *snd_msg, *rcv_msg; os_dly_wait(4); while(1) { if(os_mbx_wait(&mbx_task_slave_2, (void *)&rcv_msg, 10) != OS_R_TMO) { snd_msg = _alloc_box(mbx_pool); if(rcv_msg->cmd == 3) snd_msg->cmd = 4; else uart_2_write_str("cmd != 4\n"); os_mbx_send(&mbx_task_master, snd_msg, 10); } _free_box(pool_sweepfp, rcv_msg); } } /* Boot task */ __task void boot_task(void) { uart_2_open(9600); _init_box(mbx_pool, sizeof(mbx_pool), sizeof(struct mbx_messages)); os_mbx_init(&mbx_task_master, sizeof(mbx_task_master)); os_mbx_init(&mbx_task_slave_1, sizeof(mbx_task_slave_1)); os_mbx_init(&mbx_task_slave_2, sizeof(mbx_task_slave_2)); os_tsk_create(master_task, 11); os_tsk_create(slave_1_task, 12); os_tsk_create(slave_2_task, 13); } /* Main */ int main(void) { os_sys_init(boot_task); }
That a call will be _free_box is not clearing the message sent recently? Message allocated by _alloc_box is automatically removed by os_mbx_wait?
If the master task only start one slave task at a time, and don't start a new task before the previous task is done, then you don't need multiple child tasks. It's enough with a single "worker" tasks that waits for a job to be handed out. The worker task checks what to do, performs the task and then report back before starting to wait for next thing to do.
The main reason for a program to consist of 4 tasks is that the individual tasks are likely to need to run concurrently with each other. Things that can be handled in sequence shouldn't be splitted into separate tasks unless you work on a hyperthreaded or multicore processor and wants to process multiple, non-related work blocks, concurrently.
So an image-processing program may have multiple tasks to get a quad-core processor to process a large 20Mpix image four times faster - or to process four images concurrently.
But an image-processing program running on a single-threaded processor would add complexity while slowing down the program, by having multiple threads to try to concurrently work with same image or concurrently work on multiple images.
In the end, you should make some form of sequence diagram where you show what things that needs to be performed concurrently by having multiple threads time-slicing through the work or where a higher-priority thread must be able to interrupt and perform a more important task before releasing the processor to lower-priority threads.
And that sequence diagram should also concern itself with how a higher-prio thread can lock up a lower-prio thread. Or how a lower-prio thread taking a resource lock can lock up a higher prio thread.
In the end - programs should be written as well-defined modules. So functionality is broken down into small and easy-to-understand functions. But these functions shouldn't be run by individual threads unless there is needs for concurrency. Or the sequence diagram becomes too complex if the work isn't split into multiple threads interacting using simple, and easy to overview, signaling, messaging, ... mechanisms.
Ok, as my processor is LPC2478 and the best option is to do a single task with sequential requests. Other tasks of my application would be:
display_update_task - Driven by update event or os_dly_wait log_save_task - Driven by mailbox for burning logs on the memory card
Thanks for the help.
That looks like reasonable tasks - thinks that is valuable to do concurrently.