- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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. BillLink Copied
257 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Stephan,
This is interesting. I see how you're right, but I also think there is a change that does not increase latency. The reason it was kept so short is that our system requires as close to 0 latency as possible. I think the root problem is the location of this line:
// decrement packet counter
--tse_info->mRxCount;
I believe the following also solves the problem since the packet count (which tells us if there is a free space) is decremented last:
// start the critical section by disabling IRQs
const alt_irq_context cpu_sr;
// assign current packet from lwIP packet buffer as the new data
*data = tse_info->mRxBuffer;
// assign next packet instead and move forward in buffer
tse_info->mRxBuffer = (void*)next_packet;
if (++tse_info->mRxIndex >= TSE_RX_BUFFER)
{
tse_info->mRxIndex = UINT32_L(0);
}
cpu_sr = alt_irq_disable_all();
// decrement packet counter
--tse_info->mRxCount;
// stop the critical section by enabling IRQs
alt_irq_enable_all(cpu_sr);
This also could make the second change uneccessary since the count doesn't show a free slot until the pbuf pointer has replaced the previous one. Good catch. We, as well might be the case with most users, don't load the system until the buffers are full. We have enough memory that this array is quite large. Bill
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi BillA (and others !),
Really big thanks for your lwip port on altera. I have succefully implemented the webserver template with lwip on a bemicro SDK from arrow. I have a question because i don't know how to do it : actually i have my sgdma Tx and sgdma Rx mapped on a DDR , the same DDR where the CPU data an instruction is mapped. Now imagine i want to use an onchip ram for sgdma tx and sgdmarx instead of DDR. (but CPU still mapped to DDR) I tried direclty but this is not working. if you have any idea . thanks- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- actually i have my sgdma Tx and sgdma Rx mapped on a DDR , the same DDR where the CPU data an instruction is mapped. --- Quote End --- I'm almost positive that this can't work. Every example I've seen has SGDMA writing to onchip memory. --- Quote Start --- Now imagine i want to use an onchip ram for sgdma tx and sgdmarx instead of DDR. (but CPU still mapped to DDR) --- Quote End --- I would agree with this too. :-) --- Quote Start --- I tried direclty but this is not working. if you have any idea . --- Quote End --- Maybe it's not working for a non-SGDMA or memory reason. Compare to an example (e.g. the Altera NEEK development kit Ethernet code) and see if you're in the ballpark setting-wise. Bill A.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks BillA,
My problem was solved by using an equivalent SOPC as in Altera NEEK development kit Ethernet code. thanks for the idea . Laurent- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Just want to say that the example compiles under 12.1 with no effort. Then a question, i am getting a code size of 180KB. I have not started tuning the code yet, but do any of you thinks it's possible to get down to 30-40Kb for a simple telnet server? I need a small footprint to get it into internal mem. Would make our life much easier. Apus- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Then a question, i am getting a code size of 180KB. I have not started tuning the code yet, but do any of you thinks it's possible to get down to 30-40Kb for a simple telnet server? I need a small footprint to get it into internal mem. Would make our life much easier. --- Quote End --- My guess as a long-time user of lwIP (going back 10 years now) is that 30-40k will not likely be possible. TCP takes up a good bit of code. I could see 60k possibly. If you find out the smallest you can make it, please post back so others will know what is the smallest possible footprint. Bill A.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have read through several threads on the subject but haven't been able to find the answer I am looking for. I would like to use lwIP with Altera TSE with no OS to receive TCP. I need to support about 10MB/s (80 Mb/s) shared between multiple TCP connections. There is very little other processing on the NIOS II/f. From reading it seems that if I do the following: 1) Run out of on chip memory. 2) Increase Processor clock speed as much as possible (Using Stratix IV) 3) Add TCP checksum offloading 4) possibly some other optimizations like endian conversion then i should be able to reach that speed but I was wondering if anyone could give me a more firm answer of if this is feasible or not. Thanks, Arthur- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi, I have read through several threads on the subject but haven't been able to find the answer I am looking for. I would like to use lwIP with Altera TSE with no OS to receive TCP. I need to support about 10MB/s (80 Mb/s) shared between multiple TCP connections. There is very little other processing on the NIOS II/f. From reading it seems that if I do the following: 1) Run out of on chip memory. --- Quote End --- I would run just select parts - inet_chksum, some of ethernetif, and maybe the oft-used pbuf functions. For a start, move nothing and see how it goes. It's so easy to move functions to on-chip memory there's no urgency to do that up front. And use code and data cache. 4k each if you can. --- Quote Start --- 2) Increase Processor clock speed as much as possible (Using Stratix IV) 3) Add TCP checksum offloading --- Quote End --- This is the biggest thing you can do. If not in hardware, using assembly for the checksum is still good. And an optimized memcpy too! The built-in memcpy is OK but can be better. Oh, and the macro SMEMCPY replace with an inline copy - it's always a small copy with a constant size. --- Quote Start --- 4) possibly some other optimizations like endian conversion --- Quote End --- For Cyclone-III the endian opcodes are included for htonl/ntohl. There was none for hton/ntoh - we did our own but I don't know if it's really used enough to matter. --- Quote Start --- then i should be able to reach that speed but I was wondering if anyone could give me a more firm answer of if this is feasible or not. --- Quote End --- Yes, it's feasible. Close but I see not much reason for it not to work. Bill A
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks! Thats a big help and exactly what I was looking for.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello fellow adventurers,
I am currently trying to port the FreeRTOS+lwIP environment onto the Stratix-V fpga eval board under the Quartus-II 13.0sp1 toolset. I've already ran into a number of issues, but so far managed to plow through most (tool name changes, some FreeRTOS/lwIP syntax changes after upgrading to latest, etc..). I was wondering if anyone else has tried running FreeRTOS+lwIP on Stratix V eval board, and if so, how successful were you? I am happy to provide feedback/share my findings (assuming we don't scrap this approach and go with Micrium+NicheStack... not my preferred choice). Thanks for your help! sjp- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following optimization can be applied to lwip_tse_mac.c:
In function tse_sgdmaRx_isr: Replace the init_tset_descriptor function call (spans 6 or 7 lines) just after label _dump: with the following: IOWR_32DIRECT(&tse_ptr->desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST].write_addr, 0, (u32_t) ethernetif->lwip_rx_pbuf[ethernetif->lwipRxIndexIsr]->payload); IOWR_8DIRECT(&tse_ptr->desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST].control, 0, ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK); I don't claim credit for this - I see they did this in the NIOS 12.1 TSE driver and it makes a lot of sense. Bill A- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- You can use the one that the dev kit will use when running e.g. the Interniche examples. If it doesn't come with a MAC address, you will have to use a temporary one but be sure to stay behind a router or directly connected to a PC. I use a real test MAC address from our block of addresses that I know is not in use locally. Bill --- Quote End --- ims,can you send your project to me ?I have the same problem with you.my email is 763475917@qq.com,thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear billa:
My board can ping it,But I meet another qusetion,I want to use the udp protocol to send and receive message!Unfortunately I can't send.I want to use the board acts as client and send the message to computer.maybe my code lose someting important,could you help me check it? waiting for your reply,thank you very much! here is my code: /* * Simple lwIP 1.3.1 example program. * * Expects no Operating System (NO_SYS=1) * * lwIP initialization and optional DHCP and WEB server support can be * enabled by setting# defines described below. * * You must plug in your board's MAC address below before compiling! * * Contributed by: Bill Auerbach lwip@softools.com */ # include <stdio.h> # include <unistd.h> # include "system.h" # include "sys/alt_timestamp.h" # include "sys/alt_alarm.h" # include "lwip/init.h" # include "lwip/netif.h" # include "lwip/dhcp.h" # include "lwip/tcp.h" # include "lwip/udp.h" # include "lwip/stats.h" # include "lwip/ip_frag.h" # include "lwip/ip_addr.h" # include "netif/etharp.h" # include "string.h" # include "INC/alteraTseEthernetif.h" # include "alt_types.h" # include "sys/alt_irq.h" # define mSdelay(x) usleep(x*1000) //#define USE_DHCP 1 //#define LWIP_UDP 1 # define STATIC_IP IP4_ADDR(&lwipStaticIp,219,245,66,185) # define STATIC_NM IP4_ADDR(&lwipnetmask,255,255,255,0) # define STATIC_GW IP4_ADDR(&lwipgw,219,245,66,254) # define STATIC_DA IP4_ADDR(&destAddr,219,245,66,112) struct ip_addr lwipStaticIp; struct ip_addr lwipnetmask; struct ip_addr lwipgw; struct ip_addr destAddr; // Define BUILD_HTTPD to 1 to build the httpserver_raw contrib example # define BUILD_HTTPD 1 // Alarm & timer variables - provides a 250mS counter void lwipProcessTimers(void); void Init_UDP(); static alt_alarm lwipAlarm; static alt_u32 lwipProcessTimerFlag; static alt_u32 lwipTicksPer250mS; static alt_u32 lwip250mStimer; // Alarm callback function. alt_u32 lwipAlarmCallback(void* context) { lwipProcessTimerFlag = 1; // Set flag to process timers return lwipTicksPer250mS; } // UDP callback function. void UDP_Receive(void *arg, struct udp_pcb *upcb, struct pbuf *p,struct ip_addr *addr, u16_t port) { struct ip_addr dAddr = *addr; if(p != NULL) { udp_sendto(upcb,p,&dAddr,port); pbuf_free(p); } } // Define netif for lwIP struct netif alteraTseNetif; struct udp_pcb *UdpPcbR; int main() { char udpdata[] = "UDP has Initialed successfully, begin to transfer!\r\n"; static struct ip_addr ip_zero = { 0 }; struct pbuf *psend; struct udp_pcb *UdpPcbS; void httpd_init(void); mSdelay(1000); // test_jtag_uart(); printf("Running...\n"); lwip250mStimer = 0; lwipProcessTimerFlag = 0; lwipTicksPer250mS = alt_ticks_per_second() / 4; if (alt_alarm_start (&lwipAlarm, lwipTicksPer250mS, lwipAlarmCallback, NULL) < 0) { printf ("System clock is required!\n"); for(;; } // Load platform specific MAC address into netif alteraTseNetif.hwaddr[0] = 0x00; alteraTseNetif.hwaddr[1] = 0x1C; alteraTseNetif.hwaddr[2] = 0x23; alteraTseNetif.hwaddr[3] = 0x17; alteraTseNetif.hwaddr[4] = 0x4A; alteraTseNetif.hwaddr[5] = 0xCB; // Initialize lwIP, Altera TSE and the ethernetif lwip_init(); if(netif_add(&alteraTseNetif, &ip_zero, &ip_zero, &ip_zero, alteraTseNetif.state, ethernetif_init, ethernet_input) == NULL) { printf( "Fatal error initializing...\n" ); goto fatal; } netif_set_default(&alteraTseNetif); // Initialize Altera TSE in a loop if waiting for a link printf("Waiting for link..."); while(((struct ethernetif *) alteraTseNetif.state)->link_alive!=1) { mSdelay(1000); putchar('.'); tse_mac_init(0, alteraTseNetif.state); } printf("OK\n"); STATIC_IP; STATIC_NM; STATIC_GW; netif_set_addr(&alteraTseNetif, &lwipStaticIp, &lwipnetmask, &lwipgw); //netif_add(&alteraTseNetif, &lwipStaticIp, &lwipnetmask, &lwipgw, NULL, ethernetif_init, ethernet_input); //netif_set_default(&alteraTseNetif); netif_set_up(&alteraTseNetif); printf("IP address: %s\n", ip_ntoa(&alteraTseNetif.ip_addr)); printf("IP netmask: %s\n", ip_ntoa(&alteraTseNetif.netmask)); printf("IP gateway: %s\n", ip_ntoa(&alteraTseNetif.gw)); # if BUILD_HTTPD httpd_init(); # endif Init_UDP(); STATIC_DA; printf("UDP Dest IP address: %s\n", ip_ntoa(&destAddr)); //psend = pbuf_alloc(PBUF_RAW, sizeof(udpdata), PBUF_POOL); psend = pbuf_alloc(PBUF_RAW, sizeof(udpdata), PBUF_RAM); psend->payload = (void *)udpdata; if (!psend) { printf("Can't allocate buffer.\n"); goto fatal; } UdpPcbS = udp_new(); if (!UdpPcbS) { printf("udp_new() failed.\n"); goto fatal; } udp_bind(UdpPcbS, &lwipStaticIp, 67); if (udp_bind(UdpPcbS, &lwipStaticIp, 67) != ERR_OK) { printf("udp_bind() failed.\n"); goto fatal; } udp_connect(UdpPcbS, &destAddr, 67); if (udp_connect(UdpPcbS, &destAddr, 67) != ERR_OK) { printf("udp_connect() failed.\n"); goto fatal; } // This is the main loop for lwIP - other processing can be done by calling application functions. printf("SUCCESS\n"); while(1) { udp_send(UdpPcbS,psend); mSdelay(1000); } fatal: for(;; /* { // Process lwIP timer dependent code if(lwipProcessTimerFlag) lwipProcessTimers(); // Poll lwIP for incoming packets. ethernetif_input(&alteraTseNetif); } return 0; */ } //UDP Init void Init_UDP() { UdpPcbR = udp_new(); udp_bind(UdpPcbR, IP_ADDR_ANY, 67); udp_recv(UdpPcbR,UDP_Receive,NULL); } // Run this every 250mS to update lwIP timers void lwipProcessTimers(void) { lwipProcessTimerFlag = 0; lwip250mStimer += 250; if( (lwip250mStimer % TCP_TMR_INTERVAL) == 0 ) { tcp_tmr(); } if( (lwip250mStimer % ARP_TMR_INTERVAL) == 0 ) { etharp_tmr(); } # if IP_REASSEMBLY if( (lwip250mStimer % IP_TMR_INTERVAL) == 0 ) { ip_reass_tmr(); } # endif # if LWIP_AUTOIP if( (lwip250mStimer % AUTOIP_TMR_INTERVAL ) == 0 ) { autoip_tmr(); } # endif # if LWIP_IGMP if( (lwip250mStimer % IGMP_TMR_INTERVAL ) == 0 ) { igmp_tmr(); } # endif # if LWIP_DHCP if( (lwip250mStimer % DHCP_FINE_TIMER_MSECS ) == 0 ) { dhcp_fine_tmr(); } if( (lwip250mStimer % (DHCP_COARSE_TIMER_SECS*1000) ) == 0 ) { dhcp_coarse_tmr(); } # endif # if LWIP_DNS if( (lwip250mStimer % DNS_TMR_INTERVAL) == 0 ) { dns_tmr(); } # endif }- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Add Include Path ${workspace_loc:/altera.components/Nios II Software Packages/altera_iniche/UCOSII/inc}
I cannot unstand why? this example use UC/OS???- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,billa
cannot insert breakpoint 0 is my problem! I use quartus 9.0 and nios 9.0,and I use this example to build the project http://www.alteraforum.com/forum/showthread.php?t=23787&page=3 now I can ping the board,but I can not use UDP to send the packget,so I try to debug step by step,and set the breakpoint at function udpsend().(see in picture1)As I seeing the flow,when it return,until to the function udp_sendto_if() ,pointout wrong(see in picture 2),this problem makes me truble,a week,could you give me some advices. best wishes to you,waiting for your reply.thank you!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please stop sending the same question multiple times. It won't get you more answers.
I rarely use the debugger so I can't be of much help here. For starters is 0xe11fc a valid program address, i.e. an address in your main RAM region? IF the address is complete bogus, it could indicate a memory corruption or a head/stack collision.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi BillA (and others !), Really big thanks for your lwip port on altera. I have succefully implemented the webserver template with lwip on a bemicro SDK from arrow. I have a question because i don't know how to do it : actually i have my sgdma Tx and sgdma Rx mapped on a DDR , the same DDR where the CPU data an instruction is mapped. Now imagine i want to use an onchip ram for sgdma tx and sgdmarx instead of DDR. (but CPU still mapped to DDR) I tried direclty but this is not working. if you have any idea . thanks --- Quote End --- I haven't had much luck getting this to port on the BemicroSDK... do you have any pointers on the changes you needed to make to get it to work?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi,billa cannot insert breakpoint 0 is my problem! I use quartus 9.0 and nios 9.0,and I use this example to build the project http://www.alteraforum.com/forum/showthread.php?t=23787&page=3 now I can ping the board,but I can not use UDP to send the packget,so I try to debug step by step,and set the breakpoint at function udpsend().(see in picture1)As I seeing the flow,when it return,until to the function udp_sendto_if() ,pointout wrong(see in picture 2),this problem makes me truble,a week,could you give me some advices. best wishes to you,waiting for your reply.thank you! --- Quote End --- This kind of error typically means the hardware definition is wrong. Something is wrong with memory, clocks, speeds or something. In the past I've told people that have problems with this example to get a standard Altera example running - like Simple Socket Server as-is on your hardware (create app and BSP with that template). If the Simple Socket Server won't run, this lwIP example will never run either. It's pretty hard to test and debug software with unstable hardware. BillA

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page