Contents[hide]
|
The StarterWare Ethernet software deliverable consists of four main layers:
This layer implements the lowest level hardware abstraction APIs that can be used for control and configuration of the EMAC device. There are three files that form this layer and are located at StarterWare_xx_yy_mm_pp/drivers:
The device abstraction layer is implemented as a very light layer just for hardware/device access and conforms to the generic framework of StarterWare. It does not maintain any state variables.
To interface with the rest of the network, the device abstraction layer needs to be glued with a network stack that can form and interpret network packets. StarterWare uses lwIP for this purpose because it has no OS dependency and supports many standard network protocols. The device abstraction hooks into the interface layer of lwIP. This is also referred to as the device-specific "port" or the StarterWare-interface for lwIP. This lwIP interface layer forms a major part of the StarterWare network driver. It defines standard interface entry points and state variables. A network device is represented by struct netif, generically referred to as netif. The netif contains all the information about the interface, including the IP/MAC address(s), TCP/IP options, protocol handlers, link information, and (most importantly) the network device driver entry point callbacks. Every network interface must implement the linkoutput and init callbacks, and all state information is maintained in this structure. The interface layer also implements the core interrupt handling and DMA handling. All the required function calls for initializing the lwIP stack and registering the StarterWare network interface are performed in lwiplib.c. Refer to the lwIP documentation for more information about the lwIP stack implementation. Further sections below explain the network interface initialization and registration. This is located at third_party/lwip-1.x.x/ports/<port_name>/
The main tasks of the StarterWare network interface layer are:
The first step towards bringing up the interface is done as part of the <device>if_init. This function is called when the network device is registered with the lwIP stack using netif_add. As part of the initialization, the netif output callbacks are registered and hardware initialization, including PHY and DMA initialization, is performed. DMA buffer descriptor (BD) pools are maintained in the CPPI RAM for both TX and RX channels. The descriptor chains are maintained by the "free_head", which points to the next unused/free descriptor in the BD pool, and "active_tail", which points to the last BD in the active queue that has been en-queued to the hardware. The packet buffers (pbuf) are pre-allocated for maximum length and queued in the receive buffer descriptors before the reception begins. Please refer to the lwIP documentation for details on pbuf handling by lwIP.
Packet data transmission takes place inside the linkoutput callback registered with the lwIP stack. This callback is invoked whenever the lwIP stack receives a packet for transmission from the application layer. The pbuf can contain a chain of packet buffers and hence the DMA descriptors are properly updated (chained if necessary), with SOP, EOP and length fields. The first DMA descriptor is marked with the EOP and OWNER flags, while only the last is set with the EOP flag. After filling the BD's with the pbuf information, the BD, which corresponds to the SOP is written to the HEAD descriptor pointer register to start the transmission. Once a packet is transmitted, the EMAC Control Core generates a transmit interrupt. This interrupt is cleared only if the completion pointer is written with the last BD processed. In the interrupt handler, the next BD to process is taken and traversed to reach the BD that corresponds to the end of the packet. This BD, which corresponds to the end of the packet, is written to the completion pointer. After this, the pbuf that corresponds to this packet is freed. Thus it is made sure that the freeing of pbuf is done only after the packet transmission is complete.
Packet reception takes place in the context of the interrupt handler for receive. As described earlier, the receive buffer descriptors are en-queued to the DMA before the reception can actually begin. The pbuf allocated for maximum length, may actually contain a chain of packet buffers. The descriptors are updated for OWNER flag only. The EOP, SOP and EOQ are updated by the DMA upon completion of the reception. One important point to note is that, the actual data received may be less/more than the max length allocated. Hence the pbuf chain needs to be adjusted as detailed here. First, the active_head (which is the first BD en-queued), is checked for OWNER bit having been cleared by the DMA. Then the BD list is traversed, starting at the active_head, to find the EOP BD, which is the last BD of the current packet. While doing so if the EOP is not found on the current BD, then the pbuf of the current BD is chained to the pbuf of the next BD, since the current packet has spilled over to the next BD. Once, the EOP is found the last pbuf is updated as the terminator (pbuf->next = NULL). Thus, the entire packet is collected and passed to the upper layer for processing. Since, the current BD has been done with, it is put back at the free_head, by allocating a new pbuf.
This layer contains the ethernet application (HTTP server, echo server, etc.). This is located at StarterWare_xx_yy_mm_pp/third_party/lwip-1.x.x/apps/<application>. This is the layer at which all the imcoming packets terminate and all outgoing packets originate.
This layer implements system level initialization and provides options for lwIP stack. This layer can contain any other algorithms, decoding, etc. The main IP stack based application is part of the lwip directory as mentioned above.