Linux UWB Stack实现——MCPS接口

本专栏主要介绍在Linux内核中的UWB Stack的实现,整体基于IEEE 802.15.4框架,采用Qorvo UWB芯片DW3000,开源协议版本为GPLv2。
在本篇文章中,主要介绍MCPS接口的定义,MCPS(MAC Common Part Sublayer,MAC公共部分子层)。

关于mcps802154.h

为MCPS接口相关定义,主要包括一些一些结构体的定义,主要包括底层驱动的连接,收发数据帧等,相关结构体定义如下:

  • struct mcps802154_llhw,不带MCPS的底层硬件,必须使用mcps802154_alloc_llhw()函数进行分配,然后底层驱动程序应对其进行初始化。
  • struct mcps802154_tx_frame_info,用于传输帧的信息。
  • struct mcps802154_rx_info ,使能接收机的信息。
  • struct mcps802154_rx_frame_info,接收到数据帧的信息。
  • struct mcps802154_sts_params,HPR UWB的STS参数。
  • struct mcps802154_ops,MCPS从底层驱动程序的回调函数。

mcps802154_llhw

struct mcps802154_llhw {
	/**
	 * @dtu_freq_hz: Inverse of device time unit duration, in Hz.
	 */
	int dtu_freq_hz;
	/**
	 * @symbol_dtu: Symbol duration in device time unit, can change if radio
	 * parameters are changed. Can be set to 1 if device time unit is the
	 * symbol.
	 */
	int symbol_dtu;
	/**
	 * @cca_dtu: CCA duration in device time unit, can change if radio
	 * parameters or CCA modes are changed.
	 */
	int cca_dtu;
	/**
	 * @shr_dtu: Synchronisation header duration in device time unit, can
	 * change if radio parameters are changed. If ranging is supported, this
	 * is the difference between the RMARKER and the first frame symbol.
	 */
	int shr_dtu;
	/**
	 * @dtu_rctu: Duration of one device time unit in ranging counter time
	 * unit (RDEV only).
	 */
	int dtu_rctu;
	/**
	 * @rstu_dtu: Duration of ranging slot time unit in device time unit
	 * (ERDEV only).
	 */
	int rstu_dtu;
	/**
	 * @anticip_dtu: Reasonable delay between reading the current timestamp
	 * and doing an operation in device time unit.
	 */
	int anticip_dtu;
	/**
	 * @idle_dtu: Duration long enough to prefer entering the idle mode
	 * rather than trying to find a valid access.
	 */
	int idle_dtu;
	/**
	 * @flags: Low-level hardware flags, see &enum mcps802154_llhw_flags.
	 */
	u32 flags;
	/**
	 * @hw: Pointer to IEEE802154 hardware exposed by MCPS. The low-level
	 * driver needs to update this and hw->phy according to supported
	 * hardware features and radio parameters. More specifically:
	 *
	 * * &ieee802154_hw.extra_tx_headroom
	 * * in &ieee802154_hw.flags:
	 *
	 *     * IEEE802154_HW_TX_OMIT_CKSUM
	 *     * IEEE802154_HW_RX_OMIT_CKSUM
	 *     * IEEE802154_HW_RX_DROP_BAD_CKSUM
	 *
	 * * &wpan_phy.flags
	 * * &wpan_phy_supported
	 * * &wpan_phy.symbol_duration
	 */
	struct ieee802154_hw *hw;
	/**
	 * @priv: Driver private data.
	 */
	void *priv;
};

mcps802154_tx_frame_info

enum mcps802154_tx_frame_info_flags {
	MCPS802154_TX_FRAME_TIMESTAMP_DTU = BIT(0),
	MCPS802154_TX_FRAME_CCA = BIT(1),
	MCPS802154_TX_FRAME_RANGING = BIT(2),
	MCPS802154_TX_FRAME_KEEP_RANGING_CLOCK = BIT(3),
	MCPS802154_TX_FRAME_SP1 = BIT(4),
	MCPS802154_TX_FRAME_SP2 = BIT(5),
	MCPS802154_TX_FRAME_SP3 = BIT(4) | BIT(5),
	MCPS802154_TX_FRAME_STS_MODE_MASK = BIT(4) | BIT(5),
};

struct mcps802154_tx_frame_info {
	/**
	 * @timestamp_dtu: If timestamped, date of transmission start.
	 */
	u32 timestamp_dtu;
	/**
	 * @rx_enable_after_tx_dtu: If positive, enable receiver this number of
	 * device time unit after the end of the transmitted frame.
	 */
	int rx_enable_after_tx_dtu;
	/**
	 * @rx_enable_after_tx_timeout_dtu: When receiver is enabled after the
	 * end of the transmitted frame: if negative, no timeout, if zero, use
	 * a default timeout value, else this is the timeout value in device
	 * time unit.
	 */
	int rx_enable_after_tx_timeout_dtu;
	/**
	 * @flags: See &enum mcps802154_tx_frame_info_flags.
	 */
	u8 flags;
	/**
	 * @ant_id: antenna index to use for transmit.
	 */
	int ant_id;
};

mcps802154_rx_info

enum mcps802154_rx_info_flags {
	MCPS802154_RX_INFO_TIMESTAMP_DTU = BIT(0),
	MCPS802154_RX_INFO_AACK = BIT(1),
	MCPS802154_RX_INFO_RANGING = BIT(2),
	MCPS802154_RX_INFO_KEEP_RANGING_CLOCK = BIT(3),
	MCPS802154_RX_INFO_SP1 = BIT(4),
	MCPS802154_RX_INFO_SP2 = BIT(5),
	MCPS802154_RX_INFO_SP3 = BIT(4) | BIT(5),
	MCPS802154_RX_INFO_STS_MODE_MASK = BIT(4) | BIT(5),
};

struct mcps802154_rx_info {
	/**
	 * @timestamp_dtu: If timestamped, date to enable the receiver.
	 */
	u32 timestamp_dtu;
	/**
	 * @timeout_dtu: 负数,无超时;0,默认超时;正数为设定的超时时间
	 */
	int timeout_dtu;
	/**
	 * @flags: See &enum mcps802154_rx_info_flags.
	 */
	u8 flags;
	/**
	 * @ant_pair_id: 用于接收的天线配对索引
	 */
	u8 ant_pair_id;
};

mcps802154_rx_frame_info

接收帧信息相关。
接收帧信息标志包括测距时间戳、LQI、RSSI、测距FOM、PDOA、STS等相关的接收帧标志。

  • RCTU(Ranging Count Time Unit,测距计数单元),用于测距应用,基础时间单位约为15 ps,仅支持测距的设备支持。
  • DTU,Device Time Unit,设备时钟单元。
enum mcps802154_rx_frame_info_flags {
	MCPS802154_RX_FRAME_INFO_TIMESTAMP_DTU = BIT(0),
	MCPS802154_RX_FRAME_INFO_TIMESTAMP_RCTU = BIT(1),
	MCPS802154_RX_FRAME_INFO_LQI = BIT(2),
	MCPS802154_RX_FRAME_INFO_RSSI = BIT(3),
	MCPS802154_RX_FRAME_INFO_RANGING_FOM = BIT(4),
	MCPS802154_RX_FRAME_INFO_RANGING_OFFSET = BIT(5),
	MCPS802154_RX_FRAME_INFO_RANGING_PDOA = BIT(6),
	MCPS802154_RX_FRAME_INFO_RANGING_PDOA_FOM = BIT(7),
	MCPS802154_RX_FRAME_INFO_RANGING_STS_TIMESTAMP_RCTU = BIT(8),
	MCPS802154_RX_FRAME_INFO_RANGING_STS_FOM = BIT(9),
	MCPS802154_RX_FRAME_INFO_AACK = BIT(10),
};

struct mcps802154_rx_frame_info {
	/**
	 * @timestamp_dtu: Timestamp of start of frame in device time unit.
	 */
	u32 timestamp_dtu;
	/**
	 * @timestamp_rctu: Timestamp of RMARKER in ranging count time unit
	 * (RDEV only).
	 */
	u64 timestamp_rctu;
	/**
	 * @frame_duration_dtu: Duration of the whole frame in device time unit
	 * or 0 if unknown.
	 */
	int frame_duration_dtu;

	int rssi;
	/**
	 * @ranging_tracking_interval_rctu: Interval on which tracking offset
	 * was measured (RDEV only).
	 */
	int ranging_tracking_interval_rctu;
	/**
	 * @ranging_offset_rctu: Difference between the transmitter and the
	 * receiver clock measure over the tracking interval, if positive, the
	 * transmitter operates at a higher frequency (RDEV only).
	 */
	int ranging_offset_rctu;
	/**
	 * @ranging_pdoa_rad_q11: Phase difference of arrival, unit is radian
	 * multiplied by 2048 (RDEV only).
	 */
	int ranging_pdoa_rad_q11;
	/**
	 * @ranging_pdoa_spacing_mm_q11: Spacing between antennas, unit is mm
	 * multiplied by 2048 (RDEV only).
	 */
	int ranging_pdoa_spacing_mm_q11;
	/**
	 * @ranging_sts_timestamp_diffs_rctu: For each SRMARKERx, difference
	 * between the measured timestamp and the expected timestamp relative to
	 * RMARKER in ranging count time unit (ERDEV only). When STS mode is
	 * 1 or 3, SRMARKER0 is the same as RMARKER and difference is always 0.
	 */
	s16 ranging_sts_timestamp_diffs_rctu[MCPS802154_STS_N_SEGS_MAX + 1];
	/**
	 * @lqi: Link quality indicator (LQI).
	 */
	u8 lqi;
	/**
	 * @ranging_fom: Ranging figure of merit (FoM, RDEV only). Should be
	 * formatted according to 802.15.4.
	 */
	u8 ranging_fom;
	/**
	 * @ranging_pdoa_fom: Phase difference of arrival figure of merit (FoM,
	 * RDEV only). Range is 0 to 255, with 0 being an invalid measure and
	 * 255 being a 100% confidence.
	 */
	u8 ranging_pdoa_fom;
	/**
	 * @ranging_sts_fom: Table of figures of merit measuring the correlation
	 * strength between the received STS segment and the expected one (FoM,
	 * ERDEV only). Range is 0 to 255, with 0 being an invalid measure and
	 * 255 being a 100% confidence.
	 */
	u8 ranging_sts_fom[MCPS802154_STS_N_SEGS_MAX];
	/**
	 * @flags: See &enum mcps802154_rx_frame_info_flags.
	 */
	u16 flags;
};

mcps802154_sts_params

HRP UWB的STS参数,包括用在DRBG中生成STS的Value与key,以及STS段的数量以及每个段内STS的长度(FiRa、CCC的标准中通常使用1个STS段,长度为64个Symbol)。
另外,针对SP2模式帧格式,定义了STS与payload之间的附加gap信息。

struct mcps802154_sts_params {
	/**
	 * @v: Value V used in DRBG for generating the STS. The 32 LSB are the
	 * VCounter which is incremented every 128 generated pulse.
	 */
	u8 v[AES_BLOCK_SIZE];
	/**
	 * @key: STS AES key used in DRBG for generating the STS.
	 */
	u8 key[AES_KEYSIZE_128];

	int n_segs;

	int seg_len;
	/**
	 * @sp2_tx_gap_4chips: For SP2 frame format, additional gap in unit of
	 * 4 chips between the end of the payload and the start of the STS, used
	 * for TX.
	 */
	int sp2_tx_gap_4chips;
	/**
	 * @sp2_rx_gap_4chips: For SP2 frame format, additional gap in unit of
	 * 4 chips between the end of the payload and the start of the STS, used
	 * for RX. A0 and A1 bits in PHR are used to index the array.
	 */
	int sp2_rx_gap_4chips[MCPS802154_STS_N_SEGS_MAX];
};

mcps802154_ops

定义了底层驱动相关的实现接口回调,包括初始化底层设备、停止、发送、接收等常规操作接口。

struct mcps802154_ops {
	/**
	 * @start: Initialize device. Reception should not be activated.
	 */
	int (*start)(struct mcps802154_llhw *llhw);
	/**
	 * @stop: Stop device. Should stop any transmission or reception and put
	 * the device in a low power mode.
	 */
	void (*stop)(struct mcps802154_llhw *llhw);
	/**
	 * @tx_frame: Transmit a frame. skb应包含从IEEE 802.15.4帧头开始的数据。底层驱动将根据设定发送帧信息发送。接收机应在没有收到帧的情况下自动关闭。
	 *
	 * @next_delay_dtu : 表示预期发送帧开始和下一动作之间的延迟时间
	 *
	 */
	int (*tx_frame)(struct mcps802154_llhw *llhw, struct sk_buff *skb,
			const struct mcps802154_tx_frame_info *info,
			int next_delay_dtu);
	/**
	 * @rx_enable: 使能接收机。
	 * @next_delay_dtu: 表示预期从开始接受帧或帧接收超时之间的时间。
	 */
	int (*rx_enable)(struct mcps802154_llhw *llhw,
			 const struct mcps802154_rx_info *info,
			 int next_delay_dtu);
	/**
	 * @rx_disable: Disable receiver
	 */
	int (*rx_disable)(struct mcps802154_llhw *llhw);
	/**
	 * @rx_get_frame: Get previously received frame. MCPS calls this handler
	 * after a frame reception has been signaled by the low-level driver.
	 *
	 * The received buffer is owned by MCPS after this call. Only the
	 * requested information need to be filled in the information structure.
	 *
	 */
	int (*rx_get_frame)(struct mcps802154_llhw *llhw, struct sk_buff **skb,
			    struct mcps802154_rx_frame_info *info);
	/**
	 * @rx_get_error_frame: Get information on rejected frame. MCPS can call
	 * this handler after a frame rejection has been signaled by the
	 * low-level driver.
	 */
	int (*rx_get_error_frame)(struct mcps802154_llhw *llhw,
				  struct mcps802154_rx_frame_info *info);
	/**
	 * @idle: Put the device into idle mode without time limit or until the
	 * given timestamp.  The driver should call &mcps802154_timer_expired()
	 * before the given timestamp so that an action can be programmed at the
	 * given timestamp.
	 *
	 * The &mcps802154_timer_expired() function must not be called
	 * immediately from this callback, but should be scheduled to be called
	 * later.
	 *
	 * If the driver is late, the regular handling of late actions will take
	 * care of the situation.
	 */
	int (*idle)(struct mcps802154_llhw *llhw, bool timestamp,
		    u32 timestamp_dtu);
	/**
	 * @reset: Reset device after an unrecoverable error.
	 */
	int (*reset)(struct mcps802154_llhw *llhw);
	/**
	 * @get_current_timestamp_dtu: Get current timestamp in device time
	 * unit.
	 *
	 * If the device is currently in a low power state, the eventual wake up
	 * delay should be added to the returned timestamp.
	 *
	 * If the current timestamp can not be determined precisely, it should
	 * return a pessimistic value, i.e. rounded up.
	 */
	int (*get_current_timestamp_dtu)(struct mcps802154_llhw *llhw,
					 u32 *timestamp_dtu);
	/**
	 * @timestamp_dtu_to_rctu: Convert a timestamp in device time unit to
	 * a timestamp in ranging counter time unit.
	 */
	u64 (*timestamp_dtu_to_rctu)(struct mcps802154_llhw *llhw,
				     u32 timestamp_dtu);
	/**
	 * @timestamp_rctu_to_dtu: Convert a timestamp in ranging counter time
	 * unit to a timestamp in device time unit.
	 */
	u32 (*timestamp_rctu_to_dtu)(struct mcps802154_llhw *llhw,
				     u64 timestamp_rctu);
	/**
	 * @tx_timestamp_dtu_to_rmarker_rctu: Compute the RMARKER timestamp in
	 * ranging counter time unit for a frame transmitted at given timestamp
	 * in device time unit (RDEV only).
	 *
	 * Return: The RMARKER timestamp.
	 */
	u64 (*tx_timestamp_dtu_to_rmarker_rctu)(struct mcps802154_llhw *llhw,
						u32 tx_timestamp_dtu,
						int ant_id);
	/**
	 * @difference_timestamp_rctu: Compute the difference between two
	 * timestamp values.
	 *
	 * Return: The difference between A and B.
	 */
	s64 (*difference_timestamp_rctu)(struct mcps802154_llhw *llhw,
					 u64 timestamp_a_rctu,
					 u64 timestamp_b_rctu);
	/**
	 * @compute_frame_duration_dtu: Compute the duration of a frame with
	 * given payload length (header and checksum included) using the current
	 * radio parameters.
	 *
	 * Return: The duration in device time unit.
	 */
	int (*compute_frame_duration_dtu)(struct mcps802154_llhw *llhw,
					  int payload_bytes);
	/**
	 * @set_channel: Set channel parameters.
	 */
	int (*set_channel)(struct mcps802154_llhw *llhw, u8 page, u8 channel,
			   u8 preamble_code);
	/**
	 * @set_hrp_uwb_params: Set radio parameters for HRP UWB.
	 *
	 * The parameters in &mcps802154_llhw can change according to radio
	 * parameters.
	 */
	int (*set_hrp_uwb_params)(struct mcps802154_llhw *llhw, int prf,
				  int psr, int sfd_selector, int phr_rate,
				  int data_rate);
	/**
	 * @set_sts_params: Set STS parameters (ERDEV only).
	 */
	int (*set_sts_params)(struct mcps802154_llhw *llhw,
			      const struct mcps802154_sts_params *params);
	/**
	 * @set_hw_addr_filt: Set hardware filter parameters.
	 */
	int (*set_hw_addr_filt)(struct mcps802154_llhw *llhw,
				struct ieee802154_hw_addr_filt *filt,
				unsigned long changed);
	/**
	 * @set_txpower: Set transmission power.
	 */
	int (*set_txpower)(struct mcps802154_llhw *llhw, s32 mbm);
	/**
	 * @set_cca_mode: Set CCA mode.
	 *
	 * The CCA duration in &mcps802154_llhw can change according to CCA
	 * mode.
	 */
	int (*set_cca_mode)(struct mcps802154_llhw *llhw,
			    const struct wpan_phy_cca *cca);
	/**
	 * @set_cca_ed_level: Set CCA energy detection threshold.
	 */
	int (*set_cca_ed_level)(struct mcps802154_llhw *llhw, s32 mbm);
	/**
	 * @set_promiscuous_mode: Set promiscuous mode.
	 */
	int (*set_promiscuous_mode)(struct mcps802154_llhw *llhw, bool on);
	/**
	 * @set_scanning_mode: Set SW scanning mode.
	 */
	int (*set_scanning_mode)(struct mcps802154_llhw *llhw, bool on);
	/**
	 * @set_calibration: Set calibration value.
	 *
	 * Set the calibration parameter specified by the key string with the
	 * value specified in the provided buffer. The provided length must
	 * match the length returned by the @get_calibration() callback.
	 */
	int (*set_calibration)(struct mcps802154_llhw *llhw, const char *key,
			       void *value, size_t length);
	/**
	 * @get_calibration: Get calibration value.
	 *
	 * Get the calibration parameter specified by the key string into the
	 * provided buffer.
	 *
	 * Return: size of parameter written in buffer or error.
	 */
	int (*get_calibration)(struct mcps802154_llhw *llhw, const char *key,
			       void *value, size_t length);
	/**
	 * @list_calibration: Returns list of accepted calibration key strings.
	 */
	const char *const *(*list_calibration)(struct mcps802154_llhw *llhw);
	/**
	 * @vendor_cmd: 运行一个供应商特定命令。Run a vendor specific command.
	 */
	int (*vendor_cmd)(struct mcps802154_llhw *llhw, u32 vendor_id,
			  u32 subcmd, void *data, size_t data_len);
#ifdef CONFIG_MCPS802154_TESTMODE
	/**
	 * @testmode_cmd: Run a testmode command.
	 */
	int (*testmode_cmd)(struct mcps802154_llhw *llhw, void *data, int len);
#endif
};

你可能感兴趣的:(Linux,UWB,Stack,UWB技术,智能硬件,物联网,linux)