Forum Discussion
Altera_Forum
Honored Contributor
16 years agoAltera TSE driver and example program for lwIP (1.3.2)
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. Bill257 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- Basically yes. What about memcpy optimizations? Maybe worth adding a dma? --- Quote End --- DMA doesn't work reliably with the TSE. I would rarely get a bad byte in the copied data. Even so in my timing tests the timing improvement wasn't significant compared to memcpy - or I should say my memcpy which is highly optimized assembly code. Bill - Altera_Forum
Honored Contributor
--- Quote Start --- Hmm, lets see:
TCP_MSS = 1460 PBUF_LINK_HLEN = 14 ETH_PAD_SIZE = 2 To sum up: 1460+40+14+2 = 1516 Seems like no problems here? --- Quote End --- The defaults are correct. If TCP_MSS is changed I could see it being a problem. I wouldn't think NIOS II systems are so memory constrained to not allow a large MSS. Although we were mulling here over making an lwIP-based program entirely in onchip memory. So I could see that being a case. Bill# ifndef PBUF_POOL_BUFSIZE# define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN+ETH_PAD_SIZE)# endif - Altera_Forum
Honored Contributor
--- Quote Start --- The defaults are correct. If TCP_MSS is changed I could see it being a problem. I wouldn't think NIOS II systems are so memory constrained to not allow a large MSS. Although we were mulling here over making an lwIP-based program entirely in onchip memory. So I could see that being a case. Bill --- Quote End --- Bill, I agree that your defaults are consistent, but it is not obvious for the user that changing TCP_MSS also affects maximum allowable Ethernet frame size. More dangerous and hard-to-debug flaw is rx buffer overflow which may occur for small MAC core if PBUF_POOL_BUFSIZE < 1520. I see that setting TSEMAC_FRM_LENGTH to (PBUF_POOL_BUFSIZE+ETH_PAD_SIZE) in tse_mac_init() supposed to do the job, but this doesn’t work because “This maximum frame length is fixed to 1518 in 10/100 and 1000 Small MAC core variations.” So, it would be good for the driver to either ensure PBUF_POOL_BUFSIZE > 1520 in compile time, or to check that PBUF_POOL_BUFSIZE > TSEMAC_FRM_LENGTH in runtime and fail hard if this confition is not meat. Igor - Altera_Forum
Honored Contributor
--- 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 --- I think it would be really helpful and would promote much more use of your additions if this was put on the lwIP Wiki: http://lwip.wikia.com/wiki/available_device_drivers I will check what you did for sure - I hope FreeRTOS use is optional in your installation. There are several ways to use lwIP without an RTOS and it's well documented that a significant performance hit occurs using an RTOS. Integrating a significant number of lwipopts.h settings into the Eclipse install would also help new users as well. I wonder if a lwIP template application was possible in the "New" menu? By the way, I use lwIP as a library - I don't know if you allowed for that. In fact I have the TSE driver as a LIB also but unfortunately it needs to be tied to a BSP. This makes it hard to use the TSE/lwIP combo in multiple projects that have (and normally would) different BSPs without duplicating the 2 LIBs. It's great to see your additions here. You really did more than I did and I'm thankful someone took it as a catalyst and ran with it like I wish I could have. lwIP 1.4.1 is due out shortly and 1.5 isn't far off with stable IPV6. Bill - Altera_Forum
Honored Contributor
Igor,
--- Quote Start --- I agree that your defaults are consistent, but it is not obvious for the user that changing TCP_MSS also affects maximum allowable Ethernet frame size. --- Quote End --- There is unfortunately a good bit of lwIP and lwipopts that is not obvious. --- Quote Start --- More dangerous and hard-to-debug flaw is rx buffer overflow which may occur for small MAC core if PBUF_POOL_BUFSIZE < 1520. I see that setting TSEMAC_FRM_LENGTH to (PBUF_POOL_BUFSIZE+ETH_PAD_SIZE) in tse_mac_init() supposed to do the job, but this doesn’t work because “This maximum frame length is fixed to 1518 in 10/100 and 1000 Small MAC core variations.” So, it would be good for the driver to either ensure PBUF_POOL_BUFSIZE > 1520 in compile time, or to check that PBUF_POOL_BUFSIZE > TSEMAC_FRM_LENGTH in runtime and fail hard if this confition is not meat. --- Quote End --- Then I agree it's too easy to break things with MSS changes and it shouldn't be left as-is. alteraTseEthernetif.c should include a# define with the right (calculated) size to be used in the pbug_allocs. I typically code that way when I know there are constraints. Bill - Altera_Forum
Honored Contributor
It looks like the driver incorrectly handles chains of short pbufs. The following code produces invalid TCP packets:
With printf("<%d>", len); in tse_mac_raw_send() I see that the driver forwards to the sgdma the following pbuf sequence: <56><1> <56><1><1><1><1> According to Altera docs sgdma don’t like short transfers, and I think all these extra pad bytes are injected by sgdma. If this is the case, then the driver should provide some workaround, maybe by combining small chunks (if any) into single continuous sgdma request. Also, has anyone tried to use “On-Chip FIFO Memory Core” in place of sgdma for ethernet? I have never observed this behavior with copying tcp_write. But, does lwIP guarantee not to emit short pbufs for copying tcp flow? Igorusleep(1000000); netconn_write(com->conn, "a", 1, NETCONN_NOCOPY); netconn_write(com->conn, "b", 1, NETCONN_NOCOPY); netconn_write(com->conn, "c", 1, NETCONN_NOCOPY); netconn_write(com->conn, "d", 1, NETCONN_NOCOPY); netconn_write(com->conn, "e", 1, NETCONN_NOCOPY); usleep(1000000); 09:41:10.544021 IP 169.254.177.104.23 > IM-W7.1166: P 154:155(1) ack 30 win 5811 0x0000: 4500 0029 001d 0000 4006 95a2 a9fe b168 E..)[email protected] 0x0010: a9fe dfaa 0017 048e 0000 1a08 33eb a83c ............3..< 0x0020: 5018 16b3 5833 0000 6100 0000 0000 P...X3..a..... 09:41:10.745999 IP IM-W7.1166 > 169.254.177.104.23: . ack 155 win 64086 0x0000: 4500 0028 014d 4000 8006 0000 a9fe dfaa E..(.M@......... 0x0010: a9fe b168 048e 0017 33eb a83c 0000 1a09 ...h....3..<.... 0x0020: 5010 fa56 e52a 0000 P..V.*.. 09:41:10.746866 IP 169.254.177.104.23 > IM-W7.1166: P 155:159(4) ack 30 win 5811 0x0000: 4500 002c 001f 0000 4006 959d a9fe b168 E..,[email protected] 0x0010: a9fe dfaa 0017 048e 0000 1a09 33eb a83c ............3..< 0x0020: 5018 16b3 f266 0000 6200 0000 6300 0000 P....f..b...c... 0x0030: 6400 0000 65 d...e (this last packet is never ACKed by the host and connection freezes) - Altera_Forum
Honored Contributor
What happens if your writes are:
The problem might be with misaligned transfers.netconn_write(com->conn, "abcd", 1, NETCONN_NOCOPY); netconn_write(com->conn, "efgh"i+1, 1, NETCONN_NOCOPY); netconn_write(com->conn, "ijkl"+2, 1, NETCONN_NOCOPY); netconn_write(com->conn, "mnop+3", 1, NETCONN_NOCOPY); netconn_write(com->conn, "qrst", 1, NETCONN_NOCOPY); - Altera_Forum
Honored Contributor
--- Quote Start --- What happens if your writes are:
The problem might be with misaligned transfers. --- Quote End --- Dsl, happens essentially the same – the same garbage on the boundaries of short writes. Bill’s driver handles misaligned writes by copying into temporary buffer on stack. I’ve attached complete session dump (for these tests I use shell.c from lwip contrib and just modify com_help()).netconn_write(com->conn, "abcd", 1, NETCONN_NOCOPY); netconn_write(com->conn, "efgh"i+1, 1, NETCONN_NOCOPY); netconn_write(com->conn, "ijkl"+2, 1, NETCONN_NOCOPY); netconn_write(com->conn, "mnop+3", 1, NETCONN_NOCOPY); netconn_write(com->conn, "qrst", 1, NETCONN_NOCOPY); - Altera_Forum
Honored Contributor
Igor & Dsl,
I'm starting to think that something else is going on here. I don't see problems here and now have lwIP in 4 Cyclone/NIOS-II products. I even implemented telnet as a debug console and have no problem with the 1-byte payloads that occurs when you type in Telnet. However, none of my chains are 1 byte because lwIP has made them bigger adding TCP/IP headers. Maybe you have an lwip option set which causes this? Also, I use PBUF_POOL_SIZE of 1518 so that I get as few chains as possible. I have 256MB of memory and have no concern over memory usage. Igor, what do you mean by: --- Quote Start --- Also, has anyone tried to use “On-Chip FIFO Memory Core” in place of sgdma for ethernet? --- Quote End --- Bill - Altera_Forum
Honored Contributor
Ok - so that won't show if the inserted 'pad' bytes come from specific data bytes.
What I'd noticed is that the last frame ends with the correct byte (0x65) - so the problem isn't an obvious one where all 4 bytes are always written. The IP header frame length (0x00 0x2c) is correct for the expected frame data - but not for that actually added. An alternate hypothesis is that the MAC unit only looks at the byte enables in the fifo word at the end of frame. Whereas your data will have multiple unasserted byte enables embedded within the frame. If so, the software would have to be willing to build an entire frame.