• Linux UWB Stack实现——MCPS帧处理


    MCPS帧处理

    用于处理IEEE 802.15.4中的相关帧,Frame Processing,简写为:fproc。

    在实现中,维护了关于帧处理的有限状态机(FSM)。本文从帧处理的数据结构和部分典型处理实现上进行简要的介绍。

    1. 数据结构定义

    关于帧处理状态机相关的事件回调定义为struct mcps802154_fproc_state,用于处理从活跃状态的转换。

    struct mcps802154_fproc_state {
    	/** @name: State name. */
    	const char *name;
    	/** @enter: Run when the state is entered. */
    	void (*enter)(struct mcps802154_local *local);
    	/** @leave: Run when the state is left. */
    	void (*leave)(struct mcps802154_local *local);
    	/** @rx_frame: Handle frame reception. */
    	void (*rx_frame)(struct mcps802154_local *local);
    	/** @rx_timeout: Handle reception timeout. */
    	void (*rx_timeout)(struct mcps802154_local *local);
    	/** @rx_error: Handle reception error. */
    	void (*rx_error)(struct mcps802154_local *local,
    			 enum mcps802154_rx_error_type error);
    	/** @tx_done: Handle end of transmission. */
    	void (*tx_done)(struct mcps802154_local *local);
    	/** @broken: Handle unrecoverable error. */
    	void (*broken)(struct mcps802154_local *local);
    	/** @timer_expired: Handle timer expiration. */
    	void (*timer_expired)(struct mcps802154_local *local);
    	/** @schedule_change: Handle schedule change. */
    	void (*schedule_change)(struct mcps802154_local *local);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    主要包括了entered、left、rx_frame、rx_timeout、rx_error、tx_done、broken、timer_expired、schedule_change几个状态,通过该结构体定义了相关状态切换对应的回调函数。

    在MCPS的私有数据struct mcps802154_local中,定义了帧处理的私有数据,通过结构体struct mcps802154_fproc实现。

    struct mcps802154_fproc {
    	/** 指向当前状态的指针 */
    	const struct mcps802154_fproc_state *state;
    	/** 指向正在处理中访问的指针 */
    	struct mcps802154_access *access;
    	/** 发送帧的buffer指针 */
    	struct sk_buff *tx_skb;
    	/** 多帧方法下的帧索引 */
    	size_t frame_idx;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    由于fproc的相关处理大多会涉及到MCPS私有数据的访问,因此在文件中通过对结构体进行声明struct mcps802154_local(未直接引用头文件的方式)。
    帧处理相关操作包括:

    • mcps802154_fproc_init,初始化;
    • mcps802154_fproc_uninit,去初始化;
    • mcps802154_fproc_change_state,更换活跃状态;
    • mcps802154_fproc_access,获取访问access并处理,需要下一访问机会的时间信息;
    • mcps802154_fproc_access_now,与上一接口的区别在于,直接获取当前时间的访问,并进行处理,可以理解为上一函数的封装;
    • mcps802154_fproc_access_done,访问完成,释放;
    • mcps802154_fproc_access_reset,当出现错误后,复位一个access;当接收到意外事件时,当前专属的帧和当前访问被保留,可能被底层驱动使用。当驱动器重启或停止时,缓冲区和访问可被释放。
    • mcps802154_fproc_stopped_handle,进入Stopped状态处理,fproc_stopped.c中定义;
    • mcps802154_fproc_broken_handle,进入broken状态处理,fproc_broken.c中定义;
    • mcps802154_fproc_nothing_handle,处理非活跃状态,fproc_nothins.c文件;
    • mcps802154_fproc_rx_handle,处理一个接收访问及改变状态;
    • mcps802154_fproc_tx_handle,除了第一个发送访问及改变状态;
    • mcps802154_fproc_multi_handle,处理多帧访问,改变状态;
    • mcps802154_fproc_vendor_handle,处理一个有供应商管理的多帧访问。

    2. 相关代码实现

    关于MCPS802154的帧,通过分配sk_buff来存储,主要构成包括:帧头 + 载荷 + FCS(IEEE802154_FCS_LEN)。
    通过struct sk_buff *mcps802154_frame_alloc(struct mcps802154_llhw *llhw, unsigned int size, gfp_t flags)函数实现。

    2.1 帧处理状态切换

    通过调用mcps802154_fproc_change_state函数,主要操作:当前的状态调用leave回调函数(若有),并将MCPS私有域的状态切换为新的状态,若定义了enter函数,则调用enter回调函数。

    void mcps802154_fproc_change_state( struct mcps802154_local *local, const struct mcps802154_fproc_state *new_state)
    {
    	if (local->fproc.state->leave)
    		local->fproc.state->leave(local);
    	local->fproc.state = new_state;
    	if (local->fproc.state->enter)
    		local->fproc.state->enter(local);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2 帧处理访问

    通过函数void mcps802154_fproc_access(struct mcps802154_local *local, u32 next_timestamp_dtu)实现帧处理的访问,通过mcps802154_ca_get_access函数,获取access指针,进行处理。

    关于帧的访问操作,根据不同的访问方式来调用不同的帧处理,主要包括rx、tx、multi以及vendor。

    	switch (access->method) {
    	case MCPS802154_ACCESS_METHOD_NOTHING:
    		mcps802154_fproc_nothing_handle(local);
    		r = 0;
    		break;
    	case MCPS802154_ACCESS_METHOD_IMMEDIATE_RX:
    		r = mcps802154_fproc_rx_handle(local, access);
    		break;
    	case MCPS802154_ACCESS_METHOD_IMMEDIATE_TX:
    		r = mcps802154_fproc_tx_handle(local, access);
    		break;
    	case MCPS802154_ACCESS_METHOD_MULTI:
    		r = mcps802154_fproc_multi_handle(local, access);
    		break;
    	case MCPS802154_ACCESS_METHOD_VENDOR:
    		r = mcps802154_fproc_vendor_handle(local, access);
    		break;
    	default:
    		r = -1;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.3 帧接收

    void mcps802154_rx_frame(struct mcps802154_llhw *llhw)
    {
        // 基于底层硬件获取当前的MCPS802154本地私有数据指针
    	struct mcps802154_local *local = llhw_to_local(llhw);
    
        // 状态机加锁
    	mutex_lock(&local->fsm_lock);
    	trace_llhw_event_rx_frame(local);
        // 调用当前状态的rx_frame回调函数
    	if (local->fproc.state->rx_frame)
    		local->fproc.state->rx_frame(local);
    	else
    		mcps802154_broken_safe(local);
    	trace_llhw_event_done(local);
    	mutex_unlock(&local->fsm_lock);
    }
    EXPORT_SYMBOL(mcps802154_rx_frame);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    对于rx_timeout、rx_error、tx_done等均为类似的处理方式,最后都通过EXPORT_SYMBOL宏,就符号导出供其他模块使用。

    • mcps802154_rx_timeout
    • mcps802154_rx_error
    • mcps802154_tx_done

    2.4 帧接收状态

    可以看到在帧处理获得访问之后,将调用mcps802154_fpoc_rx_handle来处理对应状态下的操作,对于接收的帧处理状态定义如下:

    static const struct mcps802154_fproc_state mcps802154_fproc_rx = {
    	.name = "rx",
    	.rx_frame = mcps802154_fproc_rx_rx_frame,
    	.rx_error = mcps802154_fproc_rx_rx_error,
    	.schedule_change = mcps802154_fproc_rx_schedule_change,
    };
    
    int mcps802154_fproc_rx_handle(struct mcps802154_local *local,
    			       struct mcps802154_access *access)
    {
    	int r;
    	struct mcps802154_rx_info rx_info = {
    		.flags = MCPS802154_RX_INFO_AACK,
    		.timeout_dtu = -1,
    	};
    	r = llhw_rx_enable(local, &rx_info, 0);
    	if (r)
    		return r;
    
    	mcps802154_fproc_change_state(local, &mcps802154_fproc_rx);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    状态定义中,仅定义了rx_frame、rx_error以及schedule_change,分别处理帧接收、帧接收错误处理以及调度切换。

    接收帧处理中,底层硬件使能接收,然后将帧处理状态切换到mcps802154_fproc_rx

  • 相关阅读:
    软碟通制作启动盘
    L44.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- su和visudo
    图--专升本
    Flume采集端口数据kafka消费
    【华为机试真题 JAVA】工号不够用了怎么办-100
    CCF ChinaSoft 2023 论坛巡礼 | 云计算标准化论坛
    16 Docker容器存储架构:docker存储持久化-volume
    python爬虫之protobuf协议介绍
    maven打包命令打出的可执行的jar包和可依赖的jar包的区别
    Java类的主动加载和被动加载
  • 原文地址:https://blog.csdn.net/luo58614013/article/details/133919051