Porting oWL Pico API to a new platform
The oWL Pico API is available in the
wlp_api/
folder of the source package available here
DownloadSources. Currently, the source package also includes a reference design software which gives an example of how the oWL Pico API can be used. This reference design software can be compiled to run on a linux host or on an Atmel XPLAIN host.
To run oWL Pico API on another platform, a small porting effort might be required. This section will guide you through the necessary steps to do such a porting.
Verify the hardware connections
- Check that there is 3.3V on pin 10 and Ground at pin 9
- Check that pin 2 isn’t pulled high by the host, it will power down the SPB800
- Check that UART RX (PIN 4) on the SPB800 goes to TX on the host MCU and that UART TX (PIN 3) on the SPB800 goes to RX on the host.
- If RTS/CTS are used, check their connectivity.
- Check that nothing blocks the RF signals from the antenna
Version 2.3.0
Build a minimal example
An simple example of how to write a simple pico client can be found under the Linux-application "pico_simple" in the pico_framework.
Porting this example to another platform is rather straightforward:
1. Initialize the platforms UART port and corresponding gpios (Baudrate 115200, 8 Databits, no parity, 1 stopbit).
2. Implement the function: board_exchange(void *ctx, const void *tx, void *rx, int len).
This function should check the rx and tx in-parameters for either write or read and act accordingly.
When rx parameter is non-NULL, the function must block until len bytes has been read from the UART.
The function must return the number of bytes read/written.
3. Implement the function: int board_poll(void *ctx).
This function is responsible of signaling the api of incoming UART data.
E.g. if the host has a UART read buffer, the board_poll() can return the number of bytes in the buffer.
If there is no UART buffer available, board_poll() needs to at least return a non-zero value when UART data
is incoming (e.g. UART RX interrupt).
4. Implement the function: void board_delay(int ms).
This function should implement a millisec-delay. board_delay() should be called before calling wlp_init() to make sure
that the wifi-module is done booting.
Up to Version 2.2.0
Build a minimal example
A small (but complete) example,
tutorial.c, is provided here. If oWL Pico API version 1.2.0 or later is used, use this file instead:
tutorial-1.2.c. The example will initialize the oWL Pico API and connect to the access point "hdwireless".
The minimal example is basically a summary of the code fragments available on the wiki. As the example contains code to read and write from the UART, these functions will probably have to be modified for the particular platform:
- Implement
board_uart_read_f()
to read data from the UART which the SPB800 is connected to. Note that this function must block until all requested data are read. When board_uart_read_f()
is called, the requested number of bytes (as passed in the "len" parameter) are expected to be sent by the device immediately.
- Implement
board_uart_write_f()
to write data to the UART which the SPB800 is connected. to Note that this function must block until all the data is written.
- Implement
board_uart_init()
to set the baudrate to 57600.
- Implement
board_delay()
so that at least the requested delay is obtained. If this is done with e.g. for-loops, make sure that the code doesn't get optimized away. The delay is really important for the example, since it makes sure that the SPB800 is done booting before the host starts to transmit data.
Note that the
tutorial.c
file is divided into a plaform-dependent and a platform-independent part. All the platform-specific functions are prefixed with
board_
. Having the wlp_api/ folder in the same folder as the
tutorial.c
file, we compiled it for the atxmega128a1 (8-bit MCU) with the following commands:
$ avr-gcc -mmcu=atxmega128a1 -Os -DBYTE_ORDER=LITTLE_ENDIAN -Iwlp_api
wlp_api/wlp_api.c wlp_api/wlp_inet.c tutorial.c -o tutorial.elf
The exact build procedure will of course vary depending on the build environment used for the platform. However, make sure to use the -DBYTE_ORDER=LITTLE_ENDIAN or -DBYTE_ORDER=BIG_ENDIAN, depending on the host CPU endianness.
When the minimal application is loaded started it will initialize the oWL Pico API and connect to the "hdwireless" AP (no encryption). If working, the linkup LED should be enabled. If the AP has a DHCP server, the ip LED should also be enabled.
Debugging the UART communication
If the communication with the SPB800 fails in any way the UART communication must be debugged.
When the device is powered on, it will send the "." (dot) character five times, one char every second. It should be possible to see these on a oscilloscope. When
wlp_init()
is called, the device will stop sending dots and instead send a 'w' char and a "confirm"-message (2 bytes) to indicate that the device is ready.
If
wlp_init()
is not called, the device will stop sending dots after 5 seconds, however it is still valid to call wlp_init() after this time and the device will reply with a 'w' and the confirm-message in the same way. See the documentation for
wlp_init()
in wlp_api/wlp_api.h for more information.
To debug the UART communication efficiently, the host could wait > 5 seconds before any data is transmitted. That way we don't get any spurious dots in the host UART FIFO or on the oscilloscope and can focus on what is actually transmitted by the host and the actual reply from the Wi-Fi device.
For oWL Pico versions
prior 1.2.0, the following data will be sent and received on the UART when wlp_init() is called (given that the baudrate parameter is 57600 and the rtscts parameter is 0):
TX: 0x77 ('w' sent by host)
RX: 0x77 ('w' sent by device)
TX: 0x09 (sizeof(struct wlp_uart_config_req)+1 sent by host)
RX: 0x09 (echoed by the device)
TX: 0x00 XXXX XXXX 0x00 0x00 0x00 0xe1 0x00 (struct wlp_uart_config_req sent by host)
RX: 0x00 0x00 (struct wlp_uart_config_cfm sent by device)
For oWL Pico versions
1.2.0 or later, the following data will be sent and received on the UART when wlp_init() is called:
TX: 0x77 ('w' sent by host)
RX: 0x77 ('w' sent by device)
Bytes marked as
XXXX
above are ignored and can have a random value.
If the execution seems to hang in board_uart_read_f(), there might be a problem with lost chars on the UART fifo on the host. This can occur e.g. if the host platform has a very small fifo (just a few bytes) and something intterupts the UART read operation (e.g. an interrupt).
Troubleshooting checklist
If the example application does not work properly, e.g. hangs in
board_uart_read_f()
, returns
WLP_ERR_PROTO
in a call to a oWL Pico API function, or just fails to connect to an AP:
- Verify the hardware connections again
- Verify the UART driver using a loopback test, e.g. by connecting the TX and RX line on the host.
- Verify that no data are lost when receiving data on the UART (e.g. by checking a overflow flag on the host).
- Check that the 57600 is really used by the UART.
- The SPB800 will send 5 "." (dot characters) upon power-up. If they can not be observed by e.g. an oscilloscope, the SPB800 might not be powered in the proper way or the device might be broken.
- Make sure that the
board_delay()
function really delays the execution long enough.
- Make sure that the proper endian is used (define either
LITTLE_ENDIAN
or BIG_ENDIAN
during compile).
- Verify that all the structs in
wlp_proto.h
are packed and got the proper size. Use sizeof()
to get the actual size in your build environment. The expected size is documented for each struct.
- Verify that the SSID of the AP is correct and that encryption is disabled.
Power management
See the wlp_api.h file for information about the power management functionality in general, and also for detailed description of the functions used for power management.
Achieving low power operation is always a tradeoff between some aspect of performance (or an entire feature) and the power consumption of the device. Beware that those functions can make the device difficult to reach. It is recommended that you verify the functionality of your application before attempting to reduce the power consumption with those functions.