Wireless BSP Layer
Description of the Wireless BSP API
This section describes the BSP API functions that you should implement during the integration of a wireless interface for µC/TCP-IP.
For each wireless interface/device, an application must implement (in net_bsp_wifi.c
) a unique device-specific implementation of each of the following BSP functions:
void NetDev_WiFi_Start (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_Stop (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_CfgGPIO (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_CfgIntCtrl (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_IntCtrl (NET_IF *p_if, CPU_BOOLEAN en, NET_ERR *p_err); void NetDev_WiFi_SPI_Init (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_SPI_Lock (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_SPI_Unlock (NET_IF *p_if); void NetDev_WiFi_SPI_WrRd (NET_IF *p_if, CPU_INT08U *p_buf_wr, CPU_INT08U *p_buf_rd, CPU_INT16U len, NET_ERR *p_err); void NetDev_WiFi_SPI_ChipSelEn (NET_IF *p_if, NET_ERR *p_err); void NetDev_WiFi_SPI_ChipSelDis(NET_IF *p_if); void NetDev_WiFi_SPI_Cfg (NET_IF *p_if, NET_DEV_CFG_SPI_CLK_FREQ freq, NET_DEV_CFG_SPI_CLK_POL pol, NET_DEV_CFG_SPI_CLK_PHASE phase, NET_DEV_CFG_SPI_XFER_UNIT_LEN xfer_unit_len, NET_DEV_CFG_SPI_XFER_SHIFT_DIR xfer_shift_dir, 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 a specific device)
For example, the NetDev_CfgGPIO()
function for the #2 RS9110-N-21 wireless module on an Atmel AT91SAM9263-EK should be named NetDev_RS9110N21_CfgGPIO2()
, or NetDev_RS9110N21_CfgGPIO_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 RS9110-N-21 wireless module on an Atmel AT91SAM9263-EK should be named NetDev_RS9110N21_ISR_HandlerRx2()
, or NetDev_RS9110N21_ISR_HandlerRx_2()
with additional underscore optional.
Next, each device’s/interface’s BSP functions must be organized into an interface structure used by the device driver to call specific devices’ BSP functions via function pointer instead of by name. This 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.)
Each device’s/interface’s BSP interface structure must be declared in the application’s/ development board’s network BSP source file, net_bsp.c
, as well as externally declared in the network BSP header file, net_bsp.h
, with the exact same name and type as declared in net_bsp.c
. These BSP interface structures and their corresponding functions must be uniquely named 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 arbitrarily named 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, RS9110-N-21.
[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 RS9110-N21 wireless module on an Atmel AT91SAM9263-EK board should be named NetDev_BSP_AT91SAM9263-EK_RS9110N21_2{}
and declared in the AT91SAM9263-EK board’s net_bsp.c
:
/* AT91SAM9263-EK RS9110-N21 #2's BSP fnct ptrs : */ const NET_DEV_BSP_WIFI_SPI NetDev_BSP_AT91SAM9263-EK_RS9110N21_2 = { NetDev_RS9110N21_Start_2 NetDev_RS9110N21_Stop_2, NetDev_RS9110N21_CfgGPIO_2, NetDev_RS9110N21_CfgExtIntCtrl_2 NetDev_RS9110N21_ExtIntCtrl_2, NetDev_RS9110N21_SPI_Cfg_2, NetDev_RS9110N21_SPI_Lock_2, NetDev_RS9110N21_SPI_Unlock_2, NetDev_RS9110N21_SPI_WrRd_2, NetDev_RS9110N21_SPI_ChipSelEn_2, NetDev_RS9110N21_SPI_ChipSelDis_2, NetDev_RS9110N21_SetCfg_2 };
And in order for the application to configure an interface with this BSP interface structure, the structure must be externally declared in the AT91SAM9263-EK board’s net_bsp.h
:
extern const NET_DEV_BSP_WIFI_SPI NetDev_BSP_AT91SAM9263-EK_RS9110N21_2;
Lastly, the board’s RS9110-N-21 #2 BSP functions must also be declared in net_bsp.c
:
static void NetDev_RS9110N21_Start_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_Stop_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_CfgGPIO_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_CfgIntCtrl_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_IntCtrl_2 (NET_IF *p_if, CPU_BOOLEAN en, NET_ERR *p_err); static void NetDev_RS9110N21_SPI_Init_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_SPI_Lock_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_SPI_Unlock_2 (NET_IF *p_if); static void NetDev_RS9110N21_SPI_WrRd_2 (NET_IF *p_if, CPU_INT08U *p_buf_wr, CPU_INT08U *p_buf_rd, CPU_INT16U len, NET_ERR *p_err); static void NetDev_RS9110N21_SPI_ChipSelEn_2 (NET_IF *p_if, NET_ERR *p_err); static void NetDev_RS9110N21_SPI_ChipSelDis_2(NET_IF *p_if); static void NetDev_RS9110N21_SPI_Cfg_2 (NET_IF *p_if, NET_DEV_CFG_SPI_CLK_FREQ freq, NET_DEV_CFG_SPI_CLK_POL pol, NET_DEV_CFG_SPI_CLK_PHASE phase, NET_DEV_CFG_SPI_XFER_UNIT_LEN xfer_unit_len, NET_DEV_CFG_SPI_XFER_SHIFT_DIR xfer_shift_dir, 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 function, 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 Wireless Device BSP Functions. Templates for network device BSP functions and BSP interface structures can be found in the directory \Micrium\Software\uC-TCPIP-V2\BSP\Template\
.
Configuring General-Purpose I/O for a Wireless Device
NetDev_WiFi_CfgGPIO()
configures a specific network device's general-purpose input/ouput (GPIO) on a specific interface. This function is called by a device driver's NetDev_Init()
.
Each network device's NetDev_WiFi_CfgGPIO()
should configure all required GPIO pins for the network device. For wireless devices, this function is necessary to configure the power, reset and interrupt pins.
See function NetDev_WiFi_CfgGPIO
for more information.
Starting a Wireless Device
NetDev_WiFi_Start()
is used to power up the wireless chip. This function is called by a device driver’s NetDev_WiFi_Start()
each time the interface is started.
Each network device’s NetDev_WiFi_Start()
must set GPIO pins to power up and reset the wireless device. For wireless devices, this function is necessary to configure the power pin and other required pins to power up the wireless chip. Note that a wireless device could require the toggle on the Reset pin to be started or restarted correctly.
See function NetDev_WiFi_Start
for more information.
Stopping a Wireless Device
NetDev_WiFi_Stop()
is used to power down a wireless chip. This function is called by a device driver's NetDev_WiFi_Stop()
each time the interface is stopped.
Each network device's NetDev_WiFi_Start()
must set GPIO pins to power down the wireless chip to reduce the power consumption. For wireless devices, this function is necessary to configure the power pin and other required pins to power down the wireless chip.
See function NetDev_WiFi_Stop
for more information.
Configuring the Interrupt Controller for a Wireless Device
NetDev_WiFi_CfgIntCtrl()
is called by a device driver’s NetDev_WiFi_Init()
to configure a specific wireless device’s external interrupts for a specific wireless interface.
Each network device’s NetDev_WiFi_CfgIntCtrl()
function must configure without enabling 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 disable its corresponding interrupt source. For NetDev_WiFi_CfgIntCtrl()
, the following actions should be performed:
- Configure/store each device’s network interface number to be available for all necessary
NetDev_WiFi_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_WiFi_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_WiFi_CfgIntCtrl()
should disable only each devices’ interrupt sources. See function NetDev_WiFi_CfgIntCtrl
for more information.
Enabling and Disabling Wireless Interrupt
Each network device’s NetDev_WiFi_IntCtrl()
function must enable or disable all external required interrupt sources for the wireless device. This means enable or disable its corresponding interrupt source following the enable argument received.
See function NetDev_WiFi_IntCtrl
for more information.
Configuring the SPI Interface
NetDev_WiFi_SPI_Init()
initializes a specific network device’s SPI controller. This function will be called by a device driver’s NetDev_WiFi_SPI_Init()
when the interface is added.
Each network device’s NetDev_WiFi_SPI_Init()
should configure all required SPI controllers registers for the network device. Since more than one device may share the same SPI bus, this function could be empty if the SPI controller is already configured.
If the SPI bus is not shared with other devices, it is recommended that NetDev_WiFi_SPI_Init()
configures the SPI controller following the SPI device’s communication settings and keep NetDev_WiFi_SPI_Cfg()
empty.
See NetDev_WiFi_SPI_Cfg
for more information.
Setting SPI Controller for a Wireless device
NetDev_WiFi_SPI_Cfg()
configures a specific network device’s SPI communication settings. This function is called by a device driver after the SPI’s bus lock has been acquired and before starting to write and read to the SPI bus.
Each network device’s NetDev_WiFi_SPI_Cfg()
should configure all required SPI controllers registers for the SPI’s communication setting of the network wireless device. Several aspects of SPI communication may need to be configured, including:
- Clock frequency
- Clock polarity
- Clock phase
- Transfer unit length
- Shift direction
Since more than one device with different SPI communication settings may share the same SPI bus, this function must reconfigure the SPI controller following the device’s SPI communication setting each time the device driver must access the SPI bus. If the SPI bus is not shared with other devices, it’s recommended that NetDev_SPI_Cfg()
configures the SPI controller following the SPI’s communication setting of the wireless device and to keep this function empty.
See NetDev_WiFi_SPI_Cfg
for more information.
Locking and Unlocking SPI Bus
NetDev_WiFi_SPI_Lock()
acquires a specific network device's SPI bus access. This function will be called before the device driver begins to access the SPI. The application should not use the same bus to access another device until the matching call to NetDev_WiFI_SPI_Unlock()
has been made. If no other SPI device shares the same SPI bus, it's recommended to keep this function empty.
See function NetDev_WiFi_SPI_Lock
for more information.
Enabling and Disabling SPI Chip select
NetDev_WiFi_SPI_ChipSelEn()
enables the chip select pin of the wireless device. This function is called before the device driver begins to access the SPI. The chip select pin should stay enabled until the matching call to NetDev_WiFi_SPI_ChipSelDis()
has been made. The chip select pin is typically “active low.” To enable the device, the chip select pin should be cleared; to disable the device, the chip select pin should be set.
See function NetDev_WiFi_SPI_ChipSelEn
for more information.
Writing and Reading to the SPI Bus
NetDev_WiFi_SPI_WrRd()
writes and reads data to and from the SPI bus. This function is called each time the device driver accesses the SPI bus. NetDev_WiFi_SPI_WrRd()
must not return until the write/read operation is complete. Writing and reading to the SPI bus by using DMA is possible, but the BSP layer must implement a notification mechanism to return from this function only when the write and read operations are entirely completed. See function NetDev_WiFi_SPI_WrRd
for more information.