Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12745 Discussions

Altera TSE driver and example program for lwIP (1.3.2)

Altera_Forum
Honored Contributor II
40,027 Views

After many many requests and complaints about lack of support and/or documentation for support of lwIP for the Altera TSE, I have developed a drop-in TSE driver and example program and made this available to the NIOS II community. This was done for NIOS II 8.1 SP0.01. I don't expect difficulty with version 9.x. 

 

This is for the latest version of lwIP (the latest is as of this post) for a minimal program and HTTP server based on the http server in the lwIP contrib folder. The lwIP TSE driver uses the altera_avalon_tse driver and SGDMA as-is. There is a complete (as in 41-step) set of instructions on creating the project and example program. More information and the link to the driver is available here: 

 

http://lwip.wikia.com/wiki/available_device_drivers#lwip_1.3.2 

 

Please direct any questions, changes for NIOS II 9.1, or comments to this thread. 

 

12-16-2010 update: This example works with NIOS Version 10.0 with some tweaks to the procedure to create the project. Also, a lwIP 1.4 release candidate has been out for a while and it drops into this example (in place of 1.3) without changes. 

 

Bill
0 Kudos
257 Replies
Altera_Forum
Honored Contributor II
1,862 Views

Basically yes. 

 

What about memcpy optimizations? Maybe worth adding a dma?
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

That might be a good idea :) 

 

Currently trying to debug the large chunk issue but there is still a big problem though... let's first focus on that. :p
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Great, I think this project could be maintained by more people than only You. Github maybe?

0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Yeah, that was the idea :) I wanted to make the installer automatically download the latest version of LwIP and FreeRTOS but that wouldn't be possible on windows systems since they don't have curl and wget by default. Maybe I can implement this for the dev tree on github though... I'll be back Tuesday... 

 

Further more, I think I found the possible cause of the bug, was just about to mail the mailing list for any advice. Hopefully I'm on to something ;)
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

One part of the bug solved, the input task first used the raw input method now input is inserted into the tcp stack via tcpip_input. Now I can send 14KB with one write... when I try to send more in one go the write function doesn't return, hope to fix it today!

0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Fixed it! The bug occurred because (MEM_SIZE < TCP_SND_BUF), this makes a write function block forever if the write (length > MEM_SIZE) I'll fill a bug report when nongnu.org is up again. New release will be released today! Now off to re check the entire config, make it more logical and do some final testing, later today / this evening I'll create a GitHub repository with all the sources and a TODO / Wishlist :lol:

0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Created a git repository with the latest sources has been created. https://github.com/engineeringspirit/freelwip-nios-ii this version works stable but is far from optimized.

0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

 

--- Quote Start ---  

Created a git repository with the latest sources has been created. https://github.com/engineeringspirit/freelwip-nios-ii this version works stable but is far from optimized. 

--- Quote End ---  

 

 

Thank you for the link. I have played a bit with your package - very convenient and easy to use. The example works, but it constantly prints "Error: BlockQ.". What may be the reason? Web- and echo-servers work fine. 

 

AUTOIP doesn't work - lwip_main.c misses# include <lwip/autoip.h>. Also, if you expose LWIP_AUTOIP to BSP Editor, than, probably, LWIP_DHCP_AUTOIP_COOP and LWIP_DHCP_AUTOIP_COOP_TRIES should also be here. 

 

Regards, 

Igor
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

 

--- Quote Start ---  

Hmm disabling the timer task was a bad idea, it makes the stack run quite unstable... enabled it again. 

--- Quote End ---  

 

DipSwitch, How to reproduce this instability? I run with# define MY_TIMER=0 and everything seems to be fine. It looks like in your implementation lwip timers are called both from native tcpip_thread and from your timer task. Is this intended behavior?
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Sorry, I am a bit busy with all kinds of stuff. 

 

First thanks for trying the release. That 'error' comes from an FreeRTOS demo task and I have no idea what it means... Didn't really have time yet to find out where it came from. 

 

AUTOIP wasn't tested yet so it would be possible it doesn't work. Maybe it will be fixed in a next release. Never worked with AUTOIP before so need to do some research work first. :) 

 

The timer issue was fixed. I know both tasks are calling the LwIP timers, but the response time seams faster that way... maybe there is something else missing which leads to this? 

 

Regards, 

Nick
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

A small issue on-topic: 

 

I am trying to get MAC address from a known IP address device. LwIP allows to query the device for its address and then search the ARP table for particular address: 

 

arp_query = etharp_query(&alteraTseNetif, &alteraTseNetif.gw, NULL); 

arp_find = etharp_find_addr(&alteraTseNetif, &alteraTseNetif.gw, &ret_eth_addr, &ret_ip_addr); 

 

As You can see, I am trying to get the MAC address of my gateway. The first command sends gratuitous ARP, then ARP request and finaly, the stack receives ARP reply (returns ERR_OK, which means no errors) - everything is OK here. 

 

Then I issue a search using etharp_find_addr(), which returns me -1. Let's check what's inside: 

 

s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr **eth_ret, ip_addr_t **ip_ret) { 

 

s8_t i; 

 

LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", eth_ret != NULL && ip_ret != NULL); 

LWIP_UNUSED_ARG(netif); 

 

i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); 

 

if((i >= 0) && arp_table.state == etharp_state_stable) { 

*eth_ret = &arp_table.ethaddr; 

*ip_ret = &arp_table[i].ipaddr; 

return i; 

return -1; 

 

I see that I receive table index i=0, which is fine, but the table state is not ETHARP_STATE_STABLE. I've checked that no matter what I try, I always get ETHARP_STATE_PENDING, which returns me MAC 00:00:00:00:00:00. 

 

How can I find the MAC address of the requested IP? I believe I am on the right way, but I don't know how to move state from pending to stable. Any ideas? 

 

Thanks.
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

You must force an MAC resolve first, this can be accomplished by sending an UDP or ICMP packet to the address you are trying to resolve. How we are doing this is by sending ping packets to the host we want to resolve. 

 

Here is the peace of code we use to resolve the mac address of the destination: 

while (mac->mac == 0 && --nRetries) { // avoid context switching which could result in ARP entry cleanup and cause invalid data while memcoping portENTER_CRITICAL(); // if result is positive we found a match if (etharp_find_addr(netif_default, &ip_req, &eth_mac, &ip_ret) >= 0) memcpy(mac->bytes, eth_mac->addr, MAC_ADDRESS_SIZE); // enable interrupts back on portEXIT_CRITICAL(); // only sleep if we don't have a MAC yet if (mac->mac == 0) { lwip_ping_target_data(ipaddr, 1, 1, (u8_t*)"hello", (sizeof("hello") - 1)); Sleep(100); } }
0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Hmm, seems like lwip_ping_target_data() is a custom procedure?

0 Kudos
Altera_Forum
Honored Contributor II
1,862 Views

Yeah it's in the LwIP/FreeRTOS port I wrote, but it uses the socket interface so it will only work if you use that. What it basically does, is sending an ICMP ping packet to the target. What you could do is write a function which sends an UDP packet to the requested target and then start processing the input for a while. When 10ms (in case of slow networks) or so has passed the target's mac is probably in your ARP table ready to be found :)

0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

Hmm, so ping or other packet sending is the only option? Basically, it's quite strange, since LwIP already sends gratuitous arp, then arp request and finally gets arp reply. Table is filled with data, but state is pending. I just don't understand when the entry is set to be pending and when it's stable?

0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

Pending indicates that an ARP query has been send, but no response has been received yet.  

 

By the look of it, it's also possible to force an ARP request via 'etharp_query', however you need to make sure you call 'ethernetif_input(&alteraTseNetif)' after if you are running without OS. Since the ARP replies are only updated if you process the newly received packages after 'etharp_query' has been called. 

 

You should also take into account that there is a slight delay between the send / receive so if you place both calls without delay between them the response probably hasn't been received yet. 

 

Another thing to take in account is that you can't call 'etharp_query' directly when you are using an OS since this function uses the raw API without thread safety support. This means your ARP and PBUF table isn't protected against cross thread actions.
0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

Oh, that was the issue - I haven't done ethernetif_input(&alteraTseNetif) call. Thanks!

0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

Btw, is it possible to redefine LWIP_DEBUGF() to use printf() somehow? That native debug use some interesting variables types.

0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

In cc.h you should 

 

# define LWIP_DEBUG # define LWIP_PLATFORM_DIAG(x) printf(x)  

 

and in lwipopts.h you should scroll down (approx line: 1290) there you can find all debug defines so you can enable / disable different functionality's. This is done because if you would enable all at once it would cost quite much processor time :p
0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

 

--- Quote Start ---  

In cc.h you should 

# define LWIP_DEBUG# define LWIP_PLATFORM_DIAG(x) printf(x)  

--- Quote End ---  

 

 

printf should be without parenthesis, something like  

#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)
0 Kudos
Altera_Forum
Honored Contributor II
1,854 Views

DipSwitch,  

I think there is a problem in your (and Bill’s) driver. low_level_input() in altera_tse_ethernetif.c allocates pbufs for incoming packets with pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL). By default PBUF_POOL_BUFSIZE evaluates to 1080 and, consequently, longer packets corrupt memory. In my code I simply redefine PBUF_POOL_BUFSIZE to be 2000, but for universal driver, like yours, some more elegant way should be found.
0 Kudos
Reply