当前位置: 首页 > news >正文

内存泄漏系列专题分析之三十二:高通相机CamX ION/dmabuf内存管理机制CmdBuffer

【关注我,后续持续新增专题博文,谢谢!!!】

上一篇我们讲了

        这一篇我们开始讲 内存泄漏系列专题分析之三十二:高通相机CamX ION/dmabuf内存管理机制CmdBuffer

目录

一、背景

二、:CmdBufferManager管理单元

    2.1:CmdBufferManager初始化

    2.2:CmdBufferManager获取buffer

三、:Camx CmdBuffer模块

    3.1:CmdBuffer初始化

    3.2 :CmdBuffer核心接口

    3.3 :CmdBuffer核心接口使用方式

    3.4 :CmdBuffer中sensor上电命令形式

四、:总结


一、背景

        Camx HAL层ION Buffer可以分为两类:ImageBuffer和CmdBuffer。这篇博文就CmdBuffer模块进行分析介绍。

        了解过高通Camx架构,一般知道bringup的开发并非都在kernel层,chi-cdk用户态也存在大量bringup开发工作,而用户态sensor等xml配置类似内核态dts配置一样,chi-cdk用户态存在大量sensor、马达等硬件bringup代码,需要讲xml配置通过CmdBuffer的方式下发到kernel去执行最终的驱动代码。

二、:CmdBufferManager管理单元

    2.1:CmdBufferManager初始化

CmdBufferManager::Initialize是对CmdBufferManager进行初始化,可以看到核心代码只有一行:可以知道最终还是同ImageBuffer一样由CSLAlloc分配ION内存。

X:\bruce\SI\camx\src\core\camxcmdbuffermanager.cppCamxResult CmdBufferManager::Initialize(const CHAR*             pBufferManagerName,const ResourceParams*   pParams)
{{CAMX_ASSERT(NULL != pBufferManagerName);OsUtils::StrLCpy(m_pBufferManagerName, pBufferManagerName, sizeof(m_pBufferManagerName));m_params         = *pParams;result = InitializePool();}m_pLock = Mutex::Create("CmdBufferManager");return result;
}CamxResult CmdBufferManager::InitializePool()
{CamxResult result = CamxResultSuccess;CAMX_ASSERT((0 != m_params.resourceSize) && (0 == (m_params.poolSize % m_params.resourceSize)));if ((0 == m_params.resourceSize) || (0 != (m_params.poolSize % m_params.resourceSize))){result = CamxResultEInvalidArg;}else{SIZE_T  allocationSize  = 0;UINT32  flags           = m_params.memFlags;m_numResources          = m_params.poolSize / m_params.resourceSize;CSLBufferInfo*  pBufferInfo = static_cast<CSLBufferInfo*>(CAMX_CALLOC(sizeof(CSLBufferInfo)));if (NULL == m_pParentBufferManager){if (NULL != pBufferInfo){result = CSLAlloc(m_pBufferManagerName,pBufferInfo,allocationSize,m_params.alignment,flags,m_params.pDeviceIndices,m_params.numDevices);}}
}

    2.2:CmdBufferManager获取buffer

  1. CmdBufferManager获取buffer主要通过GetBuffer和GetBufferForRequest两个接口,返回都是PacketResource,它对应的就是CmdBuffer中CSLBufferInfo,本质就是xml的命令配置。
  2. CmdBufferManager是管理 CmdBuffer的,CmdBufferManager中有2条链表 m_busyPool和m_freePool,其中:m_freePool中存放着空闲的Buffer,m_busyPool中存放着正在被client 使用的Buffer。
CamxResult CmdBufferManager::GetBuffer(PacketResource** ppBuffer)
{LDLLNode* pNode = m_freePool.RemoveFromHead();if (NULL != pNode){*ppBuffer = static_cast<PacketResource*>(pNode->pData);if (NULL == *ppBuffer){result = CamxResultEInvalidState;}else{// Check canaryif (TRUE == (*ppBuffer)->GetUsageFlags().batchedPacket){BatchedPacket* pBatchedPacket = static_cast<BatchedPacket*>(*ppBuffer);pBatchedPacket->CheckCanary();}(*ppBuffer)->Reset();(*ppBuffer)->SetRequestId(CamxInvalidRequestId);}CAMX_FREE(pNode);}m_pLock->Unlock();return result;
}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// CmdBufferManager::GetBufferForRequest
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CmdBufferManager::GetBufferForRequest(UINT64           requestId,PacketResource** ppBuffer)
{CamxResult result = GetBuffer(ppBuffer);m_pLock->Lock();if (CamxResultSuccess == result){CAMX_ASSERT(NULL != *ppBuffer);(*ppBuffer)->SetRequestId(requestId);LDLLNode* pNode = static_cast<LDLLNode*>(CAMX_CALLOC(sizeof(LDLLNode)));if (NULL != pNode){pNode->pData = *ppBuffer;m_busyPool.InsertToTail(pNode);m_peakNumResourcesUsed = Utils::MaxUINT(m_peakNumResourcesUsed, m_busyPool.NumNodes());}else{result = CamxResultENoMemory;}}m_pLock->Unlock();return result;
}

三、:Camx CmdBuffer模块

    3.1:CmdBuffer初始化

CmdBuffer初始化本质是对PacketResource进行初始化,再对CSLBufferInfo进行封装。

X:\bruce\SI\camx\src\core\camxcmdbuffer.cppCamxResult CmdBuffer::Initialize(const CmdParams*        pParams,const CSLBufferInfo*    pBufferInfo,SIZE_T                  offset,SIZE_T                  size)
{if (NULL == pParams){CAMX_LOG_ERROR(CamxLogGroupUtils, "Invalid input params");return CamxResultEInvalidPointer;}CamxResult result = PacketResource::Initialize(pBufferInfo, offset, size);return result;
}CamxResult PacketResource::Initialize(const CSLBufferInfo*    pBufferInfo,SIZE_T                  offset,SIZE_T                  size)
{CamxResult result = CamxResultSuccess;if ((NULL == pBufferInfo) || (CSLInvalidHandle == pBufferInfo->hHandle)){result = CamxResultEInvalidArg;CAMX_LOG_ERROR(CamxLogGroupUtils, "Invalid packet initialization args");}else{m_bufferInfo    = *pBufferInfo;m_offsetInBytes = offset;m_sizeInBytes   = size;m_pUserdata     = NULL;m_requestId     = CamxInvalidRequestId;}return result;
}

    3.2 :CmdBuffer核心接口

CmdBuffer核心接口主要是这三个:

  1. CmdBuffer::BeginCommands:CSL开始准备下发命令到kernel
  2. CmdBuffer::CommitCommands:CSL正式提交命令到kernel
  3. CmdBuffer::CancelCommands:CSL取消下发命令到kernel
VOID* CmdBuffer::BeginCommands(UINT32 numDwordsToReserve)
{VOID* pDwords = NULL;if ((GetNumDwordsAvailable() >= numDwordsToReserve) && (0 != numDwordsToReserve)){pDwords = GetCurrentWriteAddr();m_pendingDwords = numDwordsToReserve;// Put a canary to check in commit for overrun// This requires that we allocate one extra dword for command buffers (in command buffer manager)*static_cast<UINT*>(Utils::VoidPtrInc(pDwords, numDwordsToReserve * sizeof(UINT32))) = CamxCanary;}else{CAMX_LOG_ERROR(CamxLogGroupUtils, "Failed to reserve words-Dwords needed:%d, Dwords Available:%d",numDwordsToReserve,GetNumDwordsAvailable());}return pDwords;
}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// CmdBuffer::CommitCommands
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CmdBuffer::CommitCommands()
{CamxResult result = CamxResultSuccess;CAMX_ASSERT_MESSAGE(GetNumDwordsAvailable() >= m_pendingDwords,"Pending dwords: %d to commit is greater than available dwords: %d",m_pendingDwords, GetNumDwordsAvailable());if (0 >= m_pendingDwords){CAMX_LOG_ERROR(CamxLogGroupUtils, "Invalid Command buffer state pending dwords: %d",m_pendingDwords);result = CamxResultEInvalidState;}else{// check for overrunCAMX_ASSERT(CamxCanary == *static_cast<UINT*>(Utils::VoidPtrInc(GetCurrentWriteAddr(),m_pendingDwords * sizeof(UINT32))));m_resourceUsedDwords += m_pendingDwords;m_pendingDwords = 0;}return result;
}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// CmdBuffer::CancelCommands
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CmdBuffer::CancelCommands()
{CamxResult result = CamxResultSuccess;m_pendingDwords = 0;return result;
}

    3.3 :CmdBuffer核心接口使用方式

下面就是OIS和马达bingup代码通过这些接口下发xml命令到kernel

camx/src/swl/sensor/camxois.cpp
result = m_pI2CInfoCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = m_pPowerCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = m_pPowerCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = m_pInitializeCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pCalibrateCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pOisModeCmdBuffer->CommitCommands(); in ConfigureOISMode()camx/src/swl/sensor/camxactuator.cpp
result = pI2CInfoCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pPowerCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pPowerCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pInitializeCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pMoveFocusCmdBuffer->CommitCommands(); in MoveFocus()camx/src/swl/sensor/camxactuator.cpp
CmdBuffer* pInitializeCmdBuffer = NULL; in CreateInitializePacket() local
pInitializeCmdBuffer = m_pParentNode->GetCmdBuffer(m_pInitializeCmdManager); in CreateInitializePacket()
(NULL == pInitializeCmdBuffer)) in CreateInitializePacket()
pInitializeCmdBuffer); in CreateInitializePacket()
pCmdBegin = pInitializeCmdBuffer->BeginCommands(initializeCmdSize / sizeof(UINT32)); in CreateInitializePacket()
result = pInitializeCmdBuffer->CommitCommands(); in CreateInitializePacket()
result = pPacket->AddCmdBufferReference(pInitializeCmdBuffer, NULL); in CreateInitializePacket()
m_pInitializeCmdManager->Recycle(pInitializeCmdBuffer); in CreateInitializePacket()

    3.4 :CmdBuffer中sensor上电命令形式

以下就是imxxxx_sensor.xml配置的sensor上电的时序,最终会通过代码读取并封装到PacketResource打包成CmdBuffer,再下发大kernel。【camx chi bringup解析xml并下发kernel后面单独介绍,流程漫长】

    <powerUpSequence><!--Power setting configurationContains: configType, configValue and delay in milli seconds --><powerSetting><!--Power configuration typeSupported types are: MCLK, VANA, VDIG, VIO, VAF, RESET, STANDBY --><configType>RESET</configType><!--Configuration value for the type of configuration --><configValue>0</configValue><!--Delay in milli seconds --><delayMs>1</delayMs></powerSetting><!--Power setting configurationContains: configType, configValue and delay in milli seconds --><powerSetting><configType>VANA</configType><configValue>0</configValue><delayMs>1</delayMs></powerSetting><powerSetting><configType>VDIG</configType><configValue>0</configValue><delayMs>1</delayMs></powerSetting><powerSetting><configType>VIO</configType><configValue>0</configValue><delayMs>0</delayMs></powerSetting><powerSetting><configType>MCLK</configType><configValue>24000000</configValue><delayMs>1</delayMs></powerSetting><powerSetting><configType>RESET</configType><configValue>1</configValue><delayMs>18</delayMs></powerSetting></powerUpSequence>

四、:总结

        Camx CmdBufferManager和CmdBuffer之间的核心关系如上所述:CmdBufferManager通过GetBuffer的有2条链表 m_busyPool和m_freePool拿到CmdBuffer。

       

        CmdBuffer核心接口主要是这三个:

  1. CmdBuffer::BeginCommands:CSL开始准备下发命令到kernel
  2. CmdBuffer::CommitCommands:CSL正式提交命令到kernel
  3. CmdBuffer::CancelCommands:CSL取消下发命令到kernel

【关注我,后续持续新增专题博文,谢谢!!!】

下一篇讲解

http://www.dtcms.com/a/319217.html

相关文章:

  • 【3D图像技术分析与实现】谷歌的AlphaEarth是如何实现的?
  • 鸿蒙RichEditor
  • 使用萤石云播放视频及主题模版配置
  • python安装部署rknn-toolkit2(ModuleNotFoundError: No module named ‘rknn_toolkit2‘)
  • 技术速递|Copilot Coding Agent:自定义设置步骤更可靠、更易于调试
  • P8250 交友问题
  • 表单元素与美化技巧:打造用户友好的交互体验
  • zookeeper因jute.maxbuffer启动异常问题排查处理
  • 如何开发一个运行在windows系统服务器上的服务
  • “物联网+职业本科”:VR虚拟仿真实训室的发展前景
  • 纳米陶瓷与光子集成:猎板PCB定义下一代VR硬件的技术蓝图
  • 【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)
  • 飞机起落架轮轴深孔中间段电解扩孔内轮廓测量 - 激光频率梳 3D 轮廓检测
  • 如何将Dubbo从Zookeeper平滑地迁移到Nacos?
  • 38.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--增加日志记录器
  • Android视图状态以及重绘
  • Java面试宝典:类加载
  • 利用vue.js2X写前端搜索页面,express写后端API接口展现搜索数据
  • SymPy 中 atan2(y, x)函数的深度解析
  • vue3对比vue2的性能优化和提升 :Vue 3 vs Vue 2
  • ArkTS: McPointChart
  • 【Redis面试精讲 Day 16】Redis性能监控与分析工具
  • 从Web2.0到Web3.0——用户体验如何演进
  • 树莓派安装中文输入法
  • Day09 Tlisa登录认证
  • Linux总线,设备和驱动关系以及匹配机制解析
  • FPGA学习笔记——VGA显示静态图片(ROM IP核)
  • 【博弈 拓扑序 缩点】P9220 「TAOI-1」椎名真昼|省选-
  • Bosco-and-Mancuso Filter for CFA Image Denoising
  • 如何快速掌握Excel公式?14天轻松通关