Nordic SDK nrf_setion和nrf_section_iter模块分析
开发环境:
nRF5_SDK_14.2.0_17b948a
KEIL 5.27
Windows 10 x64
芯片:nRF51822/nRF52832/nRF52840
新版本SDK做了很多改弄,下面来分析一下两个比较有意思的模块,nrf_setion和nrf_section_iter
这个两位模块基本都是用宏定义的
nrf_setion
NRF_SECTION_START_ADDR
NRF_SECTION_END_ADDR
NRF_SECTION_LENGTH
NRF_SECTION_DEF
NRF_SECTION_ITEM_REGISTER
NRF_SECTION_ITEM_GET
NRF_SECTION_ITEM_COUNT
nrf_section_iter
NRF_SECTION_SET_DEF
NRF_SECTION_SET_ITEM_REGISTER
nrf_section_iter_init、nrf_section_iter_get、nrf_section_iter_next
1、NRF_SECTION_START_ADDR、NRF_SECTION_END_ADDR、NRF_SECTION_LENGTH
刚看这个宏定义有点蒙,这是什么鬼,查阅一下资料仔细看看
CONCAT_2表示将两个参数合并,使用的是C语言的##操作符
$$Base表示起始地址
$$Limit表示结束地址
NRF_SECTION_START_ADDR 表示获取SECTION起始地址
NRF_SECTION_END_ADDR 表示获取SECTION起始地址
NRF_SECTION_LENGTH 表示获取SECTION大小
2、NRF_SECTION_DEF
例如:
/* Create the section "fs_data". */
NRF_SECTION_DEF(fs_data, nrf_fstorage_t);
宏替换完之后最终就是
extern nrf_fstorage_t * fs_data$$Base;
extern void * fs_data$$Limit;
声明两个变量fs_data$$Base和fs_data$$Limit,变量的值为fs_data section段的起始地址和结束地址
现在明白了,实际上NRF_SECTION_DEF表示声明两个变量,变量值分别为section段的起始地址和结束地址
3、NRF_SECTION_ITEM_REGISTER
STRINGIFY 表示将将宏参数转换为字符串,使用使用的是C语言的#操作符
还是找个实例看一看:
#define NRF_FSTORAGE_DEF(inst) NRF_SECTION_ITEM_REGISTER(fs_data, inst)
NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
{
// The flash area boundaries are set in fds_init().
.evt_handler = fs_event_handler,
};
宏替换完之后最终就是
nrf_fstorage_t m_fs __attribute__ ((section(‘fs_data’))) __attribute__((used)) = {
// The flash area boundaries are set in fds_init().
.evt_handler = fs_event_handler,
};
那么NRF_SECTION_ITEM_REGISTER 就表示定义一个变量,并且指定这个变量在哪个section段,可以将多个变量指定到同一个section段
4、NRF_SECTION_ITEM_GET
还是找个实例看一看:
/**@brief Macro for retrieving an fstorage instance. */
#define NRF_FSTORAGE_INSTANCE_GET(i) NRF_SECTION_ITEM_GET(fs_data, nrf_fstorage_t, (i))
宏替换完之后最终就是
((nrf_fstorage_t*)fs_data$$Base + (i))
那么NRF_SECTION_ITEM_GET就表示获取section段中的一个实例,i表示索引
结合上面的NRF_SECTION_ITEM_REGISTER来看,NRF_FSTORAGE_INSTANCE_GET(0)就是变量m_fs。
5、NRF_SECTION_ITEM_COUNT
NRF_SECTION_ITEM_COUNT 就表示获取section段中有多少个变量实例,获取到数量之后就可以通过NRF_SECTION_ITEM_GET遍历整个section段全部变量实例
6、NRF_SECTION_SET_DEF
迭代器定义
7、NRF_SECTION_SET_ITEM_REGISTER
观察者注册到迭代器中
8、nrf_section_iter_init、nrf_section_iter_get、nrf_section_iter_next
遍历迭代器
9、总结:
使用C语言和编译器的一些功能实现 迭代器的效果,这样的写执行回调函数的时候就不用管有多少个回调函数,具体的回调函数是什么,只需要定义好section段,需要执行的回调函数注册到这个section段中,这样在需要执行回调函数的时候遍历这个section段所以回调函数即可,实现解耦,代码分离。例如蓝牙连接这个事件,不需要知道有多少个service需要这个蓝牙连接消息,只需要注册一个蓝牙的section段,谁需要谁就注册回调函数到这个section中,在蓝牙连接这个消息到来是只需要遍历这个蓝牙的section段,就可以通知所有需要该消息的观察者
$$Base和$$Limit 非常有用,在SDK中很多地址都有用到,熟练掌握使用对代码有很大的帮助
参考:
关于__attribute__中section部分的一些了解:https://blog.csdn.net/sadshen/article/details/9419267
未经本人同意 请务转载 David QQ:435398366