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.

TMS320C6678 ibl 网络启动

工程师,您好!

       我们现在想要实现的一个功能是从 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服务器的。

希望工程师能够做出解答。谢谢。

  • 我自己写的定制bootloader,没仔细研究这个流程,只用了他的驱动部分;
    flash因为启动只需要读,并不需要写,读操作参考烧写nand的工具;
    tftp是抽象为其定义的一套seek/ read操作进行的,你从tftp目录文件的api反向跟踪即可找到。
  • 您好,感谢您的回复,我也是最近才接触DSP,之前没有这方面的开发经验,而我们的项目时间又很紧,我想问一下您有什么bootloader开发的资料吗?如果可以的话,您能否将您的boot loader分享给我学习一下呢?我的邮箱是zy979228369@hotmail.com。非常感谢。
  • 您好,我想问一下您自己写bootloader是在什么环境下编写的?如果是ccs的话,编译后的.out文件是无法直接烧写进eeprom被rbl识别的,需要转化,那么转化的工具链在哪里有呢?如果是其他环境下编写的,那么是在什么环境下编写的呢?编写后的ibl又有什么步骤能够让rbl识别运行呢?希望您能点拨一下,万分感谢。
  • e2echina.ti.com/.../159230
    好像你已经看到了呢,这个是另外一个项目给FPGA转的bin(DSP的flash使用挂在fpga上面的);dsp自己固化,直接转出来烧写到对应位置就ok了。
x 出现错误。请重试或与管理员联系。