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.
Hi forum users, A few days ago I started struggling with the following problem. When opening three or more concurrent http sessions over a PPP interface my application crashes and the debugger tells me it always happens with the top of the call stack beeing in ppp_send() or ppp_receive() functions.
It seems both those functions fail when trying to allocate some memory by calling alloc_mem(). Suspecting this could have been caused by unproper resources allocation for the whole TcpNet stuff, I tryed raising the memory pool size in NetConfig.c but with no luck. Is such memory really allocated from the TcpNet memory pool or am I on the wrong way?
One more bit. No such effect is visible using concurrent modbus sessions on the same TCP / PPP stack (enabling every available modbus communications however reduces the number of concurrent http sessions I can trigger without crashing). I realize http involves more resources and I still suspect an incorrect sizing for memory. It also seems there is some relationship with the size of the file being transferred by http. Bigger files make the thing crash even with less concurrent http sessions.
A couple questions arise. Can anyone suggest a reasonable rule-of-thumb for choosing a 'safe' memory pool size? I'm using a total of 10 sockets, with max 5 http sessions. No application level protocol is enabled other then http.
And then... is an error allocating memory at the sending/receiving stage of the PPP layer supposed to be a critical error? Could this otherwise be handled by discarding the packet the way we do at MAC level? This is more a confirmation request than a true question, since I suspect some reliability is assumed at that level of the stack.
TIA Regards, Andrea
We have not found such problems with PPP examples. If a PPP fails to allocate memory, it should hang in an sys_error() error handler function. In your case it does not hang, so it seems this is not your real problem.
Are you using an RTOS? With an RTOS you should first check the stack size for TCPnet task. In our examples, we use 800 byte stack for TCPnet RTX task. Check also the private stack declarations. If you are using several modules and:
extern U64 tcp_stack[256];
might be dangerous if in external file it is not declared with the same size as declared here and you are using sizeof (tcp_stack). If tcp_stack is not allocated correctly, you may receive sporadic application crashes when using an RTOS.
TCPnet functions are not reentrant so it is dangerous to call them from several tasks.
If you are using Interrupt Serial driver, check the size of the IRQ stack, set in the startup.s file. The IRQ Stack Size shall be 256 bytes or more.
If you are using __swi functions, then also the Supervisor Stack shall be set to 128 bytes or more.
Franc
Hi Franc,
In fact, hanging in sys_error() was the behavior when I first saw this a few days ago. Repeating the tests today showed the execution being trapped in the DAbt_Handler instead. By inspecting R14 register I calculated the instruction causing the exception and discovered it to be in ppp_receive(), not far from the alloc_mem().
I just figured out that, in the meanwhile, there was a change in sys_error() to avoid hanging (for production that would be unacceptable and some sort of reset should be put in place). By rolling back to the while(1) in sys_error(), I actually see the task hanging there with the reported call stack. Does this change the focus?
As an RTOS, we are using RTX kernel from Keil. The stack is allocated and referenced in a single module as:
U32 TCPStk[200]
Other stack sizes are set up as follows (in LPC2300_RTX.s):
UND_Stack_Size EQU 0x00000000 SVC_Stack_Size EQU 0x00000080 ABT_Stack_Size EQU 0x00000000 FIQ_Stack_Size EQU 0x00000000 IRQ_Stack_Size EQU 0x00000100 USR_Stack_Size EQU 0x00000050
Hope to have slightly clarified the situation.
Andrea
There is a potential problem in the following declaration:
The ARM-runtime libraries require 8-byte stack alignment. AFAIK the floating point and double precision arithmetic do. Please change this to:
U64 TCPStk[100];
Not 8-byte aligned stack may cause RTX to fail and crash when ARM-runtime libraries are used.
Returning from sys_error() is dangerous because the TCPnet relies on the fact that mem_alloc() always return allocated memory. If you have modified this function that it returns, you will for sure get Data Abort or Prefetch Abort. I believe that is what you get in your application. The sys_error function is called on fatal - non-recoverable errors.
I'm back on this after trying a few changes following your suggestions. I 8-byte aligned my stacks but this didn't help.
Now I'm not returning anymore from sys_error() and what I see is the application hanging there as soon as I try to open three or more http sessions over the PPP link. This is always happening because of a failed alloc_mem() called by ppp_send()/receive() functions. Apart from this the system seems stable.
Don't you think this could be "simply" my underestimation of the resources required at runtime by the application? Can you suggest any guideline for choosing a 'safe' memory pool size? I'm using a total of 10 sockets, allowing a maximum of 5 http sessions. No application level protocol is enabled other then http.
You say TcpNet functions should not be called from different tasks. Do you mean that you can't call the same function from different task or that ANY call to ANY TcpNet function must be issued by the same task? Is it true also for main_TcpNet()?
Regards, Andrea
TCPnet protocol stack is a highly optimized stack and does not consume a lot of dynamic memory. However a PPP addon needs more because the ppp packets are constructed by copying the data into another allocated buffer with PPP encapsulation.
I think that in your case a 16 KByte memory pool would be enough. However you may experiment with the size of the memory pool until you do not get any application hangs.
ANY TCPnet function shall not be called from a different task than the tcp_task. This applies also to main_TcpNet().