This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工程师,您好!
我们现在想要实现的一个功能是从 6678每次启动后通过网络下载程序,如果成功下载到程序,将程序写入flash覆盖之前的程序,并从flash启动程序,如果没有下载到程序,则从flash启动之前加载的程序。我看到c6678的ibl可以通过tftp下载程序,我就想每次通过ibl从网络启动,连接tftp服务器,从服务器下载程序,并将下载好的程序写入flash,并启动程序。如果没有下载到程序,就直接从flash启动。
现在遇到的问题是,1、我看ibl源码的时候对ibl网络启动的启动流程看不明白;2、ibl通过网络连接到tftp服务器后下载到的文件存放在了哪个位置?3、ibl源码中nor/nand flash驱动都只提供了读的api,没有写的api;4、关于启动文件格式,ccs中建立工程时,选择elf格式,则生成的.out文件为elf格式,我看到网上有些资料中写到,可以直接将.out文件改名为.bin文件,ibl就可以直接识别启动了,而ethbot函数中.bin文件对应的是blob格式,那这种操作方式正确吗?通过device.h中设置启动文件格式时有blob和elf两种,我应该如何设置。
另外官方是否有关于这方面的资料,能否提供一下,谢谢
void iblEthBoot(Int32 eIdx) { NET_DRV_DEVICE nDevice; Uint32 nl; Uint32 entry; Int32 n; Int32 dataSize; Int32 format; void(*exit)(); uint8 buf[16]; char *ext; unsigned int i, j; //给网络启动相关设备上电、配置网络启动相关设备 /* Power up the device. No action is taken if the device is already powered up */ if (devicePowerPeriph(TARGET_PWR_ETH(ibl.bootModes[eIdx].port)) < 0) return; /* Do any mdio configuration */ if (ibl.mdioConfig.nMdioOps > 0) hwMdio(ibl.mdioConfig.nMdioOps, ibl.mdioConfig.mdio, ibl.mdioConfig.mdioClkDiv, ibl.mdioConfig.interDelay); for (j = 0; j < 0x100; j++) for (i = 0; i < 0x1000000; i++); /* SGMII configuration. If sgmii is not present this statement is defined * to void in target.h */ for (n = 0; n < ibl_N_ETH_PORTS; n++) { if (ibl.sgmiiConfig[n].configure == TRUE) hwSgmiiConfig(n, &ibl.sgmiiConfig[n]); } #ifdef DEVICE_CPSW /* On chip switch configuration */ hwCpswConfig(targetGetSwitchCtl(), targetGetSwitchMaxPktSize()); #endif #ifdef DEVICE_QM /* Queue manager configuration */ hwQmSetup((qmConfig_t *)(targetGetQmConfig())); targetInitQs(); #endif #ifdef DEVICE_CPDMA /* Cpdma configuration. */ hwCpdmaRxConfig((cpdmaRxCfg_t *)targetGetCpdmaRxConfig()); hwCpdmaTxConfig((cpdmaTxCfg_t *)targetGetCpdmaTxConfig()); #endif #ifdef DEVICE_PA /* Packet accelerator configuration. If PA is not present this statement is defined * to void in target.h */ targetPaConfig(ibl.bootModes[eIdx].u.ethBoot.ethInfo.hwAddress); #endif #ifdef DEVICE_SS /* Streaming switch configuration. If not present this statement is defined to void * in target.h. If present this is usually defined to a series of register writes */ hwConfigStreamingSwitch(); #endif nDevice.port_num = ibl.bootModes[eIdx].port; //驱动初始化、参数从主机字节序转换为网络字节序 /* Simple transation to initialize the driver */ netMemcpy(nDevice.mac_address, ibl.bootModes[eIdx].u.ethBoot.ethInfo.hwAddress, sizeof(nDevice.mac_address)); nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.ipAddr); if (ibl.bootModes[eIdx].u.ethBoot.doBootp == TRUE) nDevice.ip_address = 0; else nDevice.ip_address = htonl(nl); nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.netmask); nDevice.net_mask = htonl(nl); nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.serverIp); nDevice.server_ip = htonl(nl); nDevice.use_bootp_server_ip = ibl.bootModes[eIdx].u.ethBoot.useBootpServerIp; /* Note - the file name structure in nDevice is only 64 bytes, but 128 in ethInfo */ netMemcpy(nDevice.file_name, ibl.bootModes[eIdx].u.ethBoot.ethInfo.fileName, sizeof(nDevice.file_name)); nDevice.use_bootp_file_name = ibl.bootModes[eIdx].u.ethBoot.useBootpFileName; nDevice.start = cpmac_drv_start; nDevice.stop = cpmac_drv_stop; nDevice.send = cpmac_drv_send; nDevice.receive = cpmac_drv_receive; /* have_params will be set to true in the tftp call back. It must be * set to false before opening the module, since the call back will * be from the open call if bootp is not used */ have_params = FALSE; //开启网络设备 /* Open the network device */ if ((*net_boot_module.open) ((void *)&nDevice, ibl_rec_params) != 0) return; //等待从网络启动参数中获取将要下载的文件名 /* Wait for the callback with the requested filename */ while (have_params == FALSE) { if ((*net_boot_module.peek) ((uint8 *)&nl, sizeof(nl)) < 0) { (*net_boot_module.close)(); return; } } //从网络启动参数中获取启动文件格式 format = ibl.bootModes[eIdx].u.ethBoot.bootFormat; //根据启动文件名的后缀判断启动格式 /* If the data format was based on the name extension, determine * the boot data format */ if (format == ibl_BOOT_FORMAT_NAME) { ext = strrchr(iblStatus.ethParams.fileName, '.'); if (ext != NULL) { if (!strcmp(ext, ".bis")) format = ibl_BOOT_FORMAT_BIS; else if (!strcmp(ext, ".ais")) format = ibl_BOOT_FORMAT_BIS; else if (!strcmp(ext, ".out")) format = ibl_BOOT_FORMAT_COFF; else if (!strcmp(ext, ".coff")) format = ibl_BOOT_FORMAT_COFF; else if (!strcmp(ext, ".btbl")) format = ibl_BOOT_FORMAT_BTBL; else if (!strcmp(ext, ".bin")) format = ibl_BOOT_FORMAT_BBLOB; else if (!strcmp(ext, ".blob")) format = ibl_BOOT_FORMAT_BBLOB; } /* Name match failed it didn't change */ if (format == ibl_BOOT_FORMAT_NAME) { iblStatus.nameDetectFailCnt += 1; /* Close up the peripheral */ (*net_boot_module.close)(); return; } } //调用iblboot启动,iblboot返回程序入口地址 entry = iblBoot(&net_boot_module, format, &ibl.bootModes[eIdx].u.ethBoot.blob); //读取启动文件到RAM /* Before closing the module read any remaining data. In the coff boot mode the boot may * detect an exit before the entire file has been read. Read the rest of the file * to make the server happy */ do { dataSize = (*net_boot_module.query)(); /* Will return -1 when the data is done */ if (dataSize > 0) { while (dataSize > 0) { n = MIN(dataSize, sizeof(buf)); (*net_boot_module.read)(buf, n); dataSize = dataSize - n; } /* Do not peek if the data size returned in the query was > 0 */ } else if (dataSize == 0) { (*net_boot_module.peek)(buf, 1); } } while (dataSize >= 0); //关闭网络 /* Close up the peripheral */ (*net_boot_module.close)(); #ifdef DEVICE_PA hwPaDisable(); #endif #ifdef DEVICE_CPDMA /* Cpdma configuration. */ hwCpdmaRxDisable((cpdmaRxCfg_t *)targetGetCpdmaRxConfig()); hwCpdmaTxDisable((cpdmaTxCfg_t *)targetGetCpdmaTxConfig()); #endif #ifdef DEVICE_QM targetFreeQs(); /* Queue manager configuration */ hwQmTeardown(); #endif //入口地址非空,则跳转到相应地址,启动完成 if (entry != 0) { iblStatus.exitAddress = entry; exit = (void(*)())entry; (*exit)(); } }
Uint32 iblBoot(BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams) { Uint32 entry = 0; Uint32 value32; Uint8 dataBuf[4]; Uint16 value16; //判断启动格式 /* Determine the data format if required */ if (dataFormat == ibl_BOOT_FORMAT_AUTO) { (*bootFxn->peek)(dataBuf, sizeof(dataBuf)); value32 = (dataBuf[0] << 24) | (dataBuf[1] << 16) | (dataBuf[2] << 8) | (dataBuf[3] << 0); value16 = (dataBuf[0] << 8) | (dataBuf[1] << 0); /* BIS */ #ifndef EXCLUDE_BIS if (value32 == BIS_MAGIC_NUMBER) dataFormat = ibl_BOOT_FORMAT_BIS; #endif #ifndef EXCLUDE_COFF if (iblIsCoff(value16)) dataFormat = ibl_BOOT_FORMAT_COFF; #endif #ifndef EXCLUDE_ELF if (iblIsElf(dataBuf)) dataFormat = ibl_BOOT_FORMAT_ELF; #endif if (dataFormat == ibl_BOOT_FORMAT_AUTO) { iblStatus.autoDetectFailCnt += 1; return (0); } } //激活相应文件格式 iblStatus.activeFileFormat = dataFormat; //根据文件格式调用相应函数启动 /* Invoke the parser */ switch (dataFormat) { #ifndef EXCLUDE_BIS case ibl_BOOT_FORMAT_BIS: iblBootBis(bootFxn, &entry); break; #endif #ifndef EXCLUDE_COFF case ibl_BOOT_FORMAT_COFF: iblBootCoff(bootFxn, &entry); break; #endif case ibl_BOOT_FORMAT_BTBL: iblBootBtbl(bootFxn, &entry); break; #ifndef EXCLUDE_BLOB case ibl_BOOT_FORMAT_BBLOB: iblBootBlob(bootFxn, &entry, formatParams); break; #endif #ifndef EXCLUDE_ELF case ibl_BOOT_FORMAT_ELF: iblBootElf(bootFxn, &entry); break; #endif default: iblStatus.invalidDataFormatSpec += 1; break; } //返回函数入口地址 return (entry); }
上述是ethboot、iblboot函数内容,中文注释是我对ethboot和iblboot的理解,按照我的理解,我找不到,ibl网络启动中是从哪里开始访问tftp服务器的。
希望工程师能够做出解答。谢谢。