FNET - TCP/IP Stack

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FNET - TCP/IP Stack

44,765 Views
butok
NXP Employee
NXP Employee

FNET TCP/IP stack: Version 0.5.0 released. 
 

FNET Home page: http://fnet.sourceforge.net/

    Please, submit your feature requests and feedbacks here:

    http://sourceforge.net/tracker/?group_id=253892&atid=1126921 

    Please, submit your bug reports here:

    http://sourceforge.net/tracker/?group_id=253892&atid=1126920

 

FNET brief information:
The FNET is a free, open source software project (under GNU GPLv3) for building embedded communication software using the Freescale processors.

 

The stack provides following protocols and services:
  * Supported platforms:
     - Reindeer - MCF5282 (M5282EVB).
     - Kirin2 - MCF52235 (M2235EVB).
     - Kirin3 - MCF52259 (M2259EVB).
     - Lasko - MCF51CN128 (TWR-MCF51CN).
     - Other Freescale platforms to be supported soon.
  * Available as:
     - Stand-alone version. No underlying RTOS is required, although it can be used with it.
  * Supported Compilers:
     - Freescale CodeWarrior for ColdFire Version 7.1.
     - Freescale CodeWarrior for Microcontrollers Version 6.2.
  * BSD-style Socket layer API
  * Protocols:
     - User Datagram Protocol (UDP).
     - Transmission Control Protocol (TCP).
     - Internet Protocol (IPv4).
     - Internet Control Message Protocol (ICMP).
     - Address Resolution Protocol (ARP).
  * Network Interfaces:
     - Ethernet interface.
     - Loopback interface.
  * Services:
     - HTTP/0.9 server. Both SSI and CGI are supported.
     - DHCP client.
     - TFTP client.
     - Static File System.
     - CFM Flash driver.
  * Tools:
     - GUI File System Generation Tool.
  * Applications:
     - TFTP Bootloader.
     - Shell Application.
  * Doxygen User Documentation.

 

 Changes in 0.5.0 (since last public version):
 - Added TFTP client.
 - Added Coldfire Flash Module (CFM) driver.
 - Added FNET TFTP Bootloader.
 - Fixed DHCP client.
 - Updated Shell Demo application. Application parameters are saved in the flash.
 - Improved Shell library. Added blocking-command and multi-word parameter features.
 - A lot of other changes and fixes.

 

Best regards,

Andrey Butok

Labels (1)
Tags (2)
225 Replies

3,053 Views
albertolubeiro
Contributor III

Hi Andrey,

I am using K60 and i would like to save in memory the build date and time.

I have seen in fnet.h the define "define FNET_BUILD_DATE     __DATE__ " at " __TIME__" but i don't see where do you use it and neither the definition of __DATE__ and __TIME__

Can you help me?

Thanks and best regards

0 Kudos

3,053 Views
butok
NXP Employee
NXP Employee

For example, FNET_BUILD_DATE is used by FNET demo application, in welcome message and in the HTTP SSI demo web-page.

BTW: __DATE__  and __TIME__ are generated by compiler.

0 Kudos

3,053 Views
albertolubeiro
Contributor III

Hi Andrey,

Last question. I am usin codewarrior 10.2 where and how can i "configure" __DATE__ and __TIME__

Thanks!!

0 Kudos

3,053 Views
TomE
Specialist II

> where and how can i "configure" __DATE__ and __TIME__

As Andrey has already said, you can't. These definitions are part of the C Language Standard.

You should read the documentation provided with the compiler to find out about these.

For instance, here's the documentation for gcc. You may find some more useful ones you don't know about.

Standard Predefined Macros - The C Preprocessor

Tom

0 Kudos

3,053 Views
albertolubeiro
Contributor III

Hi Andrey, Tom

Thanks for your help, I'll take a look.

Best regards

0 Kudos

3,053 Views
butok
NXP Employee
NXP Employee

No configuration needed.

__DATE__ and __TIME__ are a preprocessor macro that expands to current date and compile time as a string automatically during compilation.

It is time to upgrade to newer CW10.5 compiler. (10.2 is not supported).

0 Kudos

3,054 Views
paul1962
Contributor I

Hello,

I'm looking at porting FNET to another processor.

Fortunately the MCF54418 is close in some ways to the MCF53017 I will be using so I'm looking at the differences for that and seeing what else I need to change.

In doing this I am trying to understand a little how FNET works.

I am wondering about the file FNET_MCF_ISR_INST.c which sets the interrupt level and priority. It does this on this line

FNET_MCF_INTC0_ICR(irq_number) = (fnet_uint8)FNET_MCF_INTC0_ICRn_IL(priority) | FNET_MCF_INTC0_ICRn_IP(7);

The macros are defined as

#define FNET_MCF_INTC0_ICRn_IP(x)          (((x)&0x07)<<0)

#define FNET_MCF_INTC0_ICRn_IL(x)          (((x)&0x07)<<3)

I'm not sure if this is right for the 54418 ?

It only has an interrupt level setting and not a priority. The level is the lower 3 bits of FNET_MCF_INTC0_ICR(irq_number) so it looks to me this will always get set to 7 and the level, which is shifted into bits 3/4/5 gets ignored.

I was expecting the two macros above to be different for the 54418 but they're the same for all Coldfires.

The MCF53017 is the same for this register, the lower 3 bits are the level, the priority cannot be changed.

The macros are correct for the other coldfires, am I misunderstanding how this works ?

Thanks for any information.

Dec

0 Kudos

3,054 Views
butok
NXP Employee
NXP Employee

Hi Dec,

You are right. The MCF544x has different definitions for ICRn registers than other MCFs (supported by FNET).

It does not cause any problems for FNET, as it should work with any interrupt level.

In any case, this is defect and  the correct definition should be (for MCF5441x):

     #define FNET_MCF_INTC0_ICRn_IP(x)          (0)

     #define FNET_MCF_INTC0_ICRn_IL(x)          (((x)&0x07)<<0)

The fix will be available in the next version of FNET.

Thank you,

Andrey Butok

0 Kudos

3,054 Views
lucaognibene
Contributor II

Hello Andrey and rest of community!

I'm having a strange behaviour with FNET on my board with Kinetis K60DN256Z.

By debugging a basic firware, just sending few characters to a selected remote TCP port, either using CodeWarrior V10.3 and V10.5 I go to PE_DEBUGHALT _if_ I set Optimization Level 0 in compiler options; this as soon as I get connected to the remote TCP server.

If I change to Optimization Level 1 everything works fine.

Any clues?

Thanks for any response.

   Luca O.

0 Kudos

3,054 Views
butok
NXP Employee
NXP Employee

Hi Luca,

No ideas, it can be anything.

I can try to help if you will reproduce the behavior in standard (not modified) FNET example, and on FNET supported platform.

0 Kudos

3,054 Views
lucaognibene
Contributor II

Hello Andrey!

Well, from our investigations it seems to be related to the fact we are using Processor Expert, while you are initializing devices directly by setting proper registers.

Since we managed to run successfully the benchmark demo on our board with Kinetis K60DN256Z, it's not strongly related to the platform itself (we halved RAM and flash memory space).

With our firmware doing some basic tx/rx TCP connection, every now and then we fall into PE_DEBUGHALT with ivINT_Hard_Fault interrupt.

We modified the Vectors.c interrupt file (located into Generated_Code in our project) with this two lines by comparing with your file (to make the stack work):

(tIsrFunc)&fnet_cpu_isr, /* 0x57  0x0000015C   -   ivINT_PIT3            unused by PE */

(tIsrFunc)&fnet_cpu_isr, /* 0x5D  0x00000174   -   ivINT_ENET_Receive   unused by PE */

Another thing we noticed that your interrupt vector is 256 entries long, while ours, generated by PE, is 119 entries long.

Is there some other important setting/interrupt we need to take care of?

It seems the PE_DEBUGHALT is triggered by connection establishment (but not always).

We also initialized ethernet, flash memory and timer devices in PE with no big luck.

Maybe a call/something that goes into a memory area we can't address? (since we have 256kB flash and 64kB RAM, half respect to your platform).

Thanks a lot for any ideas/suggestions.

Kind regards,

   Luca O.

0 Kudos

3,054 Views
butok
NXP Employee
NXP Employee

Hi Luca,  I am not fan of PE and  do not use it.  You can try to ask for help from Freescale Technical Support.

0 Kudos

3,054 Views
lucaognibene
Contributor II

Hello!

Don't worry: I may understand why.

Sometimes helps, but also creates problems.

My colleague and I will try more and, maybe, will skip PE at all.

Thanks anyway!  :-)

0 Kudos

3,051 Views
butok
NXP Employee
NXP Employee

FNET TCP/IP Stack has got Golden "IPv6 Ready Logo"

logo_ready_phase-2.gif
Logo ID:02-C-001017
Note: Phase-2 (Golden), Core Protocols, Host.
https://www.ipv6ready.org/db/index.php/public/logo/02-C-001017

FNET is the first open-source, bare-metal TCP/IP stack that has got it!
Correct me, if I am wrong;)
Andrey Butok

3,051 Views
TomLEE
Contributor III

Hello Andrey,

Congratulations for all this hard work !!!

I have an issue in FNET stack 2.3.0 and I just found where there is the problem.

Since 1 month now we totally finished our software and our system (IRIG-B Generator synchronised by GPS, with ethernet communication on a PC) hang up (I am not sure of the good word in english) 1 or 2 time a day and the watchog don't reset the system.

I found that the level of interrupt of the watchdog was 1 and the one of PHY is 2 and DMA Timer3 is 3 (this 2 ints are used by FNET). So I changed watchodg level to 4 and now, our system reset when issue occur (this is better than reset by manual off/on !).

So I investigate in the fnet stack, I placed a breakpoint in my watchog interrupt function and waiting (I use CodeWarrior 7.2)...

This morning, I found that my program stay locked in fnet_fec_output() (in fnet_fec.c) in the first while loop ( while(ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_TX_BD_R)){}; ).

status = 0x8C000.

I give you all the function where the program was passed :

fnet_cpu_isr()

fnet_isr_handler()

fnet_fec_isr_rx_handler_bottom()

fnet_isr_unlock()

fnet_ip_input_low()

fnet_udp_input()

fnet_icmp_error()

fnet_icmp_output()

fnet_ip_output()

fnet_ip_netif_output()

fnet_eth_output_ip4()

fnet_fec_output()

it_watchdog()

I supposed that icmp_error don't occur in normal operation so perhaps, the problem comes from it...

Do you have an idea to eliminate this ?

To avoid reset, I will add timeout to exit this infinite loop.

I don't speek english fluently so I hope you will understood my explanations...

Thank you, best regards,

Thomas RETAIL.

LES ETUDES ELECTRONIQUES

33380 BIGANOS

FRANCE


0 Kudos

3,051 Views
TomE
Specialist II

> fnet_cpu_isr()

What function that that interrupt happen in the middle of? Is it possible that it interrupted another call to the FEC code, and that is the cause of the problem?

You have the whole system in front of you, at a good breakpoint, exactly in the middle of the problem. You're the only one who can work through this. The first thing to do is to dump all of the FEC registers and all of the ring contents. Find what state it is in and then try to work back to how it got into that state.

The ICMP Messages are a clue, as the Transmit code is being called from WITHIN the Receive code. That's a potential hazard right there (that FNET must have interlocks to protect against).

You should use the "ping" utility to send ICMP Echoes at it to see if that makes it happen more often. You could even get a "flood ping" going from a unix box, or use "ping -w" with a low timeout value.

Examine the ICMP Error message. You may need to generate/trip this specific error to trigger the problem.

> the level of interrupt of the watchdog was 1

We run our software watchdogs at Level 7, so nothing can stop it.

You should check the Timer interrupts in case they're happening in the middle of some FNET or FEC code that isn't expecting it. You could try setting the Timer interrupt lower than the FEC one and see if the problem goes away.

Tom

0 Kudos

3,051 Views
TomLEE
Contributor III

Hello Tom,

Thanks for your answer.

Effectively, I don't describe the functions BEFORE interrupt happen and (oh surprise !), it was fnet_fec_output().

This is my program:

Tx_ethernet() // my own function in order to prepare buffer to transmit datas to a PC on ethernet link with UDP protocol.

Then, FNET functions :

udp_tx()

send()

sendto()

fnet_udp_send()

fnet_udp_output()

fnet_ip_output()

fnet_ip_netif_output()

fnet_eth_output_ip4()

fnet_fec_output()

fnet_cpu_isr()     // this is the FEC interrupt

then see my message above.

Is it not dangerous to transmit ICMP error message during an interrupt and not in main loop ?

For watchdog level, you are completely right !!!!! How stupid I am...

I don't have time to investigate for now (I am on others projects with short delays) but I will try ping command later to find the cause and the solution.

For now, I have deleted the while loop... It seems to work (no reset within 24 hours)...

Best regards,

Thomas RETAIL.

0 Kudos

3,054 Views
TomE
Specialist II

> Effectively, I don't describe the functions BEFORE interrupt happen and (oh surprise !),

> it was fnet_fec_output().

> This is my program:

> For now, I have deleted the while loop.

Don't do that. It is essential. You'll cause worse problems, possibly data corruptions. Wait until it is fixed properly.

Your program has nothing to do with the problem. This looks like a bug in the FEC driver where critical data structures aren't being protected against interrupts.

It would be easier to debug if you copied the entire stack dump including the line numbers. The critical part is what LINE in fnet_fec_output was it executing when the interrupt happened.

The more often your code is making FNET send Ethernet messages, the more likely a FEC interrupt will arrive with an ICMP packet at exactly the right time (exactly the wrong time) to show this bug.

You're using FNET 2.3.0 release in Feb 2013. The current version is 2.6.0. This may have been fixed, but there's nothing in the change log indicating this:

Embedded TCP/IP stack: FNET Change Log

The relevant code in FNET 1.1.0

void fnet_eth_output_low(fnet_netif_t *netif, unsigned short type, const fnet_mac_addr_t dest_addr, fnet_netbuf_t* nb)

{

    fnet_fec_if_t *ethif = (fnet_fec_if_t *)netif->if_ptr;

    fnet_eth_header_t * ethheader;

    if((nb!=0)&&(nb->flags & FNET_NETBUF_FLAG_FIRST)&&(nb->total_length<=netif->mtu))

    {

        while(ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_TX_BD_R))

        {};

The same code in FNET 2.6.0:

void fnet_fec_output(fnet_netif_t *netif, unsigned short type, const fnet_mac_addr_t dest_addr, fnet_netbuf_t* nb)

{

    fnet_fec_if_t *ethif = ((fnet_eth_if_t *)(netif->if_ptr))->if_cpu_ptr;

    fnet_eth_header_t * ethheader;

    if((nb!=0) && (nb->total_length<=netif->mtu))

    {

        while(ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_TX_BD_R))

        {};

It doesn't look like that has changed much between 1.1.0 and 2.6.0.

The problem is most likely that "ethif->tx_buf_desc_cur" has changed somewhere, possibly HERE (why won't this forum let me copy/paste without messing it up completely???):

/* Update pointer to next entry. */

if (ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_RX_BD_W))

    ethif->tx_buf_desc_cur = ethif->tx_buf_desc

else

    ethif->tx_buf_desc_cur++;

while(ethif->reg->TDAR) /* Workaround.*/

    {};

ethif->reg->TDAR=1; /* Indicate that there has been a transmit buffer produced.*/

My guess is the interrupt happened between the "ethif->tx_buf_desc_cur++" and the "ethif->reg->TDAR=1". That would increment the pointer, but the FEC wouldn't then advance to that next buffer.

I think that code needs "fnet_isr_lock(); ... fnet_isr_unlock();" around the above section. That's something for Andrey to look at.

I've just looked at how "fnet_isr_lock()" works. Weird. It makes interrupts PENDING, and then has them run later. I'd be interested to know why this code doesn't simply disable the CPU interrupts around critical sections.

Tom

0 Kudos

3,054 Views
butok
NXP Employee
NXP Employee

Do not  worry  Guys,

All FNET  critical  sections are covered by FNET SW locking mechanism fnet_isr_lock()/fnet_isr_unlock().

Also FNET ISR handlers are split to "bottom" and "top" half.

So the situation discibed by Tom is not posible.

Thanks,

Andrey

0 Kudos

3,054 Views
TomE
Specialist II

Andrey, I have sent you a message about this.

Thomas, I've sent email to your work contact email address. Send me a message if you didn't get it, email me if you did.

Tom

0 Kudos

3,054 Views
TomLEE
Contributor III

Hello Tom and Andrey,

On the advice of Tom, I modified fnet_fec_output() in order to making the problem happen more often (namely the function lock up in first while loop).
Here is the code :

void fnet_fec_output(fnet_netif_t *netif, unsigned short type, const fnet_mac_addr_t dest_addr, fnet_netbuf_t* nb)
{
    fnet_fec_if_t *ethif = ((fnet_eth_if_t *)(netif->if_ptr))->if_cpu_ptr;
    fnet_eth_header_t * ethheader;
   volatile unsigned i;
  
    if((nb!=0) && (nb->total_length<=netif->mtu))
    {
        while(ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_TX_BD_R))
        {};
        ethheader = (fnet_eth_header_t *)fnet_ntohl((unsigned long)ethif->tx_buf_desc_cur->buf_ptr);
        fnet_netbuf_to_buf(nb, 0, FNET_NETBUF_COPYALL, (void *)((unsigned long)ethheader + FNET_ETH_HDR_SIZE)); 

        fnet_memcpy (ethheader->destination_addr, dest_addr, sizeof(fnet_mac_addr_t));
        fnet_fec_get_mac_addr(ethif, &ethheader->source_addr);
        ethheader->type=fnet_htons(type);
        
        ethif->tx_buf_desc_cur->length = fnet_htons((unsigned short)(FNET_ETH_HDR_SIZE + nb->total_length));
        ethif->tx_buf_desc_cur->status |= FNET_HTONS(FNET_FEC_TX_BD_R); /* Set Frame ready for transmit.*/
     
        // FOR TEST ONLY /////////////////////////
        if (fnet_fec_output_reentry_count)
         fnet_fec_output_reentry_count = 0;  // Place breakpoint here
        fnet_fec_output_reentry_count = 1;
        //////////////////////////////////////////
       
        /* Update pointer to next entry.*/
        if (ethif->tx_buf_desc_cur->status & FNET_HTONS(FNET_FEC_RX_BD_W))
            ethif->tx_buf_desc_cur = ethif->tx_buf_desc;
        else
            ethif->tx_buf_desc_cur++;
        while(ethif->reg->TDAR) /* Workaround.*/
        {};
   
    // FOR TEST ONLY /////////////////////////
    for (i=0; i<10000; i++){}        // tempo 20µs
    //////////////////////////////////////////
   
        ethif->reg->TDAR=FNET_FEC_TDAR_X_DES_ACTIVE; /* Indicate that there has been a transmit buffer produced.*/

#if !FNET_CFG_CPU_ETH_MIB      
        ((fnet_eth_if_t *)(netif->if_ptr))->statistics.tx_packet++;
#endif     
    }
   
  fnet_fec_output_reentry_count = 0;
  
    fnet_netbuf_free_chain(nb);  
}

So, with the temporisation added, there is a lot of ICMP error (I used Wireshark to see details and ICMP error frame occurs 2 once) and few minutes later, the function locked up in while loop.

Adding the fnet_fec_output_reentry_count variable, it can detect re-entry in this function.

I tried to add fnet_isr_lock()/fnet_isr_unlock() but no change...

Thabk you,

Thomas.

0 Kudos