AUTOSAR架构下NVMBlock连续写及DefaultValue问题分析

原创 汽车电子嵌入式 2023-07-25 08:01

前言

NVM这块还只停留在按需求配置阶段,遇到问题不能深入分析。本系列文章将从遇到的问题或者提出的疑问着手,一起来更深入学习AUTOSAR架构下的存储协议栈。目前遇到的问题和疑问如下:

1. 通过RTE接口连续读写NVM Block会影响其他Block的读写吗?

2. 没有配置NVM Rom Blockdefault value且没有写过NVM Block,通过RTE接口去读NVM Block读到的是什么值?

3. Fee模块中的Block的长度更改会造成NVM BlockFlash中重排吗?中间插入NVM Block了?

本文使用的AUTOSAR配置工具为:Vector公司的Davinci工具

参考文章:

AUTOSAR存储协议栈-- NVRAM Manager 模块介绍(三)

AUTOSAR存储协议栈-- NVRAM Manager 模块介绍(二)

AUTOSAR存储协议栈-- NVRAM Manager 模块介绍(一)

AUTOSAR存储协议栈-- EEPROM Driver模块介绍

AUTOSAR存储协议栈-- EEPROM Abstraction模块介绍

AUTOSAR存储协议栈-- Memory Abstraction Interface模块介绍

正文

1.应用SWC读写NVM Block的两种方式

入下图所示,VectorAUTOAR配置工具Davinci Developer提供两种方式配置SWC使用NVM的服务。


方式一SWCNVM直连。NVM提供5个标准接口供SWC使用,SWC可以直接通过C-S接口直接读写NVM Block。这种方式适用于NVM Block仅被一个SWC访问的场景

1SWCNVM直连


如下图所示,在Developer中直接配置SWC中的Service NeedNvM_Block_NeeDs即可配置NVM服务。

 

2:配置NvMBlockNeed


最后在Rte_SWC.h生成的读写NvM_Block的接口如下所示,Rte接口直接封装了NvM的标准接口(NvM_ReadBlock, NvM_WriteBlock, NvM_GetErrorStates)。


# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _GetErrorStatus(arg1) (NvM_GetErrorStatus((NvM_BlockIdType)57, arg1))# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _ReadBlock(arg1) (NvM_ReadBlock((NvM_BlockIdType)57, arg1))# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _WriteBlock(arg1) (NvM_WriteBlock((NvM_BlockIdType)57, arg1))


方式二SWC通过NonvolatileMemoryBlock访问NVMDavinci提供一个类似NvM UserNonvolatileMemoryBlock的中间模块,SWC配置普通的S-R接口和NonvolatileMemoryBlock连接,NonvolatileMemoryBlock模块通过标准的S-R接口和NvM连接。 SWC通过NonvolatileMemoryBloc来读写NvM模块。这种方式适用于多个SWC访问同一个NvM Block的场景



3SWC通过NonvolatileMemoryBlock访问NVM


如下图所示,使用方式二需要配置中间NonvolatileMemoryBlock模块,然后在SWCNonvolatileMemoryBlock分别配置S-R的读写接口,然后进行连接即可。

 

4:配置NoVolatileMemoryBlock


如下所示,生成的Rte_SWC.hSWC读写NvM Block的接口仅仅是读写一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName全局变量。


FUNC(Std_ReturnType, RTE_CODE) Rte_Read_SWC_Pp_NvData_PortName_Rx_Element_NvData_PortName(P2VAR(uint8, AUTOMATIC, RTE_SWC_APPL_VAR) data) /* PRQA S 1505, 3206 */ /* MD_MSR_Rule8.7, MD_Rte_3206 */{  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */  Rte_MemCpy(data, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */  return ret;}

FUNC(Std_ReturnType, RTE_CODE) Rte_Write_SWC_Pp_NvData_PortName_Tx_Element_NvData_PortName(P2CONST(uint8, AUTOMATIC, RTE_SWC_APPL_DATA) data) /* PRQA S 1505, 2982 */ /* MD_MSR_Rule8.7, MD_Rte_2982 */{ Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */ Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */ Rte_MemCpy(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, data, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */ Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U; Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */ /* scheduled trigger for runnables: NonVolatileMemoryBlockTriggerRunnable */ (void)SetEvent(AplTask_10ms_Core0, Rte_Ev_Run_NonVolatileMemoryBlock_NonVolatileMemoryBlockTriggerRunnable); /* PRQA S 3417 */ /* MD_Rte_Os */ return ret;}

然后NvM也通过Rte_SetMirror_xxx/Rte_GetMirror_xxx接口来更新这个Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName全局变量。


FUNC(Std_ReturnType, RTE_CODE) Rte_SetMirror_NonVolatileMemoryBlock_NVBlockDescriptor_PortName(P2CONST(void, AUTOMATIC, RTE_APPL_DATA) NVMBuffer) /* PRQA S 3112 */ /* MD_Rte_3112 */{ Std_ReturnType ret = E_NOT_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */ CONST(uint16_least, RTE_CONST) size = sizeof(NvData_PortName); if (size <= 100U) /* PRQA S 2991, 2995 */ /* MD_Rte_2991, MD_Rte_2995 */ /* COV_RTE_NVMBUFFER_SIZE */ { Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */ Rte_MemCpy32(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, NVMBuffer, size); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */ Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */ ret = E_OK; } return ret;}
FUNC(Std_ReturnType, RTE_CODE) Rte_GetMirror_NonVolatileMemoryBlock_NVBlockDescriptor_PortName(P2VAR(void, AUTOMATIC, RTE_APPL_VAR) NVMBuffer) /* PRQA S 3112 */ /* MD_Rte_3112 */{   Std_ReturnType ret = E_NOT_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */ CONST(uint16_least, RTE_CONST) size = sizeof(NvData_PortName); if (size <= 100U) /* PRQA S 2991, 2995 */ /* MD_Rte_2991, MD_Rte_2995 */ /* COV_RTE_NVMBUFFER_SIZE */ { Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */ Rte_MemCpy32(NVMBuffer, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, size); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */ Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */ ret = E_OK; } return ret;}

2.RAM BlockROM Block

RAM Block最后在代码中体现就是一个全局变量(存放在栈Ram中),ROM Block在代码中体现就是一个const 全局变量(存放在Data Flash中)。Ram Block是一定会有的,Rom Block是可配置的。其中最主要的就是default value的配置。


方式1配置RAM BlockROM Block


方式1SWC通过NvM Block Needs直接访问NvM,如果配置了Default Value就配置了ROM Block

 

图5:NvM Block Needs配置RAM和ROM Block


方式2配置RAM BlockROM Block


方式2SWC通过NonvolatileMemoryBlock间接访问NvMRom Block通过勾选来配置,Init Value也就是Default value也可配置。

图5:NonvolatileMemoryBlock配置RAM和ROM Block

 

RAM Block对应的代码:

VAR(Nvdata_PortName, RTE_VAR_INIT) Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName;

ROM Block对应的代码:

CONST(Nvdata_PortName, RTE_CONST_DEFAULT_RTE_CDATA_GROUP) Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName_ROM_NVBlockDescriptor_PortName = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};

关于Default Value:

 

SWS_NvM_00388所诉,在ECU启动阶段,如果配置了ROM BlockNvM_ReadAll会把ROM block中的default value拷贝到RAM Block

 

SWS_NvM_00085所述,如果没有配置ROM Block,则RAM Block的值需要应用来保证。在Davinci Developer中可以配置RAM BlockInit Value,也可以让RAM Block有一个初始值。


如果,我们既没有配置RAM BlockInit value,也没有配置ROM Block,也从没有写过NvBlock,那么我们第一次去读的RAM Block.BSS段的一个全局变量(未初始化的全局变量在.BSS段),而MCU上电后会对.BSS段作清零的操作,也就是说我们会读到0


3. 应用SWC读写NVM过程

SWC通过NonvolatileMemoryBlockNvM Ram BlockSWC就是读一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName的全局变量,也就是RAMBlock


FUNC(Std_ReturnType, RTE_CODE) Rte_Read_SWC_Pp_NvData_PortName_Rx_Element_NvData_PortName(P2VAR(uint8, AUTOMATIC, RTE_SWC_APPL_VAR) data) /* PRQA S 1505, 3206 */ /* MD_MSR_Rule8.7, MD_Rte_3206 */{  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */  Rte_MemCpy(data, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */  return ret;}


SWC通过NonvolatileMemoryBlockNvM Ram BlockSWC就是写一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName的全局变量,也就是RAMBlock。同时会设置一个更新FlagSetEvent触发一个OS Task事件。

FUNC(Std_ReturnType, RTE_CODE) Rte_Write_SWC_Pp_NvData_PortName_Tx_Element_NvData_PortName(P2CONST(uint8, AUTOMATIC, RTE_SWC_APPL_DATA) data) /* PRQA S 1505, 2982 */ /* MD_MSR_Rule8.7, MD_Rte_2982 */{  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */  Rte_MemCpy(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, data, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */  Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U;  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */  /* scheduled trigger for runnables: NonVolatileMemoryBlockTriggerRunnable */  (void)SetEvent(AplTask_10ms_Core0, Rte_Ev_Run_NonVolatileMemoryBlock_NonVolatileMemoryBlockTriggerRunnable); /* PRQA S 3417 */ /* MD_Rte_Os */  return ret;}

NonvolatileMemoryBlockRunnableEvent事件激活调用NvM_WriteBlock:

RTE_LOCAL FUNC(void, RTE_CODE) NonVolatileMemoryBlockTriggerRunnable(void){  if (Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName == 1U)  {    NvM_RequestResultType NvM_ErrorStatus = 0;    (void)NvM_GetErrorStatus(NvMConf_NvMBlockDescriptor_NonVolatileMemoryBlockNVBlockDescriptor_PortName, &NvM_ErrorStatus);    if (NvM_ErrorStatus != NVM_REQ_PENDING)  {    Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */    Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 0;    Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */    (void)NvM_WriteBlock(NvMConf_NvMBlockDescriptor_NonVolatileMemoryBlockNVBlockDescriptor_PortName, NULL_PTR);  }  else  {    Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */    Rte_NvBlockPendingFlags.Rte_NvBlockPendingFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U;    Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */    }  }}

NvM_WriteBlock调用NvM_QueueJobJob排队:

FUNC(Std_ReturnType, NVM_PUBLIC_CODE) NvM_WriteBlock(NvM_BlockIdType BlockId, P2CONST(void, AUTOMATIC, NVM_APPL_DATA) NvM_SrcPtr){    Std_ReturnType returnValue = E_NOT_OK;    uint8 detErrorId = NVM_E_NO_ERROR;
const NvM_RamMngmtPtrType NvM_RamMngmt_ptloc = NvM_GetMngmtAreaPtr(BlockId); if(NvM_WriteProtectionChecks(NvM_RamMngmt_ptloc) == TRUE) /* SBSW_NvM_FuncCall_PtrParam_BlockMngmtArea */ { /* PRQA S 0311, 0316 1 */ /* MD_NvM_11.5_CastLossOfConst, MD_NvM_11.5_JobQueue_CastVoidPtrToObjPtr */ if (NvM_QueueJob(BlockId, NVM_INT_FID_WRITE_BLOCK, (NvM_RamAddressType)NvM_SrcPtr)) /* SBSW_NvM_FuncCall_PtrParam_QueueJob */ {       if(NvM_SrcPtr == NULL_PTR) {       NvM_EnterCriticalSection();       NvM_RamMngmt_ptloc->NvRamAttributes_u8 |= (NVM_STATE_VALID_SET | NVM_STATE_CHANGED_SET); /* SBSW_NvM_AccessBlockManagementArea */       NvM_ExitCriticalSection(); } returnValue = E_OK; }}
return returnValue;}

NvM_QueueJob会判断队列是否已经Full,如果FullJob被丢弃,如果没有Full,则Job入队列:

FUNC(boolean, NVM_PRIVATE_CODE) NvM_QueueJob(NvM_BlockIdType BlockId,NvM_InternalServiceIdType ServiceId,NvM_RamAddressType RamAddress){  boolean retVal = FALSE;  boolean queueFull;  boolean blockAlreadyPending;  /* get block management area */  const NvM_RamMngmtPtrType ramMngmtPtr =  ((BlockId & NVM_DCM_BLOCK_OFFSET) != 0u) ? (&NvM_DcmBlockMngmt_t) : (&NvM_BlockMngmtArea_at[BlockId]);  #if(NVM_JOB_PRIORISATION == STD_ON)  const uint8 priority = (uint8)NvM_BlockDescriptorTable_at[NVM_BLOCK_FROM_DCM_ID(BlockId)].BlockPrio_u8;  /* NvM_HighPrioQueue is only the right queue if block has an immediate priority, current job is a  write-job and requested block is not a DCM-Block. Otherwise NvM_NormalPrioQueue is right queue. */  P2VAR(NvM_JobQueueType, AUTOMATIC, NVM_PRIVATE_DATA) usedQueue =  ((priority == 0u) && (ServiceId == NVM_INT_FID_WRITE_BLOCK) && ((BlockId & NVM_DCM_BLOCK_OFFSET) == 0u)) ?  (&NvM_HighPrioQueue) : (&NvM_NormalPrioQueue);  #else  P2VAR(NvM_JobQueueType, AUTOMATIC, NVM_PRIVATE_DATA) usedQueue = &NvM_NormalPrioQueue;  #endif  /* #200 critical section (Reason: During accessing the job queue, it shall not be possible to access it from another task) */  NvM_EnterCriticalSection();  /* check queue fill status before queuing the block! */  queueFull = (usedQueue->EmptyList == NVM_LIST_END);  blockAlreadyPending = (ramMngmtPtr->NvRamErrorStatus_u8 == NVM_REQ_PENDING);  /* #210 queue is not full and the requested block isn't already pending */  if((queueFull == FALSE) && (blockAlreadyPending == FALSE))  {    /* #211 find next free element in queue */    const NvM_QueueEntryRefType elem = NvM_QueuePop(&usedQueue->EmptyList); /* SBSW_NvM_FuncCall_PtrParam_Queue */    CONSTP2VAR(NvM_QueueEntryType, AUTOMATIC, NVM_PRIVATE_DATA) elemPtr = &NvM_JobQueue_at[elem];    /* #212 setup and queue NvM job */    elemPtr->BlockId   = BlockId; /* SBSW_NvM_AccessJobQueue */    elemPtr->RamAddr_t = RamAddress; /* SBSW_NvM_AccessJobQueue */    elemPtr->ServiceId = ServiceId; /* SBSW_NvM_AccessJobQueue */    #if(NVM_JOB_PRIORISATION == STD_ON)    elemPtr->JobPrio = priority; /* SBSW_NvM_AccessJobQueue */    #endif    NvM_QueuePush(&usedQueue->SrvList, elem); /* SBSW_NvM_FuncCall_PtrParam_Queue */    /* #213 set the block status to NVM_REQ_PENDING */    ramMngmtPtr->NvRamErrorStatus_u8 = NVM_REQ_PENDING; /* SBSW_NvM_AccessBlockManagementArea */    /* block queued and pending, return successfully */    retVal = TRUE;    }  return retVal;}

综上所述,SWC读写NvM接口的时候,其实读写的是一个Ram Block的全局变量。调用写NvM的接口时会触发NonvolatileMemoryBlockNonVolatileMemoryBlockTriggerRunnableOs调用,NonVolatileMemoryBlockTriggerRunnable根据Block的写Flag调用NvM_WriteBlockNvM_WriteBlock中调用NvM_QueueJobNvM_QueueJob根据队列是否Full来将Job入队列。


也就是说,如果有SWC一直在频繁的调用写NvM的接口,就会导致NvM的队列Full,导致其他的SWC的写NvM Block的请求被丢弃,最终对外表现是NvM存不进去。

 

Ps: 本人就遇到过队列大小配的太小,导致SWCNvM写请求被丢弃的问题。。。


4. 问题回答

问题1:通过RTE接口连续读写NVM Block会影响其他Block的读写吗?

答:会。如果SWC连续写NvM Block,且NvM模块的队列大小配置太小,就会导致NvM模块的队列FullSWC的写请求被丢弃。


问题2:没有配置NVM Rom Blockdefault value且没有写过NVM Block,通过RTE接口去读NVM Block读到的是什么值?

答:要看有没有配置NvM Ram BlockInit Value。如果配置NvM Ram BlockInit Value,那么读到的就是NvM Ram BlockInit Value,如果没有配置,读到的就是0


问题3Fee模块中的Block的长度更改会是的NVM BlockFlash中重排吗?中间插入NVM Block了?

答:还没研究透彻,请关注本公众号的后续文章。


5. 总结

搞清楚了NVM的基本概念后,配置都比较容易。难的是出现问题后怎么查问题,因为NvMFee/EAFls/EEProm模块的实现还是很复杂的,常见的问题如下:

nSWC开发者抱怨NvM数据存不进去


nSWC开发者抱怨NvM数据在ECU复位变成了默认值


nSWC开发者抱怨NvM数据在ECU复位后改成了异常值


如果,存储协议栈配置本身没有问题,常见的原因如下:

nNvM队列配置太小,以及SWC在频繁的请求写NvM


nSWC在下电前把自己的Block写成了默认值,这个时候,我们可以通过修改NvM BlockDefault Value为另一个值来证明不是NvM本身的问题,是SWC自己写了个Default value


n用来接收NvM读数据的SWC的全局变量复位后并不是直接从NvM读取数据,而是从Back Ram(复位后内容不清除)中读取数据,Back Ram异常后导致接收NvM数据的全局变量内容错乱。


如果不是以上的问题,那就可能是NvM本身或者ECU系统出问题了,这就需要深入分析NvM源码加调试了。


推荐阅读

汽车电子嵌入式精彩文章汇总第一期:20210530-20230703

AUTOSAR 架构下EcuM唤醒源事件详解


End




欢迎点赞,关注,转发,在看,您的每一次鼓励,都是我最大的动力!

汽车电子嵌入式

微信扫描二维码,关注我的公众号


评论 (0)
  • 退火炉,作为热处理设备的一种,广泛应用于各种金属材料的退火处理。那么,退火炉究竟是干嘛用的呢?一、退火炉的主要用途退火炉主要用于金属材料(如钢、铁、铜等)的热处理,通过退火工艺改善材料的机械性能,消除内应力和组织缺陷,提高材料的塑性和韧性。退火过程中,材料被加热到一定温度后保持一段时间,然后以适当的速度冷却,以达到改善材料性能的目的。二、退火炉的工作原理退火炉通过电热元件(如电阻丝、硅碳棒等)或燃气燃烧器加热炉膛,使炉内温度达到所需的退火温度。在退火过程中,炉内的温度、加热速度和冷却速度都可以根
    锦正茂科技 2025-04-02 10:13 113浏览
  • 文/Leon编辑/cc孙聪颖‍步入 2025 年,国家进一步加大促消费、扩内需的政策力度,家电国补政策将持续贯穿全年。这一利好举措,为行业发展注入强劲的增长动力。(详情见:2025:消费提振要靠国补还是“看不见的手”?)但与此同时,也对家电企业在战略规划、产品打造以及市场营销等多个维度,提出了更为严苛的要求。在刚刚落幕的中国家电及消费电子博览会(AWE)上,家电行业的竞争呈现出胶着的态势,各大品牌为在激烈的市场竞争中脱颖而出,纷纷加大产品研发投入,积极推出新产品,试图提升产品附加值与市场竞争力。
    华尔街科技眼 2025-04-01 19:49 256浏览
  • 北京贞光科技有限公司作为紫光同芯授权代理商,专注于为客户提供车规级安全芯片的硬件供应与软件SDK一站式解决方案,同时配备专业技术团队,为选型及定制需求提供现场指导与支持。随着新能源汽车渗透率突破40%(中汽协2024数据),智能驾驶向L3+快速演进,车规级MCU正迎来技术范式变革。作为汽车电子系统的"神经中枢",通过AEC-Q100 Grade 1认证的MCU芯片需在-40℃~150℃极端温度下保持μs级响应精度,同时满足ISO 26262 ASIL-D功能安全要求。在集中式
    贞光科技 2025-04-02 14:50 238浏览
  • 职场之路并非一帆风顺,从初入职场的新人成长为团队中不可或缺的骨干,背后需要经历一系列内在的蜕变。许多人误以为只需努力工作便能顺利晋升,其实核心在于思维方式的更新。走出舒适区、打破旧有框架,正是让自己与众不同的重要法宝。在这条道路上,你不只需要扎实的技能,更需要敏锐的观察力、不断自省的精神和前瞻的格局。今天,就来聊聊那改变命运的三大思维转变,让你在职场上稳步前行。工作初期,总会遇到各式各样的难题。最初,我们习惯于围绕手头任务来制定计划,专注于眼前的目标。然而,职场的竞争从来不是单打独斗,而是团队协
    优思学院 2025-04-01 17:29 254浏览
  • 提到“质量”这两个字,我们不会忘记那些奠定基础的大师们:休哈特、戴明、朱兰、克劳士比、费根堡姆、石川馨、田口玄一……正是他们的思想和实践,构筑了现代质量管理的核心体系,也深远影响了无数企业和管理者。今天,就让我们一同致敬这些质量管理的先驱!(最近流行『吉卜力风格』AI插图,我们也来玩玩用『吉卜力风格』重绘质量大师画象)1. 休哈特:统计质量控制的奠基者沃尔特·A·休哈特,美国工程师、统计学家,被誉为“统计质量控制之父”。1924年,他提出世界上第一张控制图,并于1931年出版《产品制造质量的经济
    优思学院 2025-04-01 14:02 159浏览
  • 据先科电子官方信息,其产品包装标签将于2024年5月1日进行全面升级。作为电子元器件行业资讯平台,大鱼芯城为您梳理本次变更的核心内容及影响:一、标签变更核心要点标签整合与环保优化变更前:卷盘、内盒及外箱需分别粘贴2张标签(含独立环保标识)。变更后:环保标识(RoHS/HAF/PbF)整合至单张标签,减少重复贴标流程。标签尺寸调整卷盘/内盒标签:尺寸由5030mm升级至**8040mm**,信息展示更清晰。外箱标签:尺寸统一为8040mm(原7040mm),提升一致性。关键信息新增新增LOT批次编
    大鱼芯城 2025-04-01 15:02 235浏览
  • 在智能交互设备快速发展的今天,语音芯片作为人机交互的核心组件,其性能直接影响用户体验与产品竞争力。WT588F02B-8S语音芯片,凭借其静态功耗<5μA的卓越低功耗特性,成为物联网、智能家居、工业自动化等领域的理想选择,为设备赋予“听得懂、说得清”的智能化能力。一、核心优势:低功耗与高性能的完美结合超低待机功耗WT588F02B-8S在休眠模式下待机电流仅为5μA以下,显著延长了电池供电设备的续航能力。例如,在电子锁、气体检测仪等需长期待机的场景中,用户无需频繁更换电池,降低了维护成本。灵活的
    广州唯创电子 2025-04-02 08:34 189浏览
  • 文/郭楚妤编辑/cc孙聪颖‍不久前,中国发展高层论坛 2025 年年会(CDF)刚刚落下帷幕。本次年会围绕 “全面释放发展动能,共促全球经济稳定增长” 这一主题,吸引了全球各界目光,众多重磅嘉宾的出席与发言成为舆论焦点。其中,韩国三星集团会长李在镕时隔两年的访华之行,更是引发广泛热议。一直以来,李在镕给外界的印象是不苟言笑。然而,在论坛开幕前一天,李在镕却意外打破固有形象。3 月 22 日,李在镕与高通公司总裁安蒙一同现身北京小米汽车工厂。小米方面极为重视此次会面,CEO 雷军亲自接待,小米副董
    华尔街科技眼 2025-04-01 19:39 254浏览
  • 随着汽车向智能化、场景化加速演进,智能座舱已成为人车交互的核心承载。从驾驶员注意力监测到儿童遗留检测,从乘员识别到安全带状态判断,座舱内的每一次行为都蕴含着巨大的安全与体验价值。然而,这些感知系统要在多样驾驶行为、复杂座舱布局和极端光照条件下持续稳定运行,传统的真实数据采集方式已难以支撑其开发迭代需求。智能座舱的技术演进,正由“采集驱动”转向“仿真驱动”。一、智能座舱仿真的挑战与突破图1:座舱实例图智能座舱中的AI系统,不仅需要理解驾驶员的行为和状态,还要同时感知乘员、儿童、宠物乃至环境中的潜在
    康谋 2025-04-02 10:23 203浏览
  • 引言在语音芯片设计中,输出电路的设计直接影响音频质量与系统稳定性。WT588系列语音芯片(如WT588F02B、WT588F02A/04A/08A等),因其高集成度与灵活性被广泛应用于智能设备。然而,不同型号在硬件设计上存在关键差异,尤其是DAC加功放输出电路的配置要求。本文将从硬件架构、电路设计要点及选型建议三方面,解析WT588F02B与F02A/04A/08A的核心区别,帮助开发者高效完成产品设计。一、核心硬件差异对比WT588F02B与F02A/04A/08A系列芯片均支持PWM直推喇叭
    广州唯创电子 2025-04-01 08:53 230浏览
  • 探针本身不需要对焦。探针的工作原理是通过接触被测物体表面来传递电信号,其精度和使用效果取决于探针的材质、形状以及与检测设备的匹配度,而非对焦操作。一、探针的工作原理探针是检测设备中的重要部件,常用于电子显微镜、坐标测量机等精密仪器中。其工作原理主要是通过接触被测物体的表面,将接触点的位置信息或电信号传递给检测设备,从而实现对物体表面形貌、尺寸或电性能等参数的测量。在这个过程中,探针的精度和稳定性对测量结果具有至关重要的影响。二、探针的操作要求在使用探针进行测量时,需要确保探针与被测物体表面的良好
    锦正茂科技 2025-04-02 10:41 128浏览
我要评论
0
3
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦