接上篇文章,理解了这个技巧那么就该实用了,碰巧前段时间接触了cevent的开源项目就是这个原理实现的,有效的降低了程序的耦合性,提高程序的分离和稳定性。
/**
*******************************************************************************
** \brief cevent 实现过程解析
** 传统的代码 每个外设实现好在主程序开始进行顺序处理,但是这种方法会造成外设和main的耦合性增高。
** cevent 通过#define SECTION(level) __attribute__((used,__section__(".fn_cmd."level)))的方式将函数定义到指定的Text段(代码段)
** 在main只需要将指定好的Text段从起始位置做一个轮询就可以实现各个外设的初始化,当然不局限于初始化函数,其他任务函数也可以通过这种
** 方式实现,通过event的大小决定执行的顺序,有限解决耦合性。
**
int temp1 = 2; //放在data段
int temp2 = 0; //放在bss段(初始化为0相当于没有初始化)
int temp1; //放在bss段(所以全局变量定义时不用初始化)
int main(void)
{
SysClkInit();
ceventInit();
ceventPost(EVENT_INIT_STAGE); //timer usart/**减小耦合*/
//初始化函数用一个event
SysTick_Init(1000u); //1ms
while(1)
{
#if cevent_t
ceventPost(EVENT_APP_STAGE2); /**减小耦合*/
//任务函数根据先后顺序注册函数,或者用状态机
//左边的工程目录就是注册顺序(在相同的event情况下) led -- usart -- timer
//如果想要有特定的顺序,改变event即可
Ddl_Delay1ms(2000);
#endif
#if cpost_t
cpostProcess(); /**cpost代替全局变量*/
#endif
}
}
void usart_init(void);
void usart_event(void);
CEVENT_EXPORT(EVENT_INIT_STAGE, usart_init);
CEVENT_EXPORT(EVENT_APP_STAGE2, usart_event);
void timer0_init(void);
void timer_event(void);
CEVENT_EXPORT(EVENT_INIT_STAGE, timer0_init);
CEVENT_EXPORT(EVENT_APP_STAGE2 ,timer_event);
/**
* @brief 广播event事件
*
* @param event 事件
*
*/
void ceventPost(unsigned short event)
{
ceventHandler(event);
}
/**
* @brief cevent处理
*
* @param event 事件
*
*/
static void ceventHandler(unsigned short event)
{
for (size_t i = 0; i < ceventTable.count; i++)
{
if (ceventTable.base[i].event == event)
{
ceventRun(&(ceventTable.base[i]));
}
}
}
/**
* @brief 导出事件
*
* @param _event 事件
* @param _func 注册函数
* @param ... 参数
*/
#define CEVENT_EXPORT(_event, _func, ...) \
const void *cEventParam##_event##_func[] = {(void *)_func, ##__VA_ARGS__}; \
const CEvent SECTION("cEvent") cEvent##_event##_func = \
{ \
.param = cEventParam##_event##_func, \
.paramNum = sizeof(cEventParam##_event##_func) / sizeof(void *), \
.event = _event, \
}