0 Preface/Foreword
1 邮箱(mailbox)
1.1 mailbox ID定义
static osMailQId app_mailbox = NULL;
1.2 定义mailbox结构体变量
#define osMailQDef(name, queue_sz, type) \
static void *os_mail_p_##name[2]; \
const char mail_##name[] = #name; \
const osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), (&os_mail_p_##name), \
{ NULL, 0U, NULL, 0U, NULL, 0U }, \
{ mail_##name, 0U, NULL, 0U, NULL, 0U } }
osMailQDef,三个参数:
- name,名字
- queue_sz,队列中,总共元素个数
- type,元素大小
实例分析:
osMailQDef (app_mailbox, APP_MAILBOX_MAX, APP_MESSAGE_BLOCK);
#define APP_MAILBOX_MAX (20)
APP_MAILBOX_MAX: 20
APP_MESSAGE_BLOCK,为一个结构体类型数据,具体见section 1.3。
1.3 APP_MESSAGE_BLOCK
typedef struct {
uint32_t src_thread;
uint32_t dest_thread;
uint32_t system_time;
uint32_t mod_id;
enum APP_MOD_LEVEL_E mod_level;
APP_MESSAGE_BODY msg_body;
} APP_MESSAGE_BLOCK;
1.3.1 APP_MESSAGE_BODY
typedef struct {
uint32_t message_id;
uint32_t message_ptr;
uint32_t message_Param0;
uint32_t message_Param1;
uint32_t message_Param2;
float message_Param3;
#if defined(USE_BASIC_THREADS)
void* p;
#endif
} APP_MESSAGE_BODY;
1.3.2 APP_MOD_LEVEL_E
enum APP_MOD_LEVEL_E {
APP_MOD_LEVEL_0 = 0,
APP_MOD_LEVEL_1,
APP_MOD_LEVEL_2,
};
1.3.3 APP_MODULE_ID_T
#ifndef CHIP_SUBSYS_SENS
enum APP_MODUAL_ID_T {
APP_MODUAL_KEY = 0,
APP_MODUAL_AUDIO,
APP_MODUAL_BATTERY,
APP_MODUAL_BT,
APP_MODUAL_FM,
APP_MODUAL_SD,
APP_MODUAL_LINEIN,
APP_MODUAL_USBHOST,
APP_MODUAL_USBDEVICE,
APP_MODUAL_WATCHDOG,
APP_MODUAL_ANC,
APP_MODUAL_VOICE_ASSIST,
APP_MODUAL_SMART_MIC,
APP_MODUAL_CAPSENSOR,
#ifdef __PC_CMD_UART__
APP_MODUAL_CMD,
#endif
#ifdef TILE_DATAPATH
APP_MODUAL_TILE,
#endif
APP_MODUAL_MIC,
#ifdef VOICE_DETECTOR_EN
APP_MODUAL_VOICE_DETECTOR,
#endif
#ifdef AUDIO_HEARING_COMPSATN
APP_MODUAL_HEAR_COMP,
#endif
APP_MODUAL_OHTER,
#if defined(USE_BASIC_THREADS)
APP_MODUAL_AUDIO_MANAGE,
APP_MODUAL_MEDIA,
APP_MODUAL_BTSYNC,
APP_MODUAL_ANC_FADE,
APP_MODUAL_UX,
APP_MODUAL_TWSCTRL,
#else
APP_MODUAL_CUSTOM0,
APP_MODUAL_CUSTOM1,
APP_MODUAL_CUSTOM2,
APP_MODUAL_CUSTOM3,
APP_MODUAL_CUSTOM4,
APP_MODUAL_CUSTOM5,
#endif
#if defined (_OSM_HOST_FUNC_)
APP_MODUAL_P27WLC_II,
#endif
APP_MODUAL_NUM
};#else /* defined(CHIP_SUBSYS_SENS) */
enum APP_MODUAL_ID_T {
APP_MODUAL_KEY = 0,
APP_MODUAL_AUDIO,
#ifdef VOICE_DETECTOR_EN
APP_MODUAL_VOICE_DETECTOR,
#endif
APP_MODUAL_OHTER,APP_MODUAL_NUM
};
#endif /* CHIP_SUBSYS_SENS */
CHIP_SUBSYS_SENS :该宏有没有定义呢?通过makefile文件追溯可知,该宏没有定义,详情如下:
1.4 获取邮箱结构体变量
osMailQ(app_mailbox)
app_mailbox,该名字和定义时的名字需要相同。
1.5 创建mailbox对象(object)
app_mailbox = osMailCreate(osMailQ(app_mailbox), NULL);
有两个参数:
- 定义的结构体变量地址
- 线程ID,没有实际作用
1.5.1 osMailCreate implementation
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
os_mail_queue_t *ptr;
(void)thread_id;if (queue_def == NULL) {
return (osMailQId)NULL;
}ptr = queue_def->mail;
if (ptr == NULL) {
return (osMailQId)NULL;
}ptr->mp_id = osMemoryPoolNew (queue_def->queue_sz, queue_def->item_sz, &queue_def->mp_attr);
ptr->mq_id = osMessageQueueNew(queue_def->queue_sz, sizeof(void *), &queue_def->mq_attr);
if ((ptr->mp_id == (osMemoryPoolId_t)NULL) || (ptr->mq_id == (osMessageQueueId_t)NULL)) {
if (ptr->mp_id != (osMemoryPoolId_t)NULL) {
osMemoryPoolDelete(ptr->mp_id);
}
if (ptr->mq_id != (osMessageQueueId_t)NULL) {
osMessageQueueDelete(ptr->mq_id);
}
return (osMailQId)NULL;
}return (osMailQId)ptr;
}
主要功能:
- 根据mailbox的大小,动态分配内存池
- 根据mailbox大小,动态分配消息队列
- 返回一个对象指针,该指针原始值为数组。
1.5.2 os_mail_queue_t
typedef struct os_mail_queue_s {
osMemoryPoolId_t mp_id;
osMessageQueueId_t mq_id;
} os_mail_queue_t;
作用:保护两个成员,分别用于存放memory pool ID和message queue ID。
1.6 osMailGet
osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
osStatus_t status;
osEvent event;
void *mail;if (ptr == NULL) {
event.status = osErrorParameter;
return event;
}status = osMessageQueueGet(ptr->mq_id, &mail, NULL, millisec);
switch (status) {
case osOK:
event.status = osEventMail;
event.value.p = mail;
break;
case osErrorResource:
event.status = osOK;
break;
case osErrorTimeout:
event.status = osEventTimeout;
break;
default:
event.status = status;
break;
}
return event;
}
主要功能:
- 通过osMessageQueueGet获取消息
1.6.1 osMessageQueueGet
从消息队列中获取消息,或者如果消息队列为空则等待timetout
/// Get a Message from a Queue or timeout if Queue is empty.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
osStatus_t status;EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
if (IsIrqMode() || IsIrqMasked()) {
status = isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
} else {
status = __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
}
return status;
}
NOTE:
- __svcMessageQueueGet在哪里实现?库?内敛函数?宏函数?
验证发现:所有的都是调用__svcMessageQueueGet而不是isrRtxMessageQueueGet。(如下截图所示)
1.7 osMailAlloc
void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;if (ptr == NULL) {
return NULL;
}
return osMemoryPoolAlloc(ptr->mp_id, millisec);
}
/// Allocate a memory block from a Memory Pool.
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
void *memory;EvrRtxMemoryPoolAlloc(mp_id, timeout);
if (IsIrqMode() || IsIrqMasked()) {
memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
} else {
memory = __svcMemoryPoolAlloc(mp_id, timeout);
}
return memory;
}
NOTE:
- 从内存池中分配一个内存块
1.8 osMailPut
osStatus osMailPut (osMailQId queue_id, const void *mail) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;if (ptr == NULL) {
return osErrorParameter;
}
if (mail == NULL) {
return osErrorValue;
}
return osMessageQueuePut(ptr->mq_id, &mail, 0U, 0U);
}
NOTE:osMessageQueuePut参数中,为什么需要取mail的地址? 如果不取地址,会有什么结果?
验证发现:机器死机,插适配器充电无法恢复,并且无法继续固件升级。(设备变砖)
/// Put a Message into a Queue or timeout if Queue is full.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
osStatus_t status;EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
if (IsIrqMode() || IsIrqMasked()) {
status = isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
} else {
status = __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
}
return status;
}
1.9 osMailFree
osStatus osMailFree (osMailQId queue_id, void *mail) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;if (ptr == NULL) {
return osErrorParameter;
}
if (mail == NULL) {
return osErrorValue;
}
return osMemoryPoolFree(ptr->mp_id, mail);
}
/// Return an allocated memory block back to a Memory Pool.
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
osStatus_t status;EvrRtxMemoryPoolFree(mp_id, block);
if (IsIrqMode() || IsIrqMasked()) {
status = isrRtxMemoryPoolFree(mp_id, block);
} else {
status = __svcMemoryPoolFree(mp_id, block);
}
return status;
}
2 生产者(producer)
2.1 app_mailbox_put
int app_mailbox_put(APP_MESSAGE_BLOCK* msg_src)
{
osStatus status;
// osMutexWait(app_mutex_id, osWaitForever);APP_MESSAGE_BLOCK *msg_p = NULL;
msg_p = (APP_MESSAGE_BLOCK*)osMailAlloc(app_mailbox, 0);
if (!msg_p){
osEvent evt;
TRACE_IMM(0,"osMailAlloc error dump");
for (uint8_t i=0; i<APP_MAILBOX_MAX; i++){
evt = osMailGet(app_mailbox, 0);
if (evt.status == osEventMail) {
TRACE_IMM(9,"cnt:%d mod:%d level:%d src:%08x tim:%d id:%8x ptr:%08x para:%08x/%08x/%08x/%08x",
i,
((APP_MESSAGE_BLOCK *)(evt.value.p))->mod_id,
((APP_MESSAGE_BLOCK *)(evt.value.p))->mod_level,
((APP_MESSAGE_BLOCK *)(evt.value.p))->src_thread,
((APP_MESSAGE_BLOCK *)(evt.value.p))->system_time,
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_id,
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_ptr,
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param0,
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param1,
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param2,
(uint32_t)((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param3);
}else{
TRACE_IMM(2,"cnt:%d %d", i, evt.status);
break;
}
}
TRACE_IMM(0,"osMailAlloc error dump end");
}ASSERT(msg_p, "osMailAlloc error");
msg_p->src_thread = (uint32_t)osThreadGetId();
msg_p->dest_thread = (uint32_t)NULL;
msg_p->system_time = hal_sys_timer_get();
msg_p->mod_id = msg_src->mod_id;
msg_p->mod_level = msg_src->mod_level;
msg_p->msg_body.message_id = msg_src->msg_body.message_id;
msg_p->msg_body.message_ptr = msg_src->msg_body.message_ptr;
msg_p->msg_body.message_Param0 = msg_src->msg_body.message_Param0;
msg_p->msg_body.message_Param1 = msg_src->msg_body.message_Param1;
msg_p->msg_body.message_Param2 = msg_src->msg_body.message_Param2;
msg_p->msg_body.message_Param3 = msg_src->msg_body.message_Param3;
msg_p->msg_body.p = msg_src->msg_body.p;status = osMailPut(app_mailbox, msg_p);
// osMutexRelease(app_mutex_id);
return (int)status;
}
3 消费者(consumer)
3.1 app_mailbox_get
app_mailbox_get由app_thread调用。
3.2 app_mailbox_process
int app_mailbox_process(APP_MESSAGE_BLOCK* msg_p)
{
if (msg_p->mod_id < APP_MODUAL_NUM){
if (mod_handler[msg_p->mod_id]){
int ret = 0 ;
if(APP_MODUAL_AUDIO_MANAGE == msg_p->mod_id){
int Priority = osThreadGetPriority(app_thread_tid);
osThreadSetPriority(app_thread_tid, osPriorityRealtime);
ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body));
osThreadSetPriority(app_thread_tid, Priority);
}else{
ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body));
}
if (ret)
TRACE(2,"%s, mod_handler[%d] ret=%d", __func__, msg_p->mod_id, ret);
}
}
return 0;
}
NOTE:最终消息处理是在各自模块中实现。(回调函数)