我们先看下没有开启共享中断支持时,如何创建中断。⑴处代码表示如果创建的中断的模式hwiMode等于共享模式IRQF_SHARED,则返回错误OS_ERRNO_HWI_SHARED_ERROR。⑵处代码判断中断处理程序hwiForm- hook是否为空,为空时则把hwiHandler赋值赋值给它;hwiForm- hook不为空则执行⑹,说明中断已经创建过,返回异常OS_ERRNO_HWI_ALREADY_CREATED;⑷处判断irqParam是否为空,如果不为空,则为这个中断处理程序的参数申请内存,设置数组,并赋值给hwiForm- registerInfo。⑸处表示如果为中断处理程序的参数申请内存失败,则返回异常。
STATIC UINT32 OsHwiCreateNoShared(HwiHandleInfo *hwiForm, HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler, const HWI_IRQ_PARAM_S *irqParam) UINT32 intSave;⑴ if (hwiMode IRQF_SHARED) { return OS_ERRNO_HWI_SHARED_ERROR; HWI_LOCK(intSave);⑵ if (hwiForm- hook == NULL) {⑶ hwiForm- hook = hwiHandler;⑷ if (irqParam != NULL) { hwiForm- registerInfo = OsHwiCpIrqParam(irqParam);⑸ if (hwiForm- registerInfo == (HWI_ARG_T)NULL) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_NO_MEMORY; } else { HWI_UNLOCK(intSave);⑹ return OS_ERRNO_HWI_ALREADY_CREATED; HWI_UNLOCK(intSave); return LOS_OK;}
可以结合示意图理解创建非共享中断,对应的中断处理信息表HwiHandleInfo *hwiForm结构体示意图如下。创建中断时,除了校验,主要是设置中断处理程序hwiForm- hook及其参数hwiForm- registerInfo。
2.3.2 支持共享时创建中断UINT32 OsHwiCreateShared()我们先看下开启共享中断支持时,如何创建创建中断。支持共享中断时,可以创建共享中断,也可以创建非共享的中断,如果⑴处的modeResult == 1表示创建的是共享中断,否则是非共享中断。没有开启共享中断支持时,使用HwiHandleInfo *hwiForm单节点维护中断处理程序信息,开启共享中断支持时,需要使用HwiHandleInfo *hwiForm单链表来维护中断处理程序信息。
首先做些基础的参数校验,⑵处表示,如果创建的是共享中断,但是参数irqParam或参数的设备Id为空,返回错误OS_ERRNO_HWI_SHARED_ERROR。也就是说,共享模式hwiMode和中断处理程序的参数irqParam是必须的,因为需要指定特定的设备来共享同一个中断号。⑶处判断表示,如果head- next不为空,说明此中断号已经有其他设备使用了,该中断号需要被不同的设备共享,此时如果hwiMode或head- shareMode不是共享模式,则返回错误。⑷处while循环代码处理此中断号已经有其他设备使用的情况,依次循环中断处理信息表的单链表,判断是否已经存在同一个设备已经注册的情况,如果存在则返回错误OS_ERRNO_HWI_ALREADY_CREATED。循环完毕之后,hwiForm为链表中的最后一个设备节点。如果创建的不是共享中断,循环条件不满足,此处代码就不会执行。
做完参数校验后,⑸处为一个HwiHandleInfo节点申请内存,申请的这个节点是中断的设备节点,管理具体设备的中断处理程序信息,参数列表中的节点HwiHandleInfo *head是中断头节点,只标记是不是共享中断,可以参考下文的示意图,来加深理解。如果申请失败则返回错误OS_ERRNO_HWI_NO_MEMORY;申请成功继续执行后面的语句,把hwiForm- respCount赋值为0,表示中断处理程序还没有执行过。⑹处代码判断参数irqParam,不为空时申请内存空间保存参数,否则参数赋值为0。⑺处把新增设备的中断处理程序赋值给hwiFormNode- hook,然后把新增的节点挂载链表的尾部。⑻处表示更新头节点的共享模式。
STATIC UINT32 OsHwiCreateShared(HwiHandleInfo *head, HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler, const HWI_IRQ_PARAM_S *irqParam) UINT32 intSave; HwiHandleInfo *hwiFormNode = NULL; HWI_IRQ_PARAM_S *hwiParam = NULL;⑴ HWI_MODE_T modeResult = hwiMode IRQF_SHARED; HwiHandleInfo *hwiForm = NULL;⑵ if (modeResult ((irqParam == NULL) || (irqParam- pDevId == NULL))) { return OS_ERRNO_HWI_SHARED_ERROR; HWI_LOCK(intSave);⑶ if ((head- next != NULL) ((modeResult == 0) || (!(head- shareMode IRQF_SHARED)))) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_SHARED_ERROR; hwiForm = head;⑷ while (hwiForm- next != NULL) { hwiForm = hwiForm- next; hwiParam = (HWI_IRQ_PARAM_S *)(hwiForm- registerInfo); if (hwiParam- pDevId == irqParam- pDevId) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_ALREADY_CREATED;⑸ hwiFormNode = (HwiHandleInfo *)LOS_MemAlloc(m_aucSysMem0, sizeof(HwiHandleInfo)); if (hwiFormNode == NULL) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_NO_MEMORY; hwiForm- respCount = 0;⑹ if (irqParam != NULL) { hwiFormNode- registerInfo = OsHwiCpIrqParam(irqParam); if (hwiFormNode- registerInfo == (HWI_ARG_T)NULL) { HWI_UNLOCK(intSave); (VOID) LOS_MemFree(m_aucSysMem0, hwiFormNode); return OS_ERRNO_HWI_NO_MEMORY; } else { hwiFormNode- registerInfo = 0;⑺ hwiFormNode- hook = hwiHandler; hwiFormNode- next = (struct tagHwiHandleForm *)NULL; hwiForm- next = hwiFormNode;⑻ head- shareMode = modeResult; HWI_UNLOCK(intSave); return LOS_OK;}
配置完毕中断后,对应的中断处理信息表HwiHandleInfo *hwiForm示意图如下:
可以结合示意图来理解在开启共享中断支持时,如何创建中断。HwiHandleInfo *hwiForm结构体单链表示意图如下。创建非共享中断时,只需要两个节点,左侧头结点中的head- shareMode等于0,表示非共享中断,右侧一个设备节点,表示指定设备的中断处理程序,包含中断处理程序hwiForm- hook及其参数hwiForm- registerInfo,hwiForm- next为空。创建共享中断时,至少两个节点,左侧头结点中的head- shareMode等于1,表示共享中断,右侧一到多个设备节点,表示不同设备的中断处理程序,包含中断处理程序hwiForm- hook及其参数hwiForm- registerInfo,hwiForm- next依次指向下一个设备的节点,最后一个节点的hwiForm- next为空。
2.4 删除中断UINT32 LOS_HwiDelete()中断删除操作是创建操作的反向操作,也比较好理解。开发者可以调用函数UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqParam)删除中断。我们先看看这个函数的参数,HWI_HANDLE_T hwiNum是硬件中断号,HWI_IRQ_PARAM_S *irqParam是中断处理程序的参数,如果开启了共享中断需要该参数来删除指定设备的中断信息。
一起剖析下这个函数的源代码,⑴处代码获取对应中断号hwiNum的中断处理程序信息,其中g_hwiOps是中断初始化时注册的中断控制器操作项。⑵、⑶处根据是否开启了共享中断LOSCFG_NO_SHARED_IRQ来分别调用相应的函数删除中断。
LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqParam) UINT32 ret;⑴ HwiHandleInfo *hwiForm = g_hwiOps- getHandleForm(hwiNum); if (hwiForm == NULL) { return OS_ERRNO_HWI_NUM_INVALID; LOS_TRACE(HWI_DELETE, hwiNum);#ifdef LOSCFG_NO_SHARED_IRQ (VOID)irqParam;⑵ ret = OsHwiDelNoShared(hwiForm);#else⑶ ret = OsHwiDelShared(hwiForm, irqParam); LOS_TRACE(HWI_DELETE_SHARE, hwiNum, (UINTPTR)(irqParam != NULL ? irqParam- pDevId : NULL), ret);#endif return ret;}
没有开启共享中断支持时,删除中断调用OsHwiDelNoShared(hwiForm)函数,中断处理程序hwiForm- hook,释放内存等,代码简单,读者自行阅读。我们主要来剖析下支持共享中断时,是如何调用UINT32 OsHwiDelShared(HwiHandleInfo *head, const HWI_IRQ_PARAM_S *irqParam)删除中断的。
2.4.1 支持共享时删除中断UINT32 OsHwiDelShared()我们来分析下开启共享中断支持时,删除中断的源代码流程是什么样的。⑴处表示,如果删除的是共享中断,但是参数irqParam或参数的设备Id为空,返回错误OS_ERRNO_HWI_SHARED_ERROR。⑵处表示删除的是非共享中断,如果wiForm- registerInfo不为空,则释放参数占用的内存,然后释放设备节点占用的内存,并把head- next置空。
⑶处代码处理如何删除共享中断。⑷处while循环对中断程序信息链表上的设备节点进行遍历。⑸处表示如果没有匹配到要删除的设备,则继续遍历下一个设备节点。⑹处表示匹配到要删除的设备中断处理程序节点,则释放参数的内存、释放设备节点内存,并执行⑺,标记匹配到设备节点,然后跳出循环。⑻处,如果循环遍历完毕,还没有匹配到设备节点,则返回错误。⑼处表示如果删除设备节点后,只有一个头结点,则把共享模式改为非共享。
STATIC UINT32 OsHwiDelShared(HwiHandleInfo *head, const HWI_IRQ_PARAM_S *irqParam) HwiHandleInfo *hwiFormtmp = NULL; HwiHandleInfo *hwiForm = NULL; UINT32 find = FALSE; UINT32 intSave; HWI_LOCK(intSave);⑴ if ((head- shareMode IRQF_SHARED) ((irqParam == NULL) || (irqParam- pDevId == NULL))) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_SHARED_ERROR;⑵ if ((head- next != NULL) !(head- shareMode IRQF_SHARED)) { hwiForm = head- next; if (hwiForm- registerInfo) { (VOID) LOS_MemFree(m_aucSysMem0, (VOID *)hwiForm- registerInfo); (VOID) LOS_MemFree(m_aucSysMem0, hwiForm); head- next = NULL; head- respCount = 0; HWI_UNLOCK(intSave); return LOS_OK;⑶ hwiFormtmp = head; hwiForm = head- next;⑷ while (hwiForm != NULL) {⑸ if (((HWI_IRQ_PARAM_S *)(hwiForm- registerInfo))- pDevId != irqParam- pDevId) { hwiFormtmp = hwiForm; hwiForm = hwiForm- next; } else {⑹ hwiFormtmp- next = hwiForm- next; (VOID) LOS_MemFree(m_aucSysMem0, (VOID *)hwiForm- registerInfo); (VOID) LOS_MemFree(m_aucSysMem0, hwiForm);⑺ find = TRUE; break;⑻ if (!find) { HWI_UNLOCK(intSave); return OS_ERRNO_HWI_HWINUM_UNCREATE;⑼ if (head- next == NULL) { head- shareMode = 0; HWI_UNLOCK(intSave); return LOS_OK;}
本文链接: http://activeint.immuno-online.com/view-711485.html