973|2

82

帖子

3

TA的资源

一粒金砂(中级)

楼主
 

KW41Z板卡Openthread源码学习(二) [复制链接]

前言

本篇主要从main函数入手分析整个执行过程。主要就是整理了调用过程,带有简单的注释,协议栈没有深入,深入内容有点多。

 

源码整理

主函数

/* openthread/example/apps/cli/main.c */
int main(int argc, char *argv[])
{
    otInstance *instance;

    OT_SETUP_RESET_JUMP(argv);

pseudo_reset:
	// 调用src/system.c中的otSysInit函数来初始化引脚、时钟等
    otSysInit(argc, argv);
	// 单例模式得到openthread对象
    instance = otInstanceInitSingle();

    assert(instance);

	// 调用openthread/examples/apps/cli/cli_uart.cpp中的
	// extern "C" void otAppCliInit(otInstance *aInstance)
	// 间接调用了src/uart.c中的otPlatUartEnable()
	// 以及openthread/src/cli/cli.cpp中的
	// extern "C" void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
	// 实例化了一个解释器对象。
    otAppCliInit(instance);

	// 向解释器注册命令
    IgnoreError(otCliSetUserCommands(kCommands, OT_ARRAY_LENGTH(kCommands), instance));
	// 如果不发生关机和重新初始化的情况就一直进行这个循环
    while (!otSysPseudoResetWasRequested())
    {
		// 间接调用openthread/src/core/common/tasklet.cpp中的
		// void Tasklet::Scheduler::ProcessQueuedTasklets(void)
		// 用于处理注册的任务
        otTaskletsProcess(instance);
		// 间接调用src/system.c中的void otSysProcessDrivers(otInstance *aInstance)
		// 用于处理来自硬件的请求,比如串口、射频、定时器等。
        otSysProcessDrivers(instance);
    }

    otInstanceFinalize(instance);

    goto pseudo_reset;

    return 0;
}

openthread/src/core/common/tasklet.hpp

这部分是整个openthread的核心,支撑起了其他模块的正常运行,当模块发生事件后就会将任务挂到调度器中等待被调度。

/*任务类定义,后面会还有上下文的任务和特定类型的任务模块,不展开*/
class Tasklet : public InstanceLocator
{
public:
    /**
     * 任务调度器类
     *
     */
    class Scheduler : private NonCopyable
    {
        friend class Tasklet;

    public:
        /**
         * 调度器初始化
         *
         */
        Scheduler(void)
            : mTail(nullptr)
        {
        }

        /**
         * 只是是否有任务挂起.
         *
         * @retval TRUE   If there are tasklets pending.
         * @retval FALSE  If there are no tasklets pending.
         *
         */
        bool AreTaskletsPending(void) const { return mTail != nullptr; }

        /**
         * 处理所有运行队列中的任务。
         *
         */
        void ProcessQueuedTasklets(void);

    private:
        void PostTasklet(Tasklet &aTasklet);

        Tasklet *mTail; // A circular singly linked-list
    };

    /**
     * 任务回调函数定义.
     *
     * @param[in]  aTasklet  A reference to the tasklet being run.
     *
     */
    typedef void (&Handler)(Tasklet &aTasklet);

    /**
     * 任务构造函数(任务对象创建),初始化内部成员属性.
     *
     * @param[in]  aInstance   A reference to the OpenThread instance object.
     * @param[in]  aHandler    A pointer to a function that is called when the tasklet is run.
     *
     */
    Tasklet(Instance &aInstance, Handler aHandler)
        : InstanceLocator(aInstance)
        , mHandler(aHandler)
        , mNext(nullptr)
    {
    }

    /**
     * 将任务放到任务列表中。
     *
     * If the tasklet is already posted, no change is made and run queue stays as before.
     *
     */
    void Post(void);

    /**
     * 指示任务是否注册到任务列表中.
     *
     * @retval TRUE  The tasklet is posted.
     * @retval FALSE The tasklet is not posted.
     *
     */
    bool IsPosted(void) const { return (mNext != nullptr); }

private:
    void RunTask(void) { mHandler(*this); }

    Handler  mHandler;
    Tasklet *mNext;
};

命令处理

// 串口命令处理过程
void kw41zUartProcess(void);
	static void processReceive(void);
		void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength);
			static void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength);
				ProcessCommand();
// 承接上面
static otError ProcessCommand(void);
	extern "C" void otCliInputLine(char *aBuf);
		void Interpreter::ProcessLine(char *aBuf);
			// 解析字符串,获取命令
			SuccessOrExit(error = Utils::CmdLineParser::ParseCmd(aBuf, args, kMaxArgs));
			// 执行命令,内部定义了任务列表kCommands
			// 任务列表包含了命令及其解释器
			// 所有命令的执行在此完成
			ProcessCommand(args);

射频

// 射频接收处理过程
void kw41zRadioProcess(otInstance *aInstance);
	extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
		void Radio::Callbacks::HandleReceiveDone(Mac::RxFrame *aFrame, Error aError);
			void SubMac::HandleReceiveDone(RxFrame *aFrame, Error aError);
				void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, Error aError);
					Get<LinkRaw>().InvokeReceiveDone(aFrame, aError);
					Get<Mac>().HandleReceivedFrame(aFrame, aError);
// 承上Get<LinkRaw>().InvokeReceiveDone(aFrame, aError);
void LinkRaw::InvokeReceiveDone(RxFrame *aFrame, Error aError);
	void NcpBase::LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
		otError NcpBase::PackRadioFrame(otRadioFrame *aFrame, otError aError);

// 承上Get<Mac>().HandleReceivedFrame(aFrame, aError);
void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError);
	// 后面就是对数据的解析处理,根据数据类型执行不同的操作
	// 展开就是协议栈的实现了,所以不深入。

小结

源码整理了命令处理和射频处理,基本上还是比较清楚的,接下来先实现一个功能实时效果吧。

此帖出自NXP MCU论坛

最新回复

openthread这几年好像没看见在推了。   详情 回复 发表于 2024-3-19 15:28
点赞 关注
 

回复
举报

6828

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

源码整理了命令处理和射频处理确实是清楚的

此帖出自NXP MCU论坛
 
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

板凳
 

openthread这几年好像没看见在推了。

此帖出自NXP MCU论坛
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表