KW41Z板卡Openthread源码学习(二)
<p><span style="font-size:16px;"><strong>前言</strong></span></p><p>本篇主要从main函数入手分析整个执行过程。主要就是整理了调用过程,带有简单的注释,协议栈没有深入,深入内容有点多。</p>
<p> </p>
<p><span style="font-size:16px;"><strong>源码整理</strong></span></p>
<p>主函数</p>
<pre>
<code class="language-cpp">/* 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;
}</code></pre>
<p>openthread/src/core/common/tasklet.hpp</p>
<p>这部分是整个openthread的核心,支撑起了其他模块的正常运行,当模块发生事件后就会将任务挂到调度器中等待被调度。</p>
<pre>
<code class="language-cpp">/*任务类定义,后面会还有上下文的任务和特定类型的任务模块,不展开*/
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 FALSEIf 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
};
/**
* 任务回调函数定义.
*
* @paramaTaskletA reference to the tasklet being run.
*
*/
typedef void (&Handler)(Tasklet &aTasklet);
/**
* 任务构造函数(任务对象创建),初始化内部成员属性.
*
* @paramaInstance A reference to the OpenThread instance object.
* @paramaHandler 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 TRUEThe tasklet is posted.
* @retval FALSE The tasklet is not posted.
*
*/
bool IsPosted(void) const { return (mNext != nullptr); }
private:
void RunTask(void) { mHandler(*this); }
HandlermHandler;
Tasklet *mNext;
};</code></pre>
<p>命令处理</p>
<pre>
<code>// 串口命令处理过程
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);</code></pre>
<p>射频</p>
<pre>
<code class="language-cpp">// 射频接收处理过程
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);
// 后面就是对数据的解析处理,根据数据类型执行不同的操作
// 展开就是协议栈的实现了,所以不深入。</code></pre>
<p><span style="font-size:16px;"><strong>小结</strong></span></p>
<p>源码整理了命令处理和射频处理,基本上还是比较清楚的,接下来先实现一个功能实时效果吧。</p>
<p>源码整理了命令处理和射频处理确实是清楚的</p>
<p>openthread这几年好像没看见在推了。</p>
页:
[1]