【EtherCAT】FMMU和SM简介

目录

一、简介

       1、 FMMU

       2、SM

        (1) 缓冲模式

        (2)邮箱模式

 3、FMMU将物理存储器映射到逻辑过程数据映射的配置原理

二、FMMU和SM在EtherCAT从站控制器的存储空间分配

三、FMMU和SM部分寄存器描述(LAN9253)

1、FMMU

2、SM

四、FMMU和SM的数据结构(soem主站)

 (1)  FMMU数据结构

 (2) SM数据结构

 五、FMMU和SM映射关系代码参考(soem)

六、其他相关链接


一、简介

       1、 FMMU

                Fieldbus Memory Management Unit,现场总线存储器管理单元, 通过内部地址映射逻辑地址转换为物理地址

                FMMU允许跨越多个从设备的数据段使用逻辑地址;一个数据报寻址几个任意分布的EtherCAT从站控制器内的数据。

                每个FMMU通道将一个连续的逻辑地址空间映射到从站的一个连续物理地址空间。

                EtherCAT从站控制器的FMMU支持逐位映射,支持的FMMU数量取决于EtherCAT从站控制器。

                FMMU支持的访问类型可配置为读、写或读/写。   

       2、SM

                Sync Manager, 同步管理;

                直接用EtherCAT从站控制器的存储器实现EtherCAT主站和本地应用程序之间交换数据,没有任何限制,这种直接通过内存通信存在缺点。所以需要SM来同步管理。SM可在EtherCAT主站本地应用程序之间实现一致且安全的数据交换,并生成中断来通知双方发生数据更改。

        SM管理DPRAM,保证了应用数据的一致性和安全性。

        SM由EtherCAT主站配置。

        SM支持两种通信模式。

        (1) 缓冲模式

                缓冲模式允许EtherCAT主站和本地应用程序随时访问通信缓冲区。

                缓冲模式通常应用与循环过程数据。

        (2)邮箱模式

                邮箱模式以握手机制实现数据交换,不会丢数据。

                邮箱模式通常用于应用程序层协议。

 3、FMMU将物理存储器映射到逻辑过程数据映射的配置原理

              

二、FMMU和SM在EtherCAT从站控制器的存储空间分配

      

三、FMMU和SM部分寄存器描述(LAN9253)

1、FMMU

        

2、SM

        

四、FMMU和SM的数据结构(soem主站)

 (1)  FMMU数据结构

/** record for FMMU */
typedef __packed struct
{uint32 LogStart;uint16 LogLength;uint8 LogStartbit;uint8 LogEndbit;uint16 PhysStart;uint8 PhysStartBit;uint8 FMMUtype;uint8 FMMUactive;uint8 unused1;uint16 unused2;} ec_fmmut;

   (2) SM数据结构

/** record for sync manager */
typedef __packed struct
{uint16 StartAddr;uint16 SMlength;uint32 SMflag;
} ec_smt;

五、FMMU和SM映射关系代码参考(soem)

/** Map all PDOs in one group of slaves to IOmap.
*
* @param[in]  context        = context struct
* @param[out] pIOmap     = pointer to IOmap  
* @param[in]  group      = group to map, 0 = all groups  
* @return IOmap size
*/
int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
{uint16 slave, configadr;int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;uint16 SMlength, EndAddr;uint8 BitPos;uint8 SMc, FMMUc;uint32 LogAddr = 0;uint32 oLogAddr = 0;uint32 diff;int nSM, rval;ec_eepromPDOt eepPDO;uint16 currentsegment = 0;uint32 segmentsize = 0;if ((*(context->slavecount) > 0) && (group < context->maxgroup)){  EC_PRINT("ec_config_map_group IOmap:%p group:%d\n \r", pIOmap, group);LogAddr = context->grouplist[group].logstartaddr;oLogAddr = LogAddr;BitPos = 0;context->grouplist[group].nsegments = 0;context->grouplist[group].outputsWKC = 0;context->grouplist[group].inputsWKC = 0;/* find output mapping of slave and program FMMU */for (slave = 1; slave <= *(context->slavecount); slave++){configadr = context->slavelist[slave].configadr;ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n \r",slave, context->slavelist[slave].configadr, context->slavelist[slave].state);/* execute special slave configuration hook Pre-Op to Safe-OP */if(context->slavelist[slave].PO2SOconfig) /* only if registered */{context->slavelist[slave].PO2SOconfig(slave);        }
if(context->slavelist[slave].proc_init) /* only if registered */
{context->slavelist[slave].proc_init(context,slave);        
}if (!group || (group == context->slavelist[slave].group)){  /* if slave not found in configlist find IO mapping in slave self */if (!context->slavelist[slave].configindex){Isize = 0;Osize = 0;if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */{rval = 0;if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access *//* read PDO mapping via CoE and use Complete Access */{rval = ecx_readPDOmapCA(context, slave, &Osize, &Isize);}if (!rval) /* CA not available or not succeeded */{/* read PDO mapping via CoE */rval = ecx_readPDOmap(context, slave, &Osize, &Isize);}EC_PRINT("  CoE Osize:%d Isize:%d\n \r", Osize, Isize);}if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */{/* read AT / MDT mapping via SoE */rval = ecx_readIDNmap(context, slave, &Osize, &Isize);context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8);context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8);EC_PRINT("  SoE Osize:%d Isize:%d\n \r", Osize, Isize);}if (!Isize && !Osize) /* find PDO mapping by SII */{memset(&eepPDO, 0, sizeof(eepPDO));Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0);EC_PRINT("  SII Isize:%d\n \r", Isize);              for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ){  if (eepPDO.SMbitsize[nSM] > 0){  context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);context->slavelist[slave].SMtype[nSM] = 4;EC_PRINT("    SM%d length %d\n \r", nSM, eepPDO.SMbitsize[nSM]);}  }  Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1);EC_PRINT("  SII Osize:%d\n \r", Osize);              for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ){  if (eepPDO.SMbitsize[nSM] > 0){  context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);context->slavelist[slave].SMtype[nSM] = 3;EC_PRINT("    SM%d length %d\n \r", nSM, eepPDO.SMbitsize[nSM]);}  }  }context->slavelist[slave].Obits = Osize;context->slavelist[slave].Ibits = Isize;EC_PRINT("     ISIZE:%d %d OSIZE:%d\n \r",context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits);   }EC_PRINT("  SM programming\n \r"); if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr){ecx_FPWR(context->port, configadr, ECT_REG_SM0,sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);EC_PRINT("    SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n \r",context->slavelist[slave].SMtype[0],context->slavelist[slave].SM[0].StartAddr,context->slavelist[slave].SM[0].SMflags);  }if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr){ecx_FPWR(context->port, configadr, ECT_REG_SM1,sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3);EC_PRINT("    SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n \r",context->slavelist[slave].SMtype[1],context->slavelist[slave].SM[1].StartAddr,context->slavelist[slave].SM[1].SMflags);  }/* program SM2 to SMx */for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ ){  if (context->slavelist[slave].SM[nSM].StartAddr){/* check if SM length is zero -> clear enable flag */if( context->slavelist[slave].SM[nSM].SMlength == 0){context->slavelist[slave].SM[nSM].SMflags =htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);}ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3);EC_PRINT("    SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n \r", nSM,context->slavelist[slave].SMtype[nSM],context->slavelist[slave].SM[nSM].StartAddr,context->slavelist[slave].SM[nSM].SMflags);  }}if (context->slavelist[slave].Ibits > 7){context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8;}if (context->slavelist[slave].Obits > 7){context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8;}FMMUc = context->slavelist[slave].FMMUunused;SMc = 0;BitCount = 0;ByteCount = 0;EndAddr = 0;FMMUsize = 0;FMMUdone = 0;/* create output mapping */if (context->slavelist[slave].Obits){EC_PRINT("  OUTPUT MAPPING\n \r");/* search for SM that contribute to the output mapping */while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8))){  EC_PRINT("    FMMU %d\n \r", FMMUc);while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;EC_PRINT("      SM%d\n \r", SMc);context->slavelist[slave].FMMU[FMMUc].PhysStart =context->slavelist[slave].SM[SMc].StartAddr;SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);ByteCount += SMlength;BitCount += SMlength * 8;EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;while ( (BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */{SMc++;while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ){break;}EC_PRINT("      SM%d\n \r", SMc);SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);ByteCount += SMlength;BitCount += SMlength * 8;EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;              }  /* bit oriented slave */if (!context->slavelist[slave].Obytes){  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;BitPos += context->slavelist[slave].Obits - 1;if (BitPos > 7){LogAddr++;BitPos -= 8;}  FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;BitPos ++;if (BitPos > 7){LogAddr++;BitPos -= 8;}  }/* byte oriented slave */else{if (BitPos){LogAddr++;BitPos = 0;}  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;BitPos = 7;FMMUsize = ByteCount;if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes){FMMUsize = context->slavelist[slave].Obytes - FMMUdone;}LogAddr += FMMUsize;context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;BitPos = 0;}FMMUdone += FMMUsize;context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2;context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;/* program FMMU for output */ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);context->grouplist[group].outputsWKC++;if (!context->slavelist[slave].outputs){  context->slavelist[slave].outputs =(uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);context->slavelist[slave].Ostartbit =context->slavelist[slave].FMMU[FMMUc].LogStartbit;EC_PRINT("    slave %d Outputs %p startbit %d\n \r",slave,context->slavelist[slave].outputs,context->slavelist[slave].Ostartbit);}FMMUc++;}  context->slavelist[slave].FMMUunused = FMMUc;diff = LogAddr - oLogAddr;oLogAddr = LogAddr;if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)){context->grouplist[group].IOsegment[currentsegment] = segmentsize;if (currentsegment < (EC_MAXIOSEGMENTS - 1)){currentsegment++;segmentsize = diff;  }}else{segmentsize += diff;}}}  }if (BitPos){LogAddr++;oLogAddr = LogAddr;BitPos = 0;if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)){context->grouplist[group].IOsegment[currentsegment] = segmentsize;if (currentsegment < (EC_MAXIOSEGMENTS - 1)){currentsegment++;segmentsize = 1;  }}else{segmentsize += 1;}}  context->grouplist[group].outputs = pIOmap;context->grouplist[group].Obytes = LogAddr;context->grouplist[group].nsegments = currentsegment + 1;context->grouplist[group].Isegment = currentsegment;context->grouplist[group].Ioffset = segmentsize;if (!group){  context->slavelist[0].outputs = pIOmap;context->slavelist[0].Obytes = LogAddr; /* store output bytes in master record */}  /* do input mapping of slave and program FMMUs */for (slave = 1; slave <= *(context->slavecount); slave++){configadr = context->slavelist[slave].configadr;FMMUc = context->slavelist[slave].FMMUunused;if (context->slavelist[slave].Obits) /* find free FMMU */{while ( context->slavelist[slave].FMMU[FMMUc].LogStart ) FMMUc++;}SMc = 0;BitCount = 0;ByteCount = 0;EndAddr = 0;FMMUsize = 0;FMMUdone = 0;/* create input mapping */if (context->slavelist[slave].Ibits){EC_PRINT(" =Slave %d, INPUT MAPPING\n \r", slave);/* search for SM that contribute to the input mapping */while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8))){  EC_PRINT("    FMMU %d\n \r", FMMUc);while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;EC_PRINT("      SM%d\n \r", SMc);context->slavelist[slave].FMMU[FMMUc].PhysStart =context->slavelist[slave].SM[SMc].StartAddr;SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);ByteCount += SMlength;BitCount += SMlength * 8;EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;while ( (BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */{SMc++;while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ){break;}EC_PRINT("      SM%d\n \r", SMc);SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);ByteCount += SMlength;BitCount += SMlength * 8;EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;              }  /* bit oriented slave */if (!context->slavelist[slave].Ibytes){  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;BitPos += context->slavelist[slave].Ibits - 1;if (BitPos > 7){LogAddr++;BitPos -= 8;}  FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;BitPos ++;if (BitPos > 7){LogAddr++;BitPos -= 8;}  }/* byte oriented slave */else{if (BitPos){LogAddr++;BitPos = 0;}  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;BitPos = 7;FMMUsize = ByteCount;if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes){FMMUsize = context->slavelist[slave].Ibytes - FMMUdone;}LogAddr += FMMUsize;context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;BitPos = 0;}FMMUdone += FMMUsize;if (context->slavelist[slave].FMMU[FMMUc].LogLength){  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1;context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;/* program FMMU for input */ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);/* add one for an input FMMU */context->grouplist[group].inputsWKC++;}  if (!context->slavelist[slave].inputs){  context->slavelist[slave].inputs =(uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);context->slavelist[slave].Istartbit =context->slavelist[slave].FMMU[FMMUc].LogStartbit;EC_PRINT("    Inputs %p startbit %d\n \r",context->slavelist[slave].inputs,context->slavelist[slave].Istartbit);}FMMUc++;}  context->slavelist[slave].FMMUunused = FMMUc;diff = LogAddr - oLogAddr;oLogAddr = LogAddr;if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)){context->grouplist[group].IOsegment[currentsegment] = segmentsize;if (currentsegment < (EC_MAXIOSEGMENTS - 1)){currentsegment++;segmentsize = diff;  }}else{segmentsize += diff;}  }ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */        ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET3); /* set safeop status */if (context->slavelist[slave].blockLRW){   context->grouplist[group].blockLRW++;                    }context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;}if (BitPos){LogAddr++;oLogAddr = LogAddr;BitPos = 0;if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)){context->grouplist[group].IOsegment[currentsegment] = segmentsize;if (currentsegment < (EC_MAXIOSEGMENTS - 1)){currentsegment++;segmentsize = 1;  }}else{segmentsize += 1;}}  context->grouplist[group].IOsegment[currentsegment] = segmentsize;context->grouplist[group].nsegments = currentsegment + 1;context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes;context->grouplist[group].Ibytes = LogAddr - context->grouplist[group].Obytes;if (!group){  context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes;context->slavelist[0].Ibytes = LogAddr - context->slavelist[0].Obytes; /* store input bytes in master record */}  EC_PRINT("IOmapSize %d\n \r", LogAddr - context->grouplist[group].logstartaddr);     return (LogAddr - context->grouplist[group].logstartaddr);}return 0;
}  

六、其他相关链接

EtherCAT从站开发要点-CSDN博客

【EtherCAT】COE对象字典与PDO映射简介-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/1131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是AIoT?

什么是AIoT? AIoT&#xff0c;即人工智能物联网&#xff0c;是一种将人工智能&#xff08;AI&#xff09;技术与物联网&#xff08;IoT&#xff09;相结合的新型应用形态。它不仅实现了设备之间的互联互通&#xff0c;还赋予了它们更智能化的特性。AIoT的核心在于通过AI的数据…

什么是知乎知+广告推广?

知乎作为中国领先的知识分享社区和高质量用户群体汇聚地&#xff0c;其广告价值日益凸显&#xff0c;其中&#xff0c;“知”作为知乎官方推出的创新广告形式&#xff0c;正逐渐成为品牌与消费者深度连接的重要桥梁。知广告推广不仅局限于传统意义上的硬性推广&#xff0c;更强…

解锁棋盘之谜:探索N皇后问题的全方位解决策略【python 力扣51题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

QML 中引用 js 文件闪退问题

问题描述 在移植 Android 中遇到这样一个引用兼容性问题&#xff0c;起因是这样的&#xff0c;Windows 版本的采用了 QML 分离的方式加载&#xff0c;而 Android 版本又采用了 qrc 的方式。而 Qt 中的机制是采用 QML 分离方式时则使用相对路径的方式引用 js 文件&#xff0c;而…

ZCMU 1531: 序列的混乱程度

Description 有一个长度为n的正整数序列&#xff0c;一个序列的混乱程度定义为这个序列的最大值和最小值之差。请编写一个程序&#xff0c;计算一个序列的混乱程度。 Input 输入的第一行为一个正整数T (T<1000)&#xff0c;表示一共有T组测试数据。 每组测试数据的第一行为一…

前后端跨域请求代码实战(vue3.4+springboot2.7.18)

前端代码 v3.4.21&#xff08;前端不是主业&#xff0c;所以就贴一贴代码&#xff0c;有疑问评论区见&#xff09;后端代码&#xff0c;springboot 2.7.18&#xff08;后端&#xff09; 文章内容&#xff1a; 一&#xff0c;后端代码 二&#xff0c;前端代码 三&#xff0c;后…

【ARM 裸机】I.MX 启动方式之启动头文件 1

接上一节&#xff1a;【ARM 裸机】I.MX 启动方式之启动设备的选择&#xff1b; 2、启动头文件 当 BOOT_MODE1 为 1&#xff0c;BOOT_MODE0 为 0 的时候此内部 BOOT 模式&#xff0c;在此模式下&#xff0c;芯片会执 行内部的 BOOT ROM 代码&#xff0c;这段 BOOT ROM 代码会进…

C++引用和指针的区别

在C中&#xff0c;引用和指针都是用于间接访问变量或对象的工具&#xff0c;但它们之间存在一些重要的区别。 引用&#xff08;Reference&#xff09; 引用是变量的别名&#xff0c;它提供了一个已经存在的变量的另一个名字。一旦一个引用被初始化为一个对象&#xff0c;就不…

tensor是pytorch的核心,那torch.tensor和torch.Tensor区别是?

本文重点 从本节课程开始我们将正式开启pytorch的学习了&#xff0c;在深度学习框架中有一个重要的概念叫做张量&#xff0c;它是pytorch的基本操作单位&#xff0c;要想创建tensor有很多的方式&#xff0c;但是有两个torch.tensor和torch.Tensor容易混淆&#xff0c;本节课程…

javase__进阶 day13stream流和方法引用

1.不可变集合 1.1 什么是不可变集合 ​ 是一个长度不可变&#xff0c;内容也无法修改的集合 1.2 使用场景 ​ 如果某个数据不能被修改&#xff0c;把它防御性地拷贝到不可变集合中是个很好的实践。 ​ 当集合对象被不可信的库调用时&#xff0c;不可变形式是安全的。 简单…

docker快速使用简介

进入服务器 ssh root192.0.0.211安装 docker load < bevformer_image.tar修改镜像的REPOSITORY和TAG docker tag a6a4c15ca9db bevformer:1.0其中&#xff0c;a6a4c15ca9db是原来镜像的id。bevformer是修改后的REPOSITORY&#xff1b;1.0是修改后的TAG。 从Docker Hub上…

高精度加减乘除

高精度加法 题目链接&#xff1a;高精度加法 #include <bits/stdc.h> #define int long long using namespace std; const int N 1e55; int a[N],b[N]; int c[N]; int n,m; string s1,s2;signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>s1…

大厂面试精华面试刷题

1.自定义unshift实现相同效果 2.数组去重 用vs2019来写这种练习题可以更直观的查看代码执行的效果&#xff0c;最后的代码是控制控制台执行完毕后不自动关闭 use strict;let arr [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] //1.//查重最简单的方法for循环结合splice从数组中…

Flask vs FastApi 性能对比测试

Flask和Fastapi都是Python下流行的Web框架&#xff0c;前者有大量拥趸&#xff0c;是一个老牌框架&#xff0c;后者相对较新&#xff0c;但是利用了异步技术和uvloop&#xff0c;都说性能比Flask好很多&#xff0c;于是就我就对比实测一下。由于Windows下不支持uvloop&#xff…

63、ARM/STM32中IIC相关学习20240417

完成温湿度传感器数据采集实验。 【思路&#xff1a;1.通过IIC通信原理&#xff0c;理解其通信过程&#xff0c;通过调用封装的IIC函数达成主机和从机之间&#xff1a;起始信号、终止信号、读、写数据的操作&#xff1b; 2.了解温湿度传感器控制芯片SI7006的工作原理&#…

【C++】飞机大战项目记录

源代码与图片参考自《你好编程》的飞机大战项目&#xff0c;这里不进行展示。 本项目是仅供学习使用的项目 飞机大战项目记录 飞机大战设计报告1 项目框架分析1.1 敌机设计&#xff1a;1.2 玩家飞机控制&#xff1a;1.3 子弹发射&#xff1a;1.4 游戏界面与互动&#xff1a;1.5…

解决Linux根分区空间不足的方法:利用Home分区进行扩容

前言 在进行系统安装时&#xff0c;一个常见的困扰是默认分区设置可能导致home分区拥有过多的空间&#xff0c;而root分区却显得十分紧缺。这种情况下&#xff0c;用户往往会陷入无法继续安装软件或存储文件的困境。本文将向您展示如何通过合理的调整&#xff0c;将home分区中多…

二叉排序树及实现

二叉排序树及实现 二叉排序树&#xff08;Binary Sort Tree, BST&#xff09;又称为二叉查找树。在一般情况下&#xff0c;查询效率要比链表结构要高。对于二叉排序树中的任何一个非叶子节点&#xff0c;要求左子节点的值比当前节点的值小&#xff0c;右子节点的值比当前节点的…

【6】mysql查询性能优化-关联子查询

【README】 0. 先说结论&#xff1a;一般用inner join来改写in和exist&#xff0c;用left join来改写not in&#xff0c;not exist&#xff1b;&#xff08;本文会比较内连接&#xff0c;包含in子句的子查询&#xff0c;exist的性能 &#xff09; 1. 本文总结自高性能mysql 6…

Python 面向对象——1.基本概念

本章学习链接如下&#xff1a; 基本概念与语法 类&#xff08;Class&#xff09;&#xff1a;定义了一组对象共有的属性和方法的蓝图。类是创建对象的模板。 对象&#xff08;Object&#xff09;&#xff1a;类的实例。对象包含实际的数据和操作数据的方法。 属性&#xff0…