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---------|-------|---- 63c8b47d08SXianjun Jiaoslice_idx|the slice that will be set/get|0 to 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``` 75c8b47d08SXianjun Jiaomodule_name drv_rx/drv_tx/drv_xpu refers to the corresponding driver functionality. Related registers are defined in sdr.h. Search drv_rx_reg_val/drv_tx_reg_val/drv_xpu_reg_val in sdr.c to see their functionalities. 762ee67178SXianjun Jiao 77c8b47d08SXianjun Jiaomodule_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 and mapped to slv_regX in .v file (X is the register index). Check rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu.c and .v files to see their functionalities. 782ee67178SXianjun Jiao 79c8b47d08SXianjun JiaoPlease be aware that some registers are set by sdr.c in real-time (instructed by Linux mac80211), so be careful when set them manually. 80c8b47d08SXianjun Jiao 81c8b47d08SXianjun Jiaomodule_name: **drv_rx** (for full list, search drv_rx_reg_val in sdr.c) 822ee67178SXianjun Jiao 8362591d26Sweiliu1011reg_idx|meaning|comment 842ee67178SXianjun Jiao-------|-------|---- 852ee67178SXianjun 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 864ecf49bbSJiao Xianjun7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON) 872ee67178SXianjun Jiao 88404ff4e0SJiao 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) 89404ff4e0SJiao Xianjun 90*b5a0a70cSXianjun Jiaomodule_name: **drv_tx** (for full list, search drv_tx_reg_val in sdr.c) 912ee67178SXianjun Jiao 9262591d26Sweiliu1011reg_idx|meaning|comment 932ee67178SXianjun Jiao-------|-------|---- 942ee67178SXianjun 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 952ee67178SXianjun 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 964ecf49bbSJiao Xianjun7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON) 972ee67178SXianjun Jiao 98c8b47d08SXianjun Jiaomodule_name: **drv_xpu** (for full list, search drv_xpu_reg_val in sdr.c) 992ee67178SXianjun Jiao 10062591d26Sweiliu1011reg_idx|meaning|comment 1012ee67178SXianjun Jiao-------|-------|---- 102c8b47d08SXianjun Jiao7|git revision when build the driver|example: return value 0071bc74 means git revision is 071bc74 (the 1st 0 is always 0!) 1032ee67178SXianjun Jiao 104404ff4e0SJiao Xianjunmodule_name: **rf** 1052ee67178SXianjun Jiao 10662591d26Sweiliu1011reg_idx|meaning|comment 1072ee67178SXianjun Jiao-------|-------|---- 10862591d26Sweiliu1011x|x|to be defined 1092ee67178SXianjun Jiao 110c8b47d08SXianjun Jiaomodule_name: **rx_intf** (for full list, check rx_intf.c and **slv_reg** in rx_intf.v) 1112ee67178SXianjun Jiao 11262591d26Sweiliu1011reg_idx|meaning|comment 1132ee67178SXianjun Jiao-------|-------|---- 114c8b47d08SXianjun Jiao1|trigger for ILA debug|bit4 and bit0. Please check slv_reg1 in rx_intf.v 1152ee67178SXianjun Jiao2|enable/disable rx interrupt|256(0x100):disable, 0:enable 116c8b47d08SXianjun Jiao11|rx digital I/Q gain|number of bit shift to left. default 4 in rx_intf.c: rx_intf_api->RX_INTF_REG_BB_GAIN_write(4) 117c8b47d08SXianjun Jiao13|delay from RX DMA complete to RX packet interrupt|unit 0.1us 118c8b47d08SXianjun Jiao16|rx antenna selection|0:ant0, 1:ant1. default 0 in rx_intf.c: rx_intf_api->RX_INTF_REG_ANT_SEL_write(ant_sel) 1192ee67178SXianjun Jiao 120c8b47d08SXianjun Jiaomodule_name: **tx_intf** (for full list, check tx_intf.c and **slv_reg** in tx_intf.v) 1212ee67178SXianjun Jiao 12262591d26Sweiliu1011reg_idx|meaning|comment 1232ee67178SXianjun Jiao-------|-------|---- 124c8b47d08SXianjun Jiao1|DUC config|tx_intf_api->TX_INTF_REG_MIXER_CFG_write(mixer_cfg) in tx_intf.c and openwifi-hw/ip/mixer_duc/src/mixer_duc.cpp 125c8b47d08SXianjun Jiao4|CTS to Self config|auto set by cts_reg in openwifi_tx of sdr.c. bit31: enable/disable, bit30: rate selection: 1: use traffic rate, 0: manual rate in bit7-4, bit23-8: duration 126c8b47d08SXianjun Jiao6|CTS to Self sending delay (for SIFS)|unit 0.1us. bit13-0 for 2.4GHz, bit29-16 for 5GHz 127c8b47d08SXianjun Jiao11|threshold for FPGA fifo almost full|driver(sdr.c) read 1bit flag in slv_reg21 (4bit in total for 4 queue) to know the FPGA fifo/queue is almost full. 128c8b47d08SXianjun Jiao12|threshold to pause openofdm_tx|back pressure flow control for I/Q generation speed of openofdm_tx 129b73660adSXianjun Jiao13|tx I/Q digital gain before DUC|current optimal value: 100 130c8b47d08SXianjun Jiao14|enable/disable tx interrupt|196612(0x30004):disable, 4:enable 131c8b47d08SXianjun Jiao16|tx antenna selection|1:ant0, 2:ant1. default 1 in tx_intf.c: tx_intf_api->TX_INTF_REG_ANT_SEL_write(ant_sel) 132c8b47d08SXianjun Jiao21|queue almost full flag|4bit for 4 queue. criteria is the threshold in slv_reg11. check by tx_intf_api->TX_INTF_REG_S_AXIS_FIFO_NO_ROOM_read() in sdr.c 1332ee67178SXianjun Jiao 134c8b47d08SXianjun Jiaomodule_name: **rx** (for full list, check openofdm_rx.c and **slv_reg** in openofdm_rx.v) 1352ee67178SXianjun Jiao 13662591d26Sweiliu1011reg_idx|meaning|comment 1372ee67178SXianjun Jiao-------|-------|---- 138c8b47d08SXianjun Jiao2|power trigger threshold|default 0. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write(0) 139c8b47d08SXianjun Jiao3|minimum plateau used for short preamble detection|default 100. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_MIN_PLATEAU_write(100) 140c8b47d08SXianjun Jiao4|soft or hard decision for viterbi decoder|0:hard, 1:soft. default 1. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_SOFT_DECODING_write(1) 1412ee67178SXianjun Jiao20|history of PHY rx state|read only. If the last digit readback is always 3, it means the Viterbi decoder stops working 1422ee67178SXianjun Jiao 143c8b47d08SXianjun Jiaomodule_name: **tx** (for full list, check openofdm_tx.c and **slv_reg** in openofdm_tx.v) 1442ee67178SXianjun Jiao 14562591d26Sweiliu1011reg_idx|meaning|comment 1462ee67178SXianjun Jiao-------|-------|---- 1472ee67178SXianjun Jiao1|pilot scrambler initial state|lowest 7 bits are used. 0x7E by default in openofdm_tx.c 1482ee67178SXianjun Jiao2|data scrambler initial state|lowest 7 bits are used. 0x7F by default in openofdm_tx.c 1492ee67178SXianjun Jiao 150c8b47d08SXianjun Jiaomodule_name: **xpu** (for full list, check xpu.c and **slv_reg** in xpu.v) 1512ee67178SXianjun Jiao 15262591d26Sweiliu1011reg_idx|meaning|comment 1532ee67178SXianjun Jiao-------|-------|---- 154c8b47d08SXianjun Jiao1|mute rx I/Q when tx|0:mute when tx, 1:unmute, which means rx baseband will receive tx signal from its own. Rx packet and tx packet (such as ACK) can be monitored in FPGA for timing analysis 155c8b47d08SXianjun Jiao2|TSF timer low 32bit write|only write this register won't trigger the TSF timer reload. should use together with register for high 31bit 156c8b47d08SXianjun Jiao3|TSF timer high 31bit write|falling edge of MSB will trigger the TSF timer reload, which means write '1' then '0' to MSB 157c8b47d08SXianjun Jiao4|band, channel and ERP short slot setting|see enum/define in hw_def.h. set automatically by Linux. manual set will be overrided unless you change sdr.c 158c8b47d08SXianjun Jiao5|DIFS and backoff advance (us)|advance (us) for tx preparation before the end of DIFS/backoff. bit7-0:DIFS advance, bit15-8: backoff advance 159c8b47d08SXianjun Jiao6|forced idle, CSMA settings|bit7-0: forced channel idle (us) after decoding done to avoid false alarm caused by strong "AGC tail" signal. bit31: NAV enable, bit30: DIFS enable, bit29: EIFS enable, bit28: dynamic CW enable (when disable, CW is taken from bit3-0 of register 19) 160c8b47d08SXianjun Jiao7|some RSSI and delay setting|please check xpu.v (search slv_reg7) 161c8b47d08SXianjun Jiao8|RSSI threshold for channel idle/busy|set by ad9361_rf_set_channel --> xpu_api->XPU_REG_LBT_TH_write 162c8b47d08SXianjun Jiao9|some time setting|bit31 0:auto, 1:manual. When manual, bit6-0: PHY rx delay, bit13-7: SIFS, bit18-14: slot time, bit23-19: ofdm symbol time, bit30-24: preamble+SIG time. unit us. check xpu.v (search slv_reg9) 163c8b47d08SXianjun Jiao10|BB RF delay setting|bit7-0: BB RF delay (0.1us), bit11-8: RF end extended time (0.1us). check xpu.v (search slv_reg10) 164c8b47d08SXianjun Jiao11|ACK control and max num retransmission|bit4: 0:normal ACK, 1:disable auto ACK reply in FPGA. bit3-0: 0: the number of retransmission is decided by Linux, non-zero: Linux auto setting about num of retransmission will be replaced by this value 165c8b47d08SXianjun Jiao16|setting when wait for ACK in 2.4GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet 166c8b47d08SXianjun Jiao17|setting when wait for ACK in 5GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet 167c8b47d08SXianjun Jiao18|setting for sending ACK|unit 0.1us. bit14-0: ACK sending delay in 2.4GHz, bit30-16: ACK sending delay in 5GHz 168c8b47d08SXianjun Jiao19|CW min and max setting for 4 FPGA queues|bit3-0: CW min for queue 0, bit7-4: CW max for queue 0, bit11-8: CW min for queue 1, bit15-12: CW max for queue 1, bit19-16: CW min for queue 2, bit23-20: CW max for queue 2, bit27-24: CW min for queue 3, bit31-28: CW max for queue 3. automatically set by openwifi_conf_tx of sdr.c 169c8b47d08SXianjun Jiao26|CTS to RTS setting|bit15-0: extra duration, bit20-16: rate/MCS, bit31: 0:enable CTStoRTS 1:disable CTStoRTS 1700669334cSJiao 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) 171c8b47d08SXianjun Jiao28|BSSID address low 32bit for BSSID filtering|auto set by xpu_api->XPU_REG_BSSID_FILTER_LOW_write in openwifi_bss_info_changed of sdr.c 172c8b47d08SXianjun Jiao29|BSSID address high 32bit for BSSID filtering|auto set by xpu_api->XPU_REG_BSSID_FILTER_HIGH_write in openwifi_bss_info_changed of sdr.c 173c8b47d08SXianjun Jiao30|MAC address low 32bit|auto set by XPU_REG_MAC_ADDR_write in sdr.c 174c8b47d08SXianjun Jiao31|MAC address high 32bit|auto set by XPU_REG_MAC_ADDR_write in sdr.c 1752ee67178SXianjun Jiao58|TSF runtime value low 32bit|read only 1762ee67178SXianjun Jiao59|TSF runtime value high 32bit|read only 177c8b47d08SXianjun Jiao63|git revision when build the FPGA|example: return value 065272ac means git revision is 65272ac (the 1st 0 is always 0) 1785f436b3cSJiao Xianjun 179da2a8350SJiao Xianjun## Rx packet flow and filtering config 1805f436b3cSJiao Xianjun 181c8b47d08SXianjun JiaoAfter 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 serves the interrupt and gives the necessary information to upper layer (Linux mac80211 subsystem) via ieee80211_rx_irqsafe. 1825f436b3cSJiao Xianjun 18310d539beSJiao Xianjun- frame filtering 18410d539beSJiao Xianjun 185c8b47d08SXianjun 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, all received packets (including ACK) will be given to Linux mac80211. 18610d539beSJiao Xianjun 18710d539beSJiao Xianjun- main rx interrupt operations in openwifi_rx_interrupt() 1884f977aa9SJiao 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 18910d539beSJiao Xianjun - parse extra information inserted by FPGA in the DMA buffer 19010d539beSJiao Xianjun - TSF timer value 1914f977aa9SJiao Xianjun - raw RSSI value that will be converted to actual RSSI in dBm by different correction in different bands/channels 19210d539beSJiao Xianjun - packet length and MCS 19310d539beSJiao Xianjun - FCS is valid or not 19410d539beSJiao Xianjun - send packet content and necessary extra information to upper layer via ieee80211_rx_irqsafe() 1955f436b3cSJiao Xianjun 196da2a8350SJiao Xianjun## Tx packet flow and config 1975f436b3cSJiao Xianjun 19810d539beSJiao XianjunLinux mac80211 subsystem calls openwifi_tx() to initiate a packet sending. 19910d539beSJiao Xianjun 20010d539beSJiao Xianjun- main operations in openwifi_tx() 201c8b47d08SXianjun Jiao - get necessary information from the packet header (struct ieee80211_hdr) for future FPGA configuration 20210d539beSJiao Xianjun - packet length and MCS 2034f977aa9SJiao 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? 204c8b47d08SXianjun Jiao - which queue (time slice) in FPGA the packet should go? 20510d539beSJiao Xianjun - should RTS-CTS be used? (Send RTS and wait for CTS before actually send the data packet) 20610d539beSJiao 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;) 207c8b47d08SXianjun Jiao - should a sequence number be inserted? 2084f977aa9SJiao Xianjun - generate SIGNAL field according to length and MCS information. Insert it before the packet for the future openofdm_tx FPGA module use 209c8b47d08SXianjun Jiao - maintain sequence number (ring->bd_wr_idx) for internal use (cross check between Linux and FPGA) 210c8b47d08SXianjun Jiao - config FPGA register according to the above information to help FPGA do correct actions according to the packet specific requirement. 21110d539beSJiao 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) 21210d539beSJiao Xianjun 2134f977aa9SJiao 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(). 21410d539beSJiao Xianjun 21510d539beSJiao Xianjun- main operations in openwifi_tx_interrupt() 2164f977aa9SJiao Xianjun - get necessary information/status of the packet just sent by FPGA 2174f977aa9SJiao Xianjun - packet length and sequence number to capture abnormal situation (cross checking between Linux and FPGA) 218c8b47d08SXianjun Jiao - packet sending result: packet is sent successfully (FPGA receives ACK for this packet) or not. How many retransmissions have been done (in case FPGA doesn't receive ACK in time, FPGA will do retransmission according to CSMA/CA low MAC state) 21910d539beSJiao Xianjun - send above information to upper layer (Linux mac80211 subsystem) via ieee80211_tx_status_irqsafe() 2202309afd4SJiao Xianjun 221da2a8350SJiao Xianjun## Regulation and channel config 2220273d862SJiao Xianjun 223c8b47d08SXianjun JiaoSDR is a powerful tool for research. It is the user's responsibility to align with local spectrum regulation. 2240273d862SJiao Xianjun 2250273d862SJiao 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. 2260273d862SJiao Xianjun 227da2a8350SJiao Xianjun### Frequency range 2280273d862SJiao Xianjun 2290273d862SJiao XianjunWhen openwifi driver is loaded, openwifi_dev_probe() will be executed. Following two lines configure the frequency range: 2300273d862SJiao Xianjun``` 2310273d862SJiao Xianjundev->wiphy->regulatory_flags = xxx 2320273d862SJiao Xianjunwiphy_apply_custom_regulatory(dev->wiphy, &sdr_regd); 2330273d862SJiao Xianjun``` 2340273d862SJiao Xianjunsdr_regd is the predefined variable in sdr.h. You can search the definition/meaning of its type: struct ieee80211_regdomain. 235c8b47d08SXianjun JiaoThen it is not difficult to find out how to change the frequency range in SDR_2GHZ_CH01_14 and SDR_5GHZ_CH36_64. 2360273d862SJiao Xianjun 237da2a8350SJiao Xianjun### Supported channel 2380273d862SJiao Xianjun 2399d96e692SJiao 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: 2400273d862SJiao Xianjun``` 2410273d862SJiao Xianjunstruct ieee80211_channel channels_2GHz[14]; 2420273d862SJiao Xianjunstruct ieee80211_channel channels_5GHz[11]; 2430273d862SJiao Xianjun``` 2440273d862SJiao XianjunFinally, the supported channel list is transferred to Linux mac80211 when openwifi driver is loaded by following two lines in openwifi_dev_probe(): 2450273d862SJiao Xianjun``` 2460273d862SJiao Xianjundev->wiphy->bands[NL80211_BAND_2GHZ] = &(priv->band_2GHz); 2470273d862SJiao Xianjundev->wiphy->bands[NL80211_BAND_5GHZ] = &(priv->band_5GHz); 2480273d862SJiao Xianjun``` 2490273d862SJiao Xianjun 250da2a8350SJiao Xianjun### Real-time channel setting 2510273d862SJiao Xianjun 25288c09b72SJiao 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. 2530273d862SJiao Xianjun 254da2a8350SJiao Xianjun## Analog and digital frequency design 255da2a8350SJiao Xianjun 256c8b47d08SXianjun JiaoFollowing 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 up converter (duc_bank_core.bd) setting to achieve this example spectrum arrangement. Values in the figure are configurable in the openwifi design. 257da2a8350SJiao Xianjun 258da2a8350SJiao Xianjun 259da2a8350SJiao XianjunAbove spectrum setting has two benefits: 260da2a8350SJiao Xianjun- The Tx Lo leakage is suppressed by Rx filter 261c8b47d08SXianjun Jiao- The centered Rx Lo leads to more easy/accurate RSSI estimation in FPGA (together with real-time AD9361 AGC gain value accessed via FPGA GPIO) 262da2a8350SJiao Xianjun 263c8b47d08SXianjun JiaoFollowing figure shows the detailed configuration point in AD9361, driver (.c file) and related FPGA modules (.v file). 2640168c125SJiao Xianjun 2650168c125SJiao Xianjun 266da2a8350SJiao Xianjun## Debug methods 2672309afd4SJiao Xianjun 2682309afd4SJiao Xianjun### dmesg 2692309afd4SJiao Xianjun 270c8b47d08SXianjun JiaoTo debug/see the basic driver behaviour, you could turn on **dmesg** message printing by 2714ecf49bbSJiao Xianjun``` 2724ecf49bbSJiao XianjunSee all printing: 2734ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 3 2744ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 3 2754ecf49bbSJiao XianjunSee only error printing: 2764ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 1 2774ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 1 2784ecf49bbSJiao XianjunSee only regular printing: 2794ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 2 2804ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 2 2814ecf49bbSJiao XianjunTurn off printing: 2824ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_tx 7 0 2834ecf49bbSJiao Xianjun./sdrctl dev sdr0 set reg drv_rx 7 0 2844ecf49bbSJiao Xianjun``` 285c8b47d08SXianjun Jiaoand use **dmesg** command in Linux to see those messages. Regular printing includes tx/rx packet information when a packet is sent or received. Error printing has WARNING information if something abnormal happens. You can search "printk" in sdr.c to see all the printing points. 2862309afd4SJiao Xianjun 287c8b47d08SXianjun Jiao### tx printing example 288c8b47d08SXianjun Jiao``` 289c8b47d08SXianjun Jiaosdr,sdr openwifi_tx: 1410bytes ht0 540M FC0208 DI002c addr1/2/3:2ec08902fdb2/6655443322ad/6655443322ad SC2100 flag40000012 retr6 ack1 prio2 q2 wr44 rd31 290c8b47d08SXianjun Jiao``` 291c8b47d08SXianjun Jiao- printing from sdr driver, openwifi_tx function 292c8b47d08SXianjun Jiao- 1410bytes: packet size (length field in SIGNAL) 293c8b47d08SXianjun Jiao- ht0: non-ht means 11a/g; ht1 means 11n 294c8b47d08SXianjun Jiao- 54M: MCS (rate field in SIGNAL) 295c8b47d08SXianjun Jiao- FC0208: Frame Control field, which means type data, subtype data, to DS 0, from DS 1 (a packet from AP to client) 296c8b47d08SXianjun Jiao- DI002c: Duration/ID field 0x002c. How many us this packet will occupy the channel (including waiting for ACK) 297c8b47d08SXianjun Jiao- addr1/2/3: address fields. Target MAC address 2ec08902fdb2, source MAC address 6655443322ad (openwifi) 298c8b47d08SXianjun Jiao- SC2100: Sequence Control, which means that the driver inserts sequence number 0x2100 to the packet under request of Linux mac80211 299c8b47d08SXianjun Jiao- flag40000012: flags field from Linux mac80211 struct ieee80211_tx_info (first fragment? need ACK? need sequence number insertion? etc.) 300c8b47d08SXianjun Jiao- retry6: Linux mac80211 tells driver the maximum number of transmissions for this packet is 6 301c8b47d08SXianjun Jiao- ack1: Linux mac80211 tells driver this packet needs ACK 3024ecf49bbSJiao Xianjun- prio2: Linux select priority queue 2 for this packet (0:VO voice, 1:VI video, 2:BE best effort and 3:BK background) 3034ecf49bbSJiao Xianjun- q2: the packet goes to FPGA queue 2. (You can change the mapping between Linux priority and FPGA queue in sdr.c) 304c8b47d08SXianjun Jiao- wr44 rd31: the write/read index of buffer (shared buffer between the active openwifi_tx and background openwifi_tx_interrupt/FPGA) 3052309afd4SJiao Xianjun 306c8b47d08SXianjun Jiao### tx interrupt printing example 3072238b42bSweiliu``` 3082238b42bSweiliusdr,sdr openwifi_tx_interrupt: tx_result 02 prio2 wr28 rd25 num_rand_slot 21 cw 6 3092238b42bSweiliu``` 310c8b47d08SXianjun Jiao- printing from sdr driver, openwifi_tx_interrupt function 311c8b47d08SXianjun Jiao- tx_result: 5bit, bit3~0 tells how many tx attempts are made on this packet, and bit4 indicates NO ACK (1) or an ACK (0) is received 312b1dd94e3Sluz paz- prio, wr, rd: these fields can be interpreted the same way as the print in openwifi_tx function 313c8b47d08SXianjun Jiao- num_rand_slot: tells how many slots the CSMA/CA state machine waited until the packet is sent in the last tx attempt 314c8b47d08SXianjun Jiao- cw: the exponent of the Contention Window for this packet. 6 means the CW size 64. If the contention phase is never entered, CW is 0 3152238b42bSweiliu 316c8b47d08SXianjun Jiao### rx printing example 317c8b47d08SXianjun Jiao``` 318c8b47d08SXianjun Jiaosdr,sdr openwifi_rx_interrupt: 796bytes ht0 120M FC0108 DI0030 addr1/2/3:6655443322f4/2ec08902fdb2/6655443322f4 SC4760 fcs1 buf_idx13 -50dBm 319c8b47d08SXianjun Jiao``` 320c8b47d08SXianjun Jiao- printing from sdr driver, openwifi_rx_interrupt function 321c8b47d08SXianjun Jiao- 796bytes: packet size (length field in SIGNAL) 322c8b47d08SXianjun Jiao- ht0: non-ht means 11a/g; ht1 means 11n 323c8b47d08SXianjun Jiao- 12M: MCS (rate field in SIGNAL) 324c8b47d08SXianjun Jiao- FC0108: Frame Control field 0x0108, which means type data, subtype data, to DS 1, from DS 0 (a packet client to openwifi AP) 325c8b47d08SXianjun Jiao- DI0030: Duration/ID field 0x0030. How many us this packet will occupy the channel (including waiting for ACK) 326c8b47d08SXianjun Jiao- addr1/2/3: address fields. Target MAC address 6655443322f4 (openwifi), source MAC address 2ec08902fdb2 327c8b47d08SXianjun Jiao- SC4760: Sequence Control, which means that the packet includes sequence number 0x4760 (under request of upper layer of the peer) 3284ecf49bbSJiao Xianjun- fcs1: FCS/CRC is OK. (fcs0 means bad CRC) 329c8b47d08SXianjun Jiao- buf_idx13: current rx packet DMA buffer index 13 330c8b47d08SXianjun Jiao- -50dBm: signal strength of this received packet (after calibration) 3312309afd4SJiao Xianjun 332da2a8350SJiao Xianjun### Native Linux tools 3332309afd4SJiao Xianjun 334c8b47d08SXianjun JiaoFor analysis/debug, many native Linux tools you still could rely on. Such as tcpdump, tshark, etc. 3352309afd4SJiao Xianjun 3362309afd4SJiao Xianjun### FPGA 3372309afd4SJiao Xianjun 338b1dd94e3Sluz 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. 339