tass-belgium / picotcp

PicoTCP is a free TCP/IP stack implementation
Other
1.17k stars 218 forks source link

Problem in 'pico_protocol_network_loop' #459

Open mageshwaransekar opened 7 years ago

mageshwaransekar commented 7 years ago

Hi

I'm porting picoTCP to an embedded system using our own baremetal system, which means I've implemented custom memory allocation functions,etc. I'm running into a problem in the function "pico_stack_tick" after the hardware ethernet init. Normally, there are few functions being called from "pico_stack_tick": pico_protocol_datalink_loop, pico_protocol_network_loop, pico_protocol_transport_loop, etc.. However, it couldn't get pass network_loop. I'm not sure why. For the moment, I'm only able to detect in which function it gets stuck, due to limitation in debugging (currently using printf as debug option). Do you have any idea why I'm facing this problem?

struct pico_device *pico_eth_create(const char *name){
  /* Create device struct */
  struct pico_device* eth_dev = PICO_ZALLOC(sizeof(struct pico_device));
  if(!eth_dev) {
      return NULL;
  }

  HW_eth_init();

  eth_dev->send = pico_eth_send;
  eth_dev->poll = pico_eth_poll;

  if( 0 != pico_device_init(eth_dev, name, get_MAC_addr())) {
      dbg("Device init failed.\n");
      PICO_FREE(eth_dev);
      return NULL;
  }

  return eth_dev;
}

Main function:

int main(){
   int id;
   struct pico_ip4 ipaddr, netmask;
   struct pico_device* dev;

   pico_stack_init();

   /* create the tap device */
   dev = pico_eth_create("eth0");
   if (!dev) return -1;

   pico_stack_tick();

   /* assign the IP address to the tap interface */
   pico_string_to_ipv4("10.0.0.2", &ipaddr.addr);
   pico_string_to_ipv4("255.255.255.0", &netmask.addr);
   pico_ipv4_link_add(dev, ipaddr, netmask);

   while(1){
     pico_stack_tick();
     PICO_IDLE();
   }
}

Thanks in advance.

frederikvs commented 7 years ago

Hi, I apologise for the delay in getting back to you. Earliest Deadline First scheduling is not kind to tasks without a strict deadline...

You say you can't get past network_loop, but on which call to pico_stack_tick is that? Before the link_add, or the one in the while loop? (Or an even earlier one, there are a few hidden calls in the pico_stack_init as well.)

Also, are you using interrupts? Just a guess, but it could be that some interrupt is firing (related to the ethernet device you're using?) but that the default interrupt handler is still set, which is quite often an infinite loop. This could look like it's happening in the network_loop, while it would actually be happening a specific time after doing something hardware-related (in the device_loop perhaps? Or during setup of the device?).

mageshwaransekar commented 7 years ago

Actually, I've commented out pico_stack_tick found in the pico_stack_init function since it is being called before pico_eth_create and causes problem in pico_devices_loop. So the first call to pico_stack_tick is made from main.I couldn't get past network_loop from the first call of pico_stack_tick (which is before link_add in main.

And, I'm using poll instead of interrupt routine.

frederikvs commented 7 years ago

The pico_stack_tick in the init function should not cause problems. It is always called before creating and inserting the device, the stack should be able to handle that. That means something else is going wrong.

Have you made any other modifications in the stack?

Could you check, just to be sure, what happens when you don't use any of your driver's functions at all? Just init the stack and start ticking - obviously it won't be able to send out packets, but if everything's working properly, the ticks should just keep looping. If the stack still hangs somewhere within the first tick, maybe examine whether the call stack isn't overflowing, and whether your memory allocator is behaving as it should be. Though to be honest, this is going to be rather hard without proper debugging tools (e.g. gdb or similar)...

mageshwaransekar commented 7 years ago

It seems that we have a small complication (might be due to compiler) where global variable is not properly initialized if a NULL pointer is passed. For example,

void *ptr=NULL; int main(){ ... }

I have to initialize it in main function

void *ptr; int main(){ ptr = NULL; }

Thus, certain structures of picotcp need to be initialized in a function rather than during global declaration. How can I properly declare those global variables/structures (ex: pico_tree_node, etc.) in a function?

maximevince commented 7 years ago

@MageshwaranSekar. In that case your should check the ".bss" section initialization of your startup-routine (pre-C environment). Meanwhile, also check if ".data" section initialization is working properly (this is where initialized, non-zero variable are stored). For running C code, it is a requirement that the .bss-section must be zero-initialized, and the .data-section is initialized with its proper values. This has nothing to do with picotcp-specific code.