2.2 失能MPUHalMpuDisable

代码很简单,直接把MPU控制寄存器赋值为0来失能MPU功能。

VOID HalMpuDisable(VOID)
{
    UINT32 intSave = HalIntLock();
    MPU->CTRL = 0;
    __DSB();
    __ISB();
    HalIntRestore(intSave);
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

2.3 失能指定的内存区域HalMpuDisableRegion

HalMpuDisableRegion函数执行后不再对指定的内存区域进行MPU保护,
⑴处校验参数合法性。
⑵处没有使用的MPU内存区域无法失能。
⑶处获取MPU的类型寄存器,详细可以访问https://developer.arm.com/documentation/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-type-register。

⑷处表示MPU的数据内存区域(MPU data regions)数量不为空时,执行
⑸处代码更新MPU内存区域编号寄存器(MPU Region Number Register)为指定的内存区域编号,详细的信息可以参考https://developer.arm.com/documentation/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-region-number-register。然后执行⑹处代码更新MPU内存区域属性和大小寄存器(MPU Region Attribute and Size Register),详细可以参考https://developer.arm.com/documentation/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-region-attribute-and-size-register。⑺处把全局变量数组中指定的区域编号设置为未使用0。

UINT32 HalMpuDisableRegion(UINT32 regionId)
{
    volatile UINT32 type;
    UINT32 intSave;

⑴  if (regionId >= MPU_MAX_REGION_NUM) {
        return LOS_NOK;
    }

    intSave = HalIntLock();
⑵  if (!g_regionNumBeUsed[regionId]) {
        HalIntRestore(intSave);
        return LOS_NOK;
    }

⑶  type = MPU->TYPE;
⑷  if ((MPU_TYPE_DREGION_Msk & type) != 0) {
⑸      MPU->RNR = regionId;
⑹      MPU->RASR = 0;
        __DSB();
        __ISB();
    }
⑺  g_regionNumBeUsed[regionId] = 0; /* clear mpu region used flag */
    HalIntRestore(intSave);
    return LOS_OK;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

2.4 设置指定的内存区域属性HalMpuSetRegion

HalMpuSetRegion函数设置指定的内存区域的属性。
⑴处对参数进行合法性校验。
⑵处如果MPU类型寄存器中表示的数据内存区域的数量为0,无法继续设置内嵌区域,直接返回LOS_NOK
⑶处调用函数HalMpuEncodeSize根据内存区域的实际大小值获取编码大小,该值后续会被赋值给MPU属性和大小寄存器的size位。
⑷判断内存区域需要相对内存区域大小进行内存对齐,否则返回LOS_NOK

⑸处计算基地址寄存器的数据,有关基地址寄存器(MPU Region Base Address Register),可以访问https://developer.arm.com/documentation/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-region-base-address-register了解更多。
⑹处计算属性和大小寄存器的数值。
⑺处如果指定的内存区域被使用,直接返回LOS_NOK
⑻处设置MPU相关的寄存器,并标记该内存区域已使用。代码如下:

UINT32 HalMpuSetRegion(UINT32 regionId, MPU_CFG_PARA *para)
{
    UINT32 RASR;
    UINT32 RBAR;
    UINT32 RNR;
    UINT32 encodeSize;
    UINT32 intSave;
    UINT64 size;

⑴  if ((regionId >= MPU_MAX_REGION_NUM) || (para == NULL)) {
        return LOS_NOK;
    }

⑵  if ((MPU_TYPE_DREGION_Msk & MPU->TYPE) == 0) {
        return LOS_NOK;
    }

    RNR = regionId;
⑶  encodeSize = HalMpuEncodeSize(para->size);
    if (encodeSize == 0) {
        return LOS_NOK;
    }
⑷  size = para->size - 1;              /* size aligned after encode check */
    if ((para->baseAddr & size) != 0) { /* base addr should aligned to region size */
        return LOS_NOK;
    }
⑸  RBAR = para->baseAddr & MPU_RBAR_ADDR_Msk;
⑹  RASR = HalMpuGetRASR(encodeSize, para);
    intSave = HalIntLock();
⑺  if (g_regionNumBeUsed[regionId]) {
        HalIntRestore(intSave);
        return LOS_NOK;
    }
⑻  MPU->RNR = RNR;
    MPU->RBAR = RBAR;
    MPU->RASR = RASR;
    __DSB();
    __ISB();
    g_regionNumBeUsed[regionId] = 1; /* Set mpu region used flag */
    HalIntRestore(intSave);
    return LOS_OK;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">
2.4.1 HalMpuEncodeSize根据内存区域实际大小获取size属性值

HalMpuEncodeSize函数根据内存区域实际大小获取size属性值,对应的计算公式为:(Region size in bytes) = 2^(SIZE+1),详细信息可以访问MPU属性和大小寄存器官网资料页面的Table 4.44. Example SIZE field values。32bytes对应4,1KB对应5,…,4GB对应31。

⑴处表示内存区域大小不能大于4GB,然后判断是否相对32字节进行内存对齐。
⑵处先右移2位,然后while循环,执行
⑶每向右循环一位,size属性大小增加1。

STATIC UINT32 HalMpuEncodeSize(UINT64 size)
{
    UINT32 encodeSize = 0;
⑴  if (size > SIZE_4G_BYTE) {
        return 0;
    }
    if ((size & 0x1F) != 0) { /* size should aligned to 32 byte at least. */
        return 0;
    }
⑵  size = (size >> 2);
    while (size != 0) {
        if (((size & 1) != 0) && ((size & 0xFFFFFFFE) != 0)) { /* size != 2^x (5 <= x <= 32)  128B - 4GB */
            return 0;
        }
⑶      size = (size >> 1);
        encodeSize++;
    }
    return encodeSize;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">
2.4.2 HalMpuGetRASR根据size属性值和配置参数计算属性和大小寄存器的值

HalMpuGetRASR根据size属性值和配置参数计算属性和大小寄存器的值。⑴处根据配置的访问权限计算AP(ACCESS permission),然后计算属性和大小寄存器的值,最后执行⑶给寄存器赋值。

STATIC UINT32 HalMpuEncodeAP(MpuAccessPermission permission)
{
    UINT32 ap;
    switch (permission) {
        case MPU_RW_BY_PRIVILEGED_ONLY:
            ap = MPU_AP_RW_USER_FORBID;
            break;
        case MPU_RW_ANY:
            ap = MPU_AP_RW_USER_RW;
            break;
        case MPU_RO_BY_PRIVILEGED_ONLY:
            ap = MPU_AP_RO_USER_FORBID;
            break;
        case MPU_RO_ANY:
            ap = MPU_AP_RO_USER_RO;
            break;
        default:
            ap = MPU_AP_RW_USER_RW;
            break;
    }
    return ap;
}
STATIC VOID HalMpuRASRAddMemAttr(MPU_CFG_PARA *para, UINT32 *RASR)
{
    BOOL cachable = 0;
    BOOL buffable = 0;
    switch (para->memType) {
        case MPU_MEM_ON_CHIP_ROM:
        case MPU_MEM_ON_CHIP_RAM:
            cachable = 1;
            buffable = 0;
            break;
        case MPU_MEM_XIP_PSRAM:
            cachable = 1;
            buffable = 1;
            break;
        case MPU_MEM_XIP_NOR_FLASH:
            cachable = 0;
            buffable = 1;
            break;
        default:
            break;
    }
    (*RASR) |= ((cachable << MPU_RASR_C_Pos) | (buffable << MPU_RASR_B_Pos));
}

STATIC UINT32 HalMpuGetRASR(UINT32 encodeSize, MPU_CFG_PARA *para)
{
    UINT32 RASR;
    UINT32 ap;
⑴  ap = HalMpuEncodeAP(para->permission);
    RASR = MPU_RASR_ENABLE_Msk;
    RASR |= ((encodeSize << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk);
    RASR |= ((ap << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | ((para->executable << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) |
        ((para->shareability << MPU_RASR_S_Pos) & MPU_RASR_S_Msk);
⑶  HalMpuRASRAddMemAttr(para, &RASR);
    return RASR;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

小结

本文带领大家一起剖析了鸿蒙轻内核的MPU模块的源代码。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/139526062","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/98316226"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!