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.
Hello,
I'm using the Realview RTX and facing an issue of how to dynamically allocate a mailbox.
What I'm trying to create a reentrant function, which is called by some RTX tasks, and uses a mailbox to communicate with another task. I search through the RL-ARM manual and forum but all the examples show that the mailbox is declared globally. If so, the function is not reentrant anymore.
I have ask the Keil support but haven't received any response for this issue yet. So I put it here in hope that anyone could have the solution.
Thanks in advance for your answer.
Huy
Hello Robert,
I thought about the way you suggest but I think there's a problem doing that way. When you declare the mailbox locally in the function, it shall be pushed to stack of the task when call other function, for example os_mbx_send(), or switch to another task, and the address use by the mailbox may be re-used for another variables in the new function/task. So there will be an issue here.
I'm thinking about using _alloc_box() to dynamically allocate the mailbox. My idea is below:
This is declare globally:
// We declare this mailbox for getting size of it os_mbx_declare(ReponseMailbox, 1); // Declare a box for dynamically allocate mailbox _declare_box(ReponseMailboxMemPoll, sizeof(ResponseMailbox), 16);
And in the CommFunc:
void CommFunc (U8 func_code, void *socket_data) { ... // Dynamically allocate a mailbox ptResponseMailbox = _alloc_block(ResponseMailbox, sizeof(ResponseMailbox); // Allocate the memory for TcpNetFuncObj ptFuncObj = malloc(sizeof(struct TcpNetFuncObj); // Setup the structure data ptFuncObj->u8TcpNetFuncCode = func_code; ptFuncObj->ResponseMailbox = ptResponseMailbox; ptFuncObj->ptSocketData = socket_data; // Send this to a Request Mailbox which is // tcp_poll task is waiting. os_mbx_send(RequestMailbox, (void *)ptFuncObj, 10); // Now wait for the response from tcp_poll task os_mbx_wait(ptResponseMailbox, &(ptFuncObj), 10); // Process the response here ... // Deallocate ptFuncObj free(ptFuncObj); // Deallocate Response Mailbox here. _free_box(ResponseMailbox, ptResponseMailbox); }
So do you think that my idea is correct?
An object allocated on the stack is valid until the function in question returns.
In this case, your function CommFunc() does not return until it has received the answer - so no problem that the memory gets reused while you are waiting for the answer.
No it is still is just as incorrect. The box allocated mailbox will be valid no longer than the stack allocated mailbox. If the os_mbx_wait times out after 10 OS_TMR_TICKS, you are hosed both ways.
The only reason I showed how to dynamically allocate a mailbox was because that is what the OP asked, not because I would use the feature. It is VERY hard to make correct code that provides something usefull with a dynamic mailbox. It is better to use something that is actually helps you to create correct code. You would much better off using either a single static mailbox per task or a event. I would probably use the event, because it could be "hidden" (i.e the task calling the CommFunc does not need to have any prior knowledge of the Event use - which was the benefit you were trying to gain by using the dynamic mailbox in the first place)
I have posted to this thread as i think its of the same vain!
I have a multiple (4of)task application passing messages via mailbox's (2of). I have one mailbox and its associated tasks works fine, i have a second task the call to the mail box works fine, however refuses to call the function within the task. See code below
this task works fine void tcp_task (void) __task { U8 *ptr_tcp_task_msg; while (1) { if(os_mbx_wait(TCP_task_msg_box, (void**)&ptr_tcp_task_msg, 0x0000) == OS_R_OK ){ /* if we have received a message decided what action to take */ switch(*ptr_tcp_task_msg){ case TCPTASK_DNS_ROUTINE: start_DNS_resolve((dns_struct*)tcp_task_msg); break; default: start_DNS_resolve((dns_struct*)tcp_task_msg); break; } } /* DNS routine */ if ( dns_resolve.DNS_active == __TRUE){ get_host_by_name((U8*)dns_resolve.ptr_dns_task_data->name, dns_cbfunc); } main_TcpNet(); os_tsk_pass(); } }
This mailbox functions fine however,
The one below fails the message arrives will break on UARTSend function can see data in via message pointer but, fails to call function moves to os_tsk_pass.
void communication_task (void) __task{ global_msg_struct *ptr_global_msg; while (1) { if(os_mbx_wait(communication_task_msg_box,void**&ptr_global_msg, 0xFFFF) == OS_R_OK ){ /* if we have received a message decided what action to take */ //init_serial_port0(); UARTSend((U8*) ptr_global_msg->tx_data ); } os_tsk_pass(); } }
Any comments welcome on the topic, tried calling a simpler function init_serial_port() this fails in same way. Though when called from init_task at start functioned ok.
The mailbox in the second case is external linked using OS_MBX as its in included file, but the mail box itself seems to work fine.
Obviously issue with the boxes i guess any pointers? excuse the pun, or similar issues in the past.
regards Darren