BES2300x笔记(1) -- SDK代码架构与Battery模块

哈喽大家好,这是该系列博文的第一篇~ 篇~

<<【系列博文索引】快速通道 >>

首先上一个链接:参考链接

一、前言

拿到恒玄的SDK源码之后,结合文档花了一些时间研究,这篇就先介绍下代码的框架和模块之间的解耦处理。

二、代码架构

1、 根据SDK的目录可以看出,BES采用的是RTOS(RTX)嵌入式实时操作系统,并且用了ARM的CMSIS_RTOS API接口;
BES2300x笔记(1) -- SDK代码架构与Battery模块_第1张图片
2、 我们知道程序运行开始的地方是RTX_CM_LIB.H里面的_main_init(),主要是进行内核初始化、堆栈的设置、main线程的创建和开启内核等。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第2张图片
3、 第一个线程os_thread_def_main就是main,接着看,在main.cpp文件中。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第3张图片
4、 app_os_init()里有线程创建,这是CMSIS的风格,开发过STM32应该比较熟悉,用来定义线程、定时器和邮箱通讯等;
app_thread_tid = osThreadCreate(osThread(app_thread), NULL);
BES2300x笔记(1) -- SDK代码架构与Battery模块_第4张图片
5、 app_thread为线程loop函数,OSThread其实是一个宏,就是取地址而已
#define osThread(name) &os_thread_def_##name
BES2300x笔记(1) -- SDK代码架构与Battery模块_第5张图片
一般在文件开头会看到这样的定义:osThreadDef其实也是一个宏
osThreadDef(app_thread, osPriorityHigh, 1, 2048, “app_thread”);
BES2300x笔记(1) -- SDK代码架构与Battery模块_第6张图片这里就是给一个结构体变量初始化赋值,然后把os_thread_def_app_thread的地址传给os_thread()。结构体类型是:
BES2300x笔记(1) -- SDK代码架构与Battery模块_第7张图片所以OSThreadDef是设置线程名、优先级以及堆栈大小,通过osThread获取配置的结构体变量的指针,然后作为参数传入OSThreadCreate()。
6、 以上创建了另一个重要线程:app_thread,这个线程将是以后应用模块修改与添加的主要线程。

7、 下面我们看一下app_thread线程里面的具体做了什么:
if (mod_handler[msg_p->mod_id])
int ret = mod_handler[msg_p->mod_id] (&(msg_p->msg_body));

BES2300x笔记(1) -- SDK代码架构与Battery模块_第8张图片
8、 我们可以看到在app_thread线程中,通过app_mailbox_get()反复的在获取邮箱信息,并传入mod_handler[]里面。
static APP_MOD_HANDLER_T mod_handler[APP_MODUAL_NUM];
在这里插入图片描述
看其数据类型是一个函数指针数组,再看其数组下标的定义:
在这里插入图片描述
BES2300x笔记(1) -- SDK代码架构与Battery模块_第9张图片
9、 全局搜索mod_handler,会找到app_set_threadhandle()接口。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第10张图片
到此,我们了解了各个模块会注册自己的回调函数,然后app_thread()会根据get的消息回调模块对应的API进行处理。

10、 我们现在选取一个模块APP_MODUAL_BATTERY(APP_MODULE_BATTERY),从app_set_threadhandle的调用入手,继续研究模块的架构。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第11张图片
可以看到app_battery_open()接口里调用了
app_set_threadhandle(APP_MODUAL_BATTERY, app_battery_handle_process);
其中,app_battery_handle_process()就是BATTERY模块的回调处理函数。
11、 app_battery_open()是由app_init()调用,初始化battery模块。其中battery模块用到的全局变量为
BES2300x笔记(1) -- SDK代码架构与Battery模块_第12张图片
从变量的初始化,我们看到定制化的设置都在tgt_hardware.h里面,还有其他定制化的设置。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第13张图片
12、 在app_battery_handle_process()里面,我们可以看到:
BES2300x笔记(1) -- SDK代码架构与Battery模块_第14张图片
通过全局搜索APP_BATTERY_STATUS_OVERVOLT,发现是通过app_battery_irqhandler发出的事件
BES2300x笔记(1) -- SDK代码架构与Battery模块_第15张图片
app_battery_measure.cb在app_battery_open()中有定义:
app_battery_measure.cb = app_battery_event_process;

BES2300x笔记(1) -- SDK代码架构与Battery模块_第16张图片
上图可以看到是通过app_battery_event_process把模块的消息放到邮箱中。
13、 回到app_battery_irqhandler()
在这里插入图片描述
BES2300x笔记(1) -- SDK代码架构与Battery模块_第17张图片

通过搜索,我们发现app_battery_timer_handler是定时器APP_BATTERY的回调函数,

至此,就搞明白了battery模块的流程:
app_battery_open()配置定时器,对结构体进行初始化,注册事件回调和模块处理函数
—>定时调用app_battery_timer_handler()来获取电池的电压值
—>再通过app_battery_irqhandler()将转换之后的电压值与初始值比较,通过 app_battery_event_process发出不同的电池状态
—>在app_battery_event_process()把消息放入邮箱中
—>最后app_thread线程取出消息,调用对应模块的app_battery_handle_process()接口进行处理

14、 我们再回到app_battery_timer_handler()看下hal_gpadc_open()接口。
BES2300x笔记(1) -- SDK代码架构与Battery模块_第18张图片
可以看到,传入的回调函数指针,赋值给了 gpadc_event_cb[channel] ,另外,用到驱动的地方,要加互斥锁。
15、 通过搜索gpadc_event_cb,进入hal_gpadc_irq_handler()接口;
BES2300x笔记(1) -- SDK代码架构与Battery模块_第19张图片
gpadc_event_cb[ch])就是再通过app_battery_irqhandler()
通过上图,看到 gpadc_event_cb调用了app_battery_irqhandler,并传入了ADC扫描的值。
16、 继续往下就是hal_gpadc_adc2volt()——> hal_gpadc_adc2volt_calib()等ADC底层接口
BES2300x笔记(1) -- SDK代码架构与Battery模块_第20张图片

17、 另外,通过搜索hal_gpadc_irq_handler()接口,也可以找到hal_gpadc_irq_control()中断获取的流程
BES2300x笔记(1) -- SDK代码架构与Battery模块_第21张图片

三、后续扩展

类比BATTERY模块,可以继续学习其他模块,比如按键、BT都是同样的机制。

你可能感兴趣的:(恒玄BES2300x,恒玄BES,BES2300x,TWS耳机)