xref: /openwifi/doc/README.md (revision b1dd94e38780b1645f1f7894c71908d8218f3d7f)
1a6085186SLina Ceballos<!--
291398b98SJiao XianjunAuthor: Xianjun jiao, Michael Mehari, Wei Liu
3b9dde989SJiao XianjunSPDX-FileCopyrightText: 2019 UGent
4a6085186SLina CeballosSPDX-License-Identifier: AGPL-3.0-or-later
5a6085186SLina Ceballos-->
6a6085186SLina Ceballos
7a6085186SLina Ceballos
8da2a8350SJiao Xianjun# Openwifi document
92ee67178SXianjun Jiao<img src="./openwifi-detail.jpg" width="1100">
102ee67178SXianjun Jiao
114f977aa9SJiao XianjunAbove figure shows software and hardware/FPGA modules that compose the openwifi design. The module name is equal/similar to the source code file name. Driver module source codes are in openwifi/driver/. FPGA module source codes are in openwifi-hw repository. The user space tool sdrctl source code are in openwifi/user_space/sdrctl_src/.
122ee67178SXianjun Jiao
13da2a8350SJiao Xianjun- [Driver and software overall principle](#Driver-and-software-overall-principle)
1410d539beSJiao Xianjun- [sdrctl command](#sdrctl-command)
15da2a8350SJiao Xianjun- [Rx packet flow and filtering config](#Rx-packet-flow-and-filtering-config)
16da2a8350SJiao Xianjun- [Tx packet flow and config](#Tx-packet-flow-and-config)
17da2a8350SJiao Xianjun- [Regulation and channel config](#Regulation-and-channel-config)
18da2a8350SJiao Xianjun- [Analog and digital frequency design](#Analog-and-digital-frequency-design)
19da2a8350SJiao Xianjun- [Debug methods](#Debug-methods)
20bf6ebc28SJiao Xianjun- [Application notes](app_notes)
215f436b3cSJiao Xianjun
22da2a8350SJiao Xianjun## Driver and software overall principle
235f436b3cSJiao Xianjun
244f977aa9SJiao Xianjun[Linux mac80211 subsystem](https://www.kernel.org/doc/html/v4.16/driver-api/80211/mac80211.html), as a part of [Linux wireless](https://wireless.wiki.kernel.org/en/developers/documentation/mac80211), defines a set of APIs ([ieee80211_ops](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#c.ieee80211_ops)) to rule the Wi-Fi chip driver behavior. SoftMAC Wi-Fi chip driver implements (subset of) those APIs. That is why Linux can support so many Wi-Fi chips of different chip vendors.
255f436b3cSJiao Xianjun
265f436b3cSJiao Xianjunopenwifi driver (sdr.c) implements following APIs of ieee80211_ops:
275f436b3cSJiao Xianjun-	**tx**. It is called when upper layer has a packet to send
285f436b3cSJiao Xianjun-	**start**. It is called when NIC up. (ifconfig sdr0 up)
295f436b3cSJiao Xianjun-	**stop**. It is called when NIC down. (ifconfig sdr0 down)
305f436b3cSJiao Xianjun-	**add_interface**. It is called when NIC is created
315f436b3cSJiao Xianjun-	**remove_interface**. It is called when NIC is deleted
325f436b3cSJiao Xianjun-	**config**. It is called when upper layer wants to change channel/frequency (like the scan operation)
335f436b3cSJiao Xianjun-	**bss_info_changed**. It is called when upper layer believe some BSS parameters need to be changed (BSSID, TX power, beacon interval, etc)
345f436b3cSJiao Xianjun-	**conf_tx**. It is called when upper layer needs to config/change some tx parameters (AIFS, CW_MIN, CW_MAX, TXOP, etc)
356a6fa9b4Sweiliu1011-	**prepare_multicast**. It is called when upper layer needs to prepare multicast, currently only a empty function hook is present.
364ecf49bbSJiao Xianjun-	**configure_filter**. It is called when upper layer wants to config/change the [frame filtering](#Rx-packet-flow-and-filtering-config) rule in FPGA.
375f436b3cSJiao Xianjun-	**rfkill_poll**. It is called when upper layer wants to know the RF status (ON/OFF).
385f436b3cSJiao Xianjun-	**get_tsf**. It is called when upper layer wants to get 64bit FPGA timer value (TSF - Timing synchronization function)
395f436b3cSJiao Xianjun-	**set_tsf**. It is called when upper layer wants to set 64bit FPGA timer value
405f436b3cSJiao Xianjun-	**reset_tsf**. It is called when upper layer wants to reset 64bit FPGA timer value
415f436b3cSJiao Xianjun-	**set_rts_threshold**. It is called when upper layer wants to change the threshold (packet length) for turning on RTS mechanism
425f436b3cSJiao Xianjun-	**testmode_cmd**. It is called when upper layer has test command for us. [sdrctl command](#sdrctl-command) message is handled by this function.
435f436b3cSJiao Xianjun
446a6fa9b4Sweiliu1011Above APIs are called by upper layer (Linux mac80211 subsystem). When they are called, the driver (sdr.c) will do necessary job over SDR platform. If necessary, the driver will call other component drivers, like tx_intf_api/rx_intf_api/openofdm_tx_api/openofdm_rx_api/xpu_api, for help.
455f436b3cSJiao Xianjun
464f977aa9SJiao XianjunAfter receiving a packet from the air, FPGA will raise interrupt (if the frame filtering rule allows) to Linux, then the function openwifi_rx_interrupt() of openwifi driver (sdr.c) will be triggered. In that function, ieee80211_rx_irqsafe() API is used to give the packet and related information (timestamp, rssi, etc) to upper layer.
4710d539beSJiao Xianjun
486a6fa9b4Sweiliu1011The packet sending is initiated by upper layer. After the packet is sent by the driver over FPGA to the air, the upper layer will expect a sending report from the driver. Each time FPGA sends a packet, an interrupt will be raised to Linux and trigger openwifi_tx_interrupt(). This function will report the sending result (failed? succeeded? number of retransmissions, etc.) to upper layer via ieee80211_tx_status_irqsafe() API.
495f436b3cSJiao Xianjun
505f436b3cSJiao Xianjun## sdrctl command
512ee67178SXianjun Jiao
5262591d26Sweiliu1011Besides the Linux native Wi-Fi control programs, such as ifconfig/iw/iwconfig/iwlist/wpa_supplicant/hostapd/etc, openwifi offers a user space tool sdrctl to access openwifi specific functionalities, such as time sharing of the interface between two network slices, you may find more details of the slicing mechanism [here](https://doc.ilabt.imec.be/ilabt/wilab/tutorials/openwifi.html#sdr-tx-time-slicing).
5362591d26Sweiliu1011
5462591d26Sweiliu1011sdrctl is implemented as nl80211 testmode command and communicates with openwifi driver (function openwifi_testmode_cmd() in sdr.c) via Linux nl80211--cfg80211--mac80211 path
552ee67178SXianjun Jiao
56da2a8350SJiao Xianjun### Get and set a parameter
572ee67178SXianjun Jiao```
582ee67178SXianjun Jiaosdrctl dev sdr0 get para_name
592ee67178SXianjun Jiaosdrctl dev sdr0 set para_name value
602ee67178SXianjun Jiao```
6162591d26Sweiliu1011para_name|meaning|comment
622ee67178SXianjun Jiao---------|-------|----
63*b1dd94e3Sluz pazslice_idx|the slice that will be set/get|0~3. After finishing all slice config, **set slice_idx to 4** to synchronize all slices. Otherwise the start/end of different slices have different actual time
644ecf49bbSJiao Xianjunaddr|target MAC address of tx slice_idx|32bit. for address 6c:fd:b9:4c:b1:c1, you set b94cb1c1
654ecf49bbSJiao Xianjunslice_total|tx slice_idx cycle length in us|for length 50ms, you set 49999
664ecf49bbSJiao Xianjunslice_start|tx slice_idx cycle start time in us|for start at 10ms, you set 10000
674ecf49bbSJiao Xianjunslice_end|  tx slice_idx cycle end   time in us|for end   at 40ms, you set 39999
68e63d1ec3SXianjun Jiaotsf| sets TSF value| it requires two values "high_TSF low_TSF". Decimal
692ee67178SXianjun Jiao
70da2a8350SJiao Xianjun### Get and set a register of a module
712ee67178SXianjun Jiao```
722ee67178SXianjun Jiaosdrctl dev sdr0 get reg module_name reg_idx
732ee67178SXianjun Jiaosdrctl dev sdr0 set reg module_name reg_idx reg_value
742ee67178SXianjun Jiao```
751bbbbdc7SJiao Xianjunmodule_name refers to the name of driver functionality, can be drv_rx/drv_tx/drv_xpu. Related registers are defined in sdr.h (drv_rx_reg_val/drv_tx_reg_val/drv_xpu_reg_val)
762ee67178SXianjun Jiao
771bbbbdc7SJiao Xianjunmodule_name rf/rx_intf/tx_intf/rx/tx/xpu refer to RF (ad9xxx front-end) and FPGA modules (rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu). Related register addresses are defined in hw_def.h.
782ee67178SXianjun Jiao
79404ff4e0SJiao Xianjunmodule_name: **drv_rx**
802ee67178SXianjun Jiao
8162591d26Sweiliu1011reg_idx|meaning|comment
822ee67178SXianjun Jiao-------|-------|----
832ee67178SXianjun Jiao1|rx antenna selection|0:rx1, 1:rx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
844ecf49bbSJiao Xianjun7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON)
852ee67178SXianjun Jiao
86404ff4e0SJiao Xianjun(In the **comment** column, you may get a list of **decimalvalue(0xhexvalue):explanation** for a register, only use the **decimalvalue** in the sdrctl command)
87404ff4e0SJiao Xianjun
88404ff4e0SJiao Xianjunmodule_name: **drv_tx**
892ee67178SXianjun Jiao
9062591d26Sweiliu1011reg_idx|meaning|comment
912ee67178SXianjun Jiao-------|-------|----
922ee67178SXianjun Jiao0|override Linux rate control of tx unicast data packet|4:6M, 5:9M, 6:12M, 7:18M, 8:24M, 9:36M, 10:48M, 11:54M
932ee67178SXianjun Jiao1|tx antenna selection|0:tx1, 1:tx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
944ecf49bbSJiao Xianjun7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON)
952ee67178SXianjun Jiao
96404ff4e0SJiao Xianjunmodule_name: **drv_xpu**
972ee67178SXianjun Jiao
9862591d26Sweiliu1011reg_idx|meaning|comment
992ee67178SXianjun Jiao-------|-------|----
100e240bea2SJiao Xianjun7|git revision when build the driver|example: return value 0071bc74 means git revision is 071bc74 (the 1st 0 must be removed!)
1012ee67178SXianjun Jiao
102404ff4e0SJiao Xianjunmodule_name: **rf**
1032ee67178SXianjun Jiao
10462591d26Sweiliu1011reg_idx|meaning|comment
1052ee67178SXianjun Jiao-------|-------|----
10662591d26Sweiliu1011x|x|to be defined
1072ee67178SXianjun Jiao
108404ff4e0SJiao Xianjunmodule_name: **rx_intf**
1092ee67178SXianjun Jiao
11062591d26Sweiliu1011reg_idx|meaning|comment
1112ee67178SXianjun Jiao-------|-------|----
1122ee67178SXianjun Jiao2|enable/disable rx interrupt|256(0x100):disable, 0:enable
1132ee67178SXianjun Jiao
114404ff4e0SJiao Xianjunmodule_name: **tx_intf**
1152ee67178SXianjun Jiao
11662591d26Sweiliu1011reg_idx|meaning|comment
1172ee67178SXianjun Jiao-------|-------|----
118b73660adSXianjun Jiao13|tx I/Q digital gain before DUC|current optimal value: 100
1192ee67178SXianjun Jiao14|enable/disable tx interrupt|196672(0x30040):disable, 64(0x40):enable
1202ee67178SXianjun Jiao
121404ff4e0SJiao Xianjunmodule_name: **rx**
1222ee67178SXianjun Jiao
12362591d26Sweiliu1011reg_idx|meaning|comment
1242ee67178SXianjun Jiao-------|-------|----
1252ee67178SXianjun Jiao20|history of PHY rx state|read only. If the last digit readback is always 3, it means the Viterbi decoder stops working
1262ee67178SXianjun Jiao
127404ff4e0SJiao Xianjunmodule_name: **tx**
1282ee67178SXianjun Jiao
12962591d26Sweiliu1011reg_idx|meaning|comment
1302ee67178SXianjun Jiao-------|-------|----
1312ee67178SXianjun Jiao1|pilot scrambler initial state|lowest 7 bits are used. 0x7E by default in openofdm_tx.c
1322ee67178SXianjun Jiao2|data  scrambler initial state|lowest 7 bits are used. 0x7F by default in openofdm_tx.c
1332ee67178SXianjun Jiao
134404ff4e0SJiao Xianjunmodule_name: **xpu**
1352ee67178SXianjun Jiao
13662591d26Sweiliu1011reg_idx|meaning|comment
1372ee67178SXianjun Jiao-------|-------|----
138365a7066SJiao Xianjun1|mute rx I/Q when tx|0:mute (default), 1:unmute, which means rx baseband will receive our own tx signal. Rx packet and tx packet (such as ACK) can be monitored in FPGA for timing analysis
1392ee67178SXianjun Jiao2|TSF timer low  32bit write|only write this register won't trigger the TSF timer reload. should use together with register for high 32bit
1402ee67178SXianjun Jiao3|TSF timer high 32bit write|falling edge of MSB will trigger the TSF timer reload, which means write '1' then '0' to MSB
1412ee67178SXianjun Jiao4|band and channel number setting|see enum openwifi_band in hw_def.h. it will be set automatically by Linux. normally you shouldn't set it
14210d539beSJiao Xianjun11|max number of retransmission in FPGA|normally number of retransmissions controlled by Linux in real-time. If you write non-zeros value to this register, it will override Linux real-time setting
1432ee67178SXianjun Jiao19|CSMA enable/disable|3758096384(0xe0000000): disable, 3:enable
1440669334cSJiao Xianjun27|FPGA packet filter config|check openwifi_configure_filter in sdr.c. also [mac80211 frame filtering](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering)
1452ee67178SXianjun Jiao28|BSSID address low  32bit for BSSID filtering|normally it is set by Linux in real-time automatically
1462ee67178SXianjun Jiao29|BSSID address high 32bit for BSSID filtering|normally it is set by Linux in real-time automatically
1472ee67178SXianjun Jiao30|openwifi MAC address low  32bit|
1482ee67178SXianjun Jiao31|openwifi MAC address high 32bit|check XPU_REG_MAC_ADDR_write in sdr.c to see how we set MAC address to FPGA when NIC start
1492ee67178SXianjun Jiao58|TSF runtime value low  32bit|read only
1502ee67178SXianjun Jiao59|TSF runtime value high 32bit|read only
151e1d42e15SJiao Xianjun63|git revision when build the FPGA|example: return value 065272ac means git revision is 65272ac (the 1st 0 must be removed!)
1525f436b3cSJiao Xianjun
153da2a8350SJiao Xianjun## Rx packet flow and filtering config
1545f436b3cSJiao Xianjun
155e8237378SJiao XianjunAfter FPGA receives a packet, no matter the FCS/CRC is correct or not it will raise interrupt to Linux if the frame filtering rule allows (See also [mac80211 frame filtering](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering)). openwifi_rx_interrupt() function in sdr.c will be triggered to do necessary operation and give the information to upper layer (Linux mac80211 subsystem).
1565f436b3cSJiao Xianjun
15710d539beSJiao Xianjun- frame filtering
15810d539beSJiao Xianjun
159f71252c5SXianjun JiaoThe FPGA frame filtering configuration is done in real-time by function openwifi_configure_filter() in sdr.c. The filter_flag together with **HIGH_PRIORITY_DISCARD_FLAG** finally go to pkt_filter_ctl.v of xpu module in FPGA, and control how FPGA does frame filtering. Openwifi has the capability to capture all received packets even if the CRC is bad. You just need to set the NIC to monitor mode by iwconfig command (check monitor_ch.sh in user_space directory). In monitor mode, openwifi_configure_filter() will set **MONITOR_ALL** to the frame filtering module pkt_filter_ctl.v in FPGA. This makes sure transfer all received packets to Linux mac80211 via rx interrupt.
16010d539beSJiao Xianjun
16110d539beSJiao Xianjun- main rx interrupt operations in openwifi_rx_interrupt()
1624f977aa9SJiao Xianjun  - get raw content from DMA buffer. When Linux receives interrupt from FPGA rx_intf module, the content has been ready in Linux DMA buffer
16310d539beSJiao Xianjun  - parse extra information inserted by FPGA in the DMA buffer
16410d539beSJiao Xianjun    - TSF timer value
1654f977aa9SJiao Xianjun    - raw RSSI value that will be converted to actual RSSI in dBm by different correction in different bands/channels
16610d539beSJiao Xianjun    - packet length and MCS
16710d539beSJiao Xianjun    - FCS is valid or not
16810d539beSJiao Xianjun  - send packet content and necessary extra information to upper layer via ieee80211_rx_irqsafe()
1695f436b3cSJiao Xianjun
170da2a8350SJiao Xianjun## Tx packet flow and config
1715f436b3cSJiao Xianjun
17210d539beSJiao XianjunLinux mac80211 subsystem calls openwifi_tx() to initiate a packet sending.
17310d539beSJiao Xianjun
17410d539beSJiao Xianjun- main operations in openwifi_tx()
17510d539beSJiao Xianjun  - get necessary information from the packet header (struct ieee80211_hdr) for future FPGA configuration use
17610d539beSJiao Xianjun    - packet length and MCS
1774f977aa9SJiao Xianjun    - unicast or broadcast? does it need ACK? how many retransmissions at most are allowed to be tried by FPGA in case ACK is not received in time?
17810d539beSJiao Xianjun    - which time slice in FPGA the packet should go?
17910d539beSJiao Xianjun    - should RTS-CTS be used? (Send RTS and wait for CTS before actually send the data packet)
18010d539beSJiao Xianjun    - should CTS-to-self be used? (Send CTS-to-self packet before sending the data packet. You can force this on by force_use_cts_protect = true;)
18110d539beSJiao Xianjun    - should a sequence number be set for this packet?
1824f977aa9SJiao Xianjun  - generate SIGNAL field according to length and MCS information. Insert it before the packet for the future openofdm_tx FPGA module use
1834f977aa9SJiao Xianjun  - generate FPGA/PHY sequence number (priv->phy_tx_sn) for internal use (cross check between Linux and FPGA)
1844f977aa9SJiao Xianjun  - config FPGA register according to the above information to make sure FPGA do correct actions according to the packet specific requirement.
18510d539beSJiao Xianjun  - fire DMA transmission from Linux to one of FPGA tx queues. The packet may not be sent immediately if there are still some packets in FPGA tx queue (FPGA does the queue packet transmission according to channel and low MAC state)
18610d539beSJiao Xianjun
1874f977aa9SJiao XianjunEach time when FPGA sends a packet, an interrupt will be raised to Linux reporting the packet sending result. This interrupt handler is openwifi_tx_interrupt().
18810d539beSJiao Xianjun
18910d539beSJiao Xianjun- main operations in openwifi_tx_interrupt()
1904f977aa9SJiao Xianjun  - get necessary information/status of the packet just sent by FPGA
1914f977aa9SJiao Xianjun    - packet length and sequence number to capture abnormal situation (cross checking between Linux and FPGA)
1924f977aa9SJiao Xianjun    - packet sending result: packet is sent successfully (FPGA receives ACK for this packet) or not. How many retransmissions are used for the packet sending (in case FPGA doesn't receive ACK in time, FPGA will do retransmission immediately)
19310d539beSJiao Xianjun  - send above information to upper layer (Linux mac80211 subsystem) via ieee80211_tx_status_irqsafe()
1942309afd4SJiao Xianjun
195da2a8350SJiao Xianjun## Regulation and channel config
1960273d862SJiao Xianjun
1970273d862SJiao XianjunSDR is a powerful tool for research. It is the user's duty to align with local spectrum regulation.
1980273d862SJiao Xianjun
1990273d862SJiao XianjunThis section explains how openwifi config the frequency/channel range and change it in real-time. After knowing the mechanism, you can try to extend frequency/channel by yourself.
2000273d862SJiao Xianjun
201da2a8350SJiao Xianjun### Frequency range
2020273d862SJiao Xianjun
2030273d862SJiao XianjunWhen openwifi driver is loaded, openwifi_dev_probe() will be executed. Following two lines configure the frequency range:
2040273d862SJiao Xianjun```
2050273d862SJiao Xianjundev->wiphy->regulatory_flags = xxx
2060273d862SJiao Xianjunwiphy_apply_custom_regulatory(dev->wiphy, &sdr_regd);
2070273d862SJiao Xianjun```
2080273d862SJiao Xianjunsdr_regd is the predefined variable in sdr.h. You can search the definition/meaning of its type: struct ieee80211_regdomain.
2090273d862SJiao XianjunThen not difficult to find out how to change the frequency range in SDR_2GHZ_CH01_14 and SDR_5GHZ_CH36_64.
2100273d862SJiao Xianjun
211da2a8350SJiao Xianjun### Supported channel
2120273d862SJiao Xianjun
2139d96e692SJiao XianjunThe supported channel list is defined in openwifi_2GHz_channels and openwifi_5GHz_channels in sdr.h. If you change the number of supported channels, make sure you also change the frequency range in sdr_regd accordingly and also array size of the following two fields in the struct openwifi_priv:
2140273d862SJiao Xianjun```
2150273d862SJiao Xianjunstruct ieee80211_channel channels_2GHz[14];
2160273d862SJiao Xianjunstruct ieee80211_channel channels_5GHz[11];
2170273d862SJiao Xianjun```
2180273d862SJiao XianjunFinally, the supported channel list is transferred to Linux mac80211 when openwifi driver is loaded by following two lines in openwifi_dev_probe():
2190273d862SJiao Xianjun```
2200273d862SJiao Xianjundev->wiphy->bands[NL80211_BAND_2GHZ] = &(priv->band_2GHz);
2210273d862SJiao Xianjundev->wiphy->bands[NL80211_BAND_5GHZ] = &(priv->band_5GHz);
2220273d862SJiao Xianjun```
2230273d862SJiao Xianjun
224da2a8350SJiao Xianjun### Real-time channel setting
2250273d862SJiao Xianjun
22688c09b72SJiao XianjunLinux mac80211 (struct ieee80211_ops openwifi_ops in sdr.c) uses the "config" API to configure channel frequency and some other parameters in real-time (such as during scanning or channel setting by iwconfig). It is hooked to openwifi_config() in sdr.c, and supports only frequency setting currently. The real execution of frequency setting falls to ad9361_rf_set_channel() via the "set_chan" field of struct openwifi_rf_ops ad9361_rf_ops in sdr.c. Besides tuning RF front-end (AD9361), the ad9361_rf_set_channel() also handles RSSI compensation for different frequencies and FPGA configurations (SIFS, etc) for different bands.
2270273d862SJiao Xianjun
228da2a8350SJiao Xianjun## Analog and digital frequency design
229da2a8350SJiao Xianjun
23095d09ab9SJiao XianjunFollowing figure shows the current openwifi analog and digital frequency design strategy. The Tx RF center frequency is tuned with 10MHz offset deliberately to ease Tx Lo leakage suppressed by Rx filter. This RF offset is pre-compensated by Tx DUC (Digital Up Converter) in FPGA (duc_bank_core.bd used by tx_intf.v). It combines AD9361's bandwidth, frequency, sampling rate and FPGA's digital down/up converter (ddc_bank_core.bd/duc_bank_core.bd) setting to achieve this example spectrum arrangement. Values in the figure are configurable in the openwifi design. Please be noticed that **ddc_bank_core.bd is not used anymore**. Because the digital and analog RX Lo is the same, mixer is not needed. Decimation by 2 is implemented in adc_intv.v.
231da2a8350SJiao Xianjun![](./rf-digital-if-chain-spectrum.jpg)
232da2a8350SJiao Xianjun
233da2a8350SJiao XianjunAbove spectrum setting has two benefits:
234da2a8350SJiao Xianjun- The Tx Lo leakage is suppressed by Rx filter
235da2a8350SJiao Xianjun- The centered Rx Lo and single channel Rx analog filter leads to more easy/accurate RSSI estimation in FPGA (together with real-time AD9361 AGC gain value accessed via FPGA GPIO)
236da2a8350SJiao Xianjun
2370168c125SJiao XianjunFollowing figure shows the detailed configuration point in AD9361, driver (sdr.c/tx_intf.c/rx_intf.c/ad9361.c/etc) and related FPGA modules.
2380168c125SJiao Xianjun![](./rf-digital-if-chain-config.jpg)
2390168c125SJiao Xianjun
240da2a8350SJiao Xianjun## Debug methods
2412309afd4SJiao Xianjun
2422309afd4SJiao Xianjun### dmesg
2432309afd4SJiao Xianjun
2444ecf49bbSJiao XianjunTo debug/see the basic driver behaviour, you could turn on message printing by
2454ecf49bbSJiao Xianjun```
2464ecf49bbSJiao XianjunSee all printing:
2474ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 3
2484ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 3
2494ecf49bbSJiao XianjunSee only error printing:
2504ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 1
2514ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 1
2524ecf49bbSJiao XianjunSee only regular printing:
2534ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 2
2544ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 2
2554ecf49bbSJiao XianjunTurn off printing:
2564ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 0
2574ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 0
2584ecf49bbSJiao Xianjun```
2594ecf49bbSJiao Xianjunand use dmesg command in Linux to see those messages. openwifi driver prints normal tx/rx packet information when a packet is sent or received. The driver also prints WARNING information if it feels something abnormal happens. You can search "printk" in sdr.c to see all the printing points.
2602309afd4SJiao Xianjun
2612309afd4SJiao Xianjun- tx printing example
2622309afd4SJiao Xianjun
2634ecf49bbSJiao Xianjun      sdr,sdr openwifi_tx:   84bytes 48M FC0208 DI002c addr1/2/3:b0481ada2ef2/66554433222a/66554433222a SC2100 flag40000012 retr6 ack1 prio2 q2 wr4 rd3
2642309afd4SJiao Xianjun  - printing from sdr driver, openwifi_tx function.
2654ecf49bbSJiao Xianjun  - 84bytes: packet size (length field in SIGNAL)
2664ecf49bbSJiao Xianjun  - 48M: MCS (rate field in SIGNAL)
2674ecf49bbSJiao Xianjun  - FC0208: Frame Control field, which means type data, subtype data, to DS 0, from DS 1 (a packet from AP to client).
2682309afd4SJiao Xianjun  - DI002c: Duration/ID field 0x002c. How many us this packet will occupy the channel (including waiting for ACK).
2694ecf49bbSJiao Xianjun  - addr1/2/3: address fields. Target MAC address b0481ada2ef2, source MAC address 66554433222a (openwifi).
2704ecf49bbSJiao Xianjun  - SC2100: Sequence Control field 0x2100, which means that the driver inserts sequence number 0x2100 to the packet under request of upper layer.
2712309afd4SJiao Xianjun  - flag40000012: flags field from upper layer struct ieee80211_tx_info (first fragment? need ACK? need sequence number insertion? etc.). Here is 0x40000012.
2724ecf49bbSJiao Xianjun  - retry6: upper layer tells us the maximum number of retransmissions for this packet is 6.
2732309afd4SJiao Xianjun  - ack1: upper layer tells us this packet needs ACK.
2744ecf49bbSJiao Xianjun  - prio2: Linux select priority queue 2 for this packet (0:VO voice, 1:VI video, 2:BE best effort and 3:BK background)
2754ecf49bbSJiao Xianjun  - q2: the packet goes to FPGA queue 2. (You can change the mapping between Linux priority and FPGA queue in sdr.c)
2764ecf49bbSJiao Xianjun  - wr4 rd3: the write/read index of buffer (shared buffer between the active openwifi_tx and background openwifi_tx_interrupt).
2772309afd4SJiao Xianjun
2782238b42bSweiliu- tx interrupt printing example
2792238b42bSweiliu```
2802238b42bSweiliusdr,sdr openwifi_tx_interrupt: tx_result 02 prio2 wr28 rd25 num_rand_slot 21 cw 6
2812238b42bSweiliu```
2822238b42bSweiliu  - printing from sdr driver, openwifi_tx_interrupt function.
283*b1dd94e3Sluz paz  - tx_result: 5 bit, lower 4 bit tells how many tx attempts are made on this packet, and the 5th bit indicates no ack (1) or an ack (0) is received
284*b1dd94e3Sluz paz  - prio, wr, rd: these fields can be interpreted the same way as the print in openwifi_tx function
2852238b42bSweiliu  - num_rand_slot: tells how many slots the CSMA/CA state machine waited until the packet is sent in the last tx attempt.
2862238b42bSweiliu  - cw: tells the exponent of the contention window. For this packet, the exponent 6 means the contention window size is 64. If the contention phase is never entered, the cw is set to 0.
2872238b42bSweiliu
2882309afd4SJiao Xianjun- rx printing example
2892309afd4SJiao Xianjun
2904ecf49bbSJiao Xianjun      sdr,sdr openwifi_rx_interrupt:  28bytes 24M FC0108 DI002c addr1/2/3:66554433222a/b0481ada2ef2/66554433222a SC4760 fcs1 buf_idx13 -30dBm
2912309afd4SJiao Xianjun  - printing from sdr driver, openwifi_rx_interrupt function.
2924ecf49bbSJiao Xianjun  - 28bytes: packet size (length field in SIGNAL)
2934ecf49bbSJiao Xianjun  - 24M:  MCS (rate field in SIGNAL)
2944ecf49bbSJiao Xianjun  - FC0108: Frame Control field 0x0108, which means type data, subtype data, to DS 1, from DS 0 (a packet client to openwifi AP).
2952309afd4SJiao Xianjun  - DI002c: Duration/ID field 0x002c. How many us this packet will occupy the channel (including waiting for ACK).
2964ecf49bbSJiao Xianjun  - addr1/2/3: address fields. Target MAC address 66554433222a (openwifi), source MAC address b0481ada2ef2.
2974ecf49bbSJiao Xianjun  - SC4760: Sequence Control field 0x4760, which means that the packet includes sequence number 0x4760 (under request of upper layer of the peer).
2984ecf49bbSJiao Xianjun  - fcs1: FCS/CRC is OK. (fcs0 means bad CRC)
2994ecf49bbSJiao Xianjun  - buf_idx13: current rx packet DMA buffer index 13.
3004ecf49bbSJiao Xianjun  - -30dBm: signal strength of this received packet.
3012309afd4SJiao Xianjun
302da2a8350SJiao Xianjun### Native Linux tools
3032309afd4SJiao Xianjun
3042309afd4SJiao XianjunFor protocol, many native Linux tools you still could rely on. Such as tcpdump.
3052309afd4SJiao Xianjun
3062309afd4SJiao Xianjun### FPGA
3072309afd4SJiao Xianjun
308*b1dd94e3Sluz pazFor FPGA itself, FPGA developer could use Xilinx ILA tools to analyze FPGA signals. Spying on those state machines in xpu/tx_intf/rx_intf would be very helpful for understanding/debugging Wi-Fi low level functionalities.
309