Ethernet BSP Layer
Description of the Ethernet BSP API
This section describes the BSP API functions that you should implement during the integration of an Ethernet interface for µC/TCP-IP.
For each Ethernet interface/device, an application must implement in net_bsp_ether.c
, a unique device-specific implementation of each of the following BSP functions:
void NetDev_CfgClk (NET_IF *p_if, NET_ERR *p_err); void NetDev_CfgIntCtrl (NET_IF *p_if, NET_ERR *p_err); void NetDev_CfgGPIO (NET_IF *p_if, NET_ERR *p_err); CPU_INT32U NetDev_ClkFreqGet(NET_IF *p_if, NET_ERR *p_err);
Since each of these functions is called from a unique instantiation of its corresponding device driver, a pointer to the corresponding network interface ( p_if
) is passed in order to access the specific interface’s device configuration or data.
Network device driver BSP functions may be arbitrarily named but since development boards with multiple devices require unique BSP functions for each device, it is recommended that each device’s BSP functions be named using the following convention:
NetDev_[Device]<Function>[Number]()
[Device]
Network device name or type. For example, MACB. (Optional if the development board does not support multiple devices.)
<Function>
Network device BSP function. For example, CfgClk.
[Number]
Network device number for each specific instance of device (optional if the development board does not support multiple instances of the specific device)
For example, the NetDev_CfgClk()
function for the #2 MACB Ethernet controller on an Atmel AT91SAM9263-EK should be named NetDev_MACB_CfgClk2()
, or NetDev_MACB_CfgClk_2()
with additional underscore optional.
Similarly, network devices’ BSP-level interrupt service routine (ISR) handlers should be named using the following convention:
NetDev_[Device]ISR_Handler[Type][Number]()
[Device]
Network device name or type. For example, MACB. (Optional if the development board does not support multiple devices.)
[Type]
Network device interrupt type. For example, receive interrupt. (Optional if interrupt type is generic or unknown.)
[Number]
Network device number for each specific instance of device (optional if the development board does not support multiple instances of a specific device).
For example, the receive ISR handler for the #2 MACB Ethernet controller on an Atmel AT91SAM9263-EK should be named NetDev_MACB_ISR_HandlerRx2()
, or NetDev_MACB_ISR_HandlerRx_2()
, with additional underscore optional.
Next, the BSP functions for each device/interface must be organized into an interface structure. This structure is used by the device driver to call specific devices’ BSP functions via function pointer instead of by name. It allows applications to add, initialize, and configure any number of instances of various devices and drivers by creating similar but unique BSP functions and interface structures for each network device/interface. (See section Interface Programming for details on how applications add interfaces to µC/TCP-IP.)
The BSP for each device or interface must be declared in the BSP source file (net_bsp.c
) for each application or development board. The BSP must also be externally declared in the network BSP header file (net_bsp.h
) with exactly the same name and type as declared in net_bsp.c
. These BSP interface structures and their corresponding functions must have unique names, and should clearly identify the development board, device name, function name, and possibly the specific device number (assuming the development board supports multiple instances of any given device). BSP interface structures may be given arbitrary names, but it is recommended that they be named using the following convention:
NetDev_BSP_<Board><Device>[Number]{}
<Board>
Development board name. For example, Atmel AT91SAM9263-EK).
<Device>
Network device name or type. For example, MACB.
[Number]
Network device number for each specific instance of the device (optional if the development board does not support multiple instances of the device).
For example, a BSP interface structure for the #2 MACB Ethernet controller on an Atmel AT91SAM9263-EK board should be named NetDev_BSP_AT91SAM9263-EK_MACB_2{}
and declared in the AT91SAM9263-EK board’s net_bsp.c
:
/* AT91SAM9263-EK MACB #2's BSP fnct ptrs : */ const NET_DEV_BSP_ETHER NetDev_BSP_AT91SAM9263-EK_MACB_2 = { NetDev_MACB_CfgClk_2, /* Cfg MACB #2's clk(s) */ NetDev_MACB_CfgIntCtrl_2, /* Cfg MACB #2's int ctrl(s) */ NetDev_MACB_CfgGPIO_2, /* Cfg MACB #2's GPIO */ NetDev_MACB_ClkFreqGet_2 /* Get MACB #2's clk freq */ };
In order for the application to configure an interface with this BSP interface structure, the structure must also be externally declared in the AT91SAM9263-EK board’s net_bsp.h
:
extern const NET_DEV_BSP_ETHER NetDev_BSP_AT91SAM9263-EK_MACB_2;
Lastly, the AT91SAM9263-EK board’s MACB #2 BSP functions must also be declared in net_bsp.c
:
static void NetDev_MACB_CfgClk_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_MACB_CfgIntCtrl_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_MACB_CfgGPIO_2 (NET_IF *p_if, NET_ERR *p_err); static CPU_INT32U NetDev_MACB_ClkFreqGet_2(NET_IF *p_if, NET_ERR *p_err);
Note that since all network device BSP functions are accessed only by function pointer via their corresponding BSP interface structure, they don’t need to be globally available and should therefore be declared as static
.
Also note that although certain device drivers may not need to implement or call all of the above network device BSP functions, we recommend that each device’s BSP interface structure define all device BSP functions, and not assign any of its function pointers to NULL
. Instead, for any device’s unused BSP functions, create empty functions that return NET_DEV_ERR_NONE
. This way, if the device driver is ever modified to start using a previously unused BSP function, there will at least be an empty function for the BSP function pointer to execute.
Details for these functions may be found in their respective sections in Ethernet Device BSP Functions and templates for network device BSP functions and BSP interface structures are available in the \Micrium\Software\uC-TCPIP\BSP\Template\
directories.
Configuring Clocks for an Ethernet Device
NetDev_CfgClk()
sets a specific network device’s clocks to a specific interface.
Each network device’s NetDev_CfgClk()
should configure and enable all required clocks for the specified network device. For example, on some devices it may be necessary to enable clock gating for an embedded Ethernet MAC, as well as various GPIO modules in order to configure Ethernet PHY pins for (R)MII mode and interrupts. See function NetDev_CfgClk for more information.
Configuring General I/O for an Ethernet Device
NetDev_CfgGPIO()
configures a specific network device’s general-purpose input/output (GPIO) on a specific interface. This function is called by a device driver’s NetDev_Init()
.
Each network device’s NetDev_CfgGPIO()
should configure all required GPIO pins for the network device. For Ethernet devices, this function is necessary to configure the (R)MII bus pins, depending on whether the user has configured an Ethernet interface to operate in the RMII or MII mode, and optionally the Ethernet PHY interrupt pin.
See function NetDev_CfgGPIO for more information.
Configuring the Interrupt Controller for an Ethernet Device
NetDev_CfgIntCtrl()
is called by a device driver’s NetDev_Init()
to configure a specific network device’s interrupts and/or interrupt controller on a specific interface.
Each network device’s NetDev_CfgIntCtrl()
function must configure and enable all required interrupt sources for the network device. This means it must configure the interrupt vector address of each corresponding network device BSP interrupt service routine (ISR) handler and enable its corresponding interrupt source.
For NetDev_CfgIntCtrl()
, the following actions should be performed:
- Configure/store each device’s network interface number to be available for all necessary
NetDev_ISR_Handler()
functions (see section Specifying the Interface Number of the Device ISR for more information). Even though devices are added dynamically, the device’s interface number must be saved in order for each device’s ISR handlers to callNetIF_ISR_Handler()
with the device’s network interface number. - Configure each of the device’s interrupts on an interrupt controller (either an external or CPU-integrated interrupt controller). However, vectored interrupt controllers may not require higher-level interrupt controller sources to be explicitly configured and enabled. In this case, you may need to configure the system’s interrupt vector table with the name of the ISR handler functions declared in
net_bsp.c
.
NetDev_CfgIntCtrl()
should enable only each devices’ interrupt sources, but not the local device-level interrupts themselves, which are enabled by the device driver only after the device has been fully configured and started.
See function NetDev_CfgIntCtrl for more information.
Getting a Device Clock Frequency
NetDev_ClkFreqGet()
returns a specific network device’s clock frequency for a specific interface. This function is called by a device driver’s NetDev_Init()
.
Each network device’s NetDev_ClkFreqGet()
should return the device’s clock frequency (in Hz). For Ethernet devices, this is the clock frequency of the device’s (R)MII bus. The device driver’s NetDev_Init()
uses the returned clock frequency to configure an appropriate bus divider to ensure that the (R)MII bus logic operates within an allowable range. In general, the device driver should not configure the divider such that the (R)MII bus operates faster than 2.5MHz.
See function NetDev_ClkGetFreq for more information.