一、具体步骤如下:
(1)接收上位机下发的新IP及端口号;
(2)将下发的新IP及端口号写入FLASH芯片,同时启动芯片软复位或者硬复位,以使新IP及端口生效;
(3)在芯片初始化阶段读取FLASH中存储的IP及端口号信息,以便下电重启后板子可以顺利使用新的IP及端口号。
二、部分代码如下:
(1)接收上位机下发的新IP及端口号
cpp
void data_rec_task(void)
{
fdOpenSession((HANDLE)TaskSelf());
while(1)
{
recv_length = recvfrom(sock, recv_buf, 1024, 0, (PSA)&sock_cfg, &plen);//从上位机接收UDP数据
if(recv_length > 0)
{
if(recv_buf.frame_head == 0xAA55)//举例:帧头为0xAA55
{
switch(frame_content.command_type)
{
case 0x01://在线IP修改指令
{
if(validateIpConfig(recv_buf.ipconfig)//判断IP是否符合相关IP规则--自己根据IP本身定义进行界定
{
/* 非阻塞发送到Mailbox,存储完后需要软/硬复位DSP板子以使新的IP可以生效 */
Bool back = SendConfigToFlash(recv_buf.ipconfig);
if (back)
{
printf("[data_rec_task] IP info. stored successfully!\n");
} else
{
printf("[data_rec_task] IP info. stored failed: %d\n", back);
}
}
else
{
printf("IP CFGs is illegal, don't storage into FLASH!\n");
}
break;
}
default:
;
break;
}
}
}
Task_sleep(150);
}
}
(2)将下发的新IP及端口号写入FLASH芯片,同时启动芯片软复位或者硬复位,以使新IP及端口生效
cpp
/* Flash写入任务(Mailbox版本) */
void FlashWriteTask_Mailbox(void)
{
struct_ip_config config;
Uint32 dstAdd = (Uint32)SPI_NOR_FLASH_ADDR(0);
Bool ret = FALSE;
int retry_count = 0;
printf("[FlashTask] Started with Mailbox, waiting for messages...\n");
while(1)
{
if (!Mailbox_pend(g_flashMailbox, &config, BIOS_WAIT_FOREVER))
{
continue;
}
// SPI 写入 Flash
for(retry_count = 0; retry_count < 3; retry_count++)
{
printf("[FlashTask] ===== Attempt %d/3 =====\n", retry_count + 1);
spi_full_reinit();
Task_sleep(100);
if(!spi_test_communication())
{
continue;
}
spiNorFlashErasePartialNoProtect(dstAdd, sizeof(config));
ret = spiNorFlashProgram((Uint8 *)&config, dstAdd, sizeof(config));
if(!ret)
{
Task_sleep(500);
continue;
}
// 验证
struct_ip_config verify;
memset(&verify, 0, sizeof(verify));
spiNorFlashRead(dstAdd, (Uint8 *)&verify, sizeof(verify));
if (memcmp(&config, &verify, sizeof(config)) == 0)
{
printf("[FlashTask] Flash verification PASSED\n");
ret = TRUE;
break;
}
else
{
printf("[FlashTask] Flash verification FAILED\n");
ret = FALSE;
Task_sleep(500);
}
}
if (ret)
{
printf("[FlashTask] ERROR: Flash write successfully!\n");
//软复位
softwareReset();//验证OK
//硬复位
//hardwareReset();//验证OK
} else
{
printf("[FlashTask] ERROR: Flash write failed!\n");
}
}
}
//软复位
void softwareReset(void)
{
volatile unsigned int *pRSTCFG = (volatile unsigned int *)(0x023100EC);
volatile unsigned int *pRSTCTRL = (volatile unsigned int *)(0x023100E8);
volatile unsigned int key = 0x5A69;
// 1. 配置 RSTCFG:设置 PLLCTLRSTTYPE 位 (bit13) 为 1,选择软复位
*pRSTCFG = (1 << 13) | key; // 写入 key 和配置
// 2. 等待配置生效
__asm(" nop");
// 3. 向 RSTCTRL 写入 key
*pRSTCTRL = key;
// 4. 向 RSTCTRL 写入 0,将 SWRST 位 (bit16) 清零,触发复位
*pRSTCTRL = 0;
}
//硬复位
void hardwareReset(void)
{
volatile unsigned int *pRSTCFG = (volatile unsigned int *)(0x023100EC);
volatile unsigned int *pRSTCTRL = (volatile unsigned int *)(0x023100E8);
// 将复位类型配置为硬复位(RSTCFG[13]=0, RSTCFG[12]=0等)
// 低16位必须包含有效KEY 0x5A69
*pRSTCFG = 0x00005A69; // 写入KEY,其他位保持默认0(硬复位)
// 触发硬复位
*pRSTCTRL = 0x5A69;
*pRSTCTRL = 0;
}
/* 完全重新初始化SPI(使用保存的配置) */
void spi_full_reinit(void)
{
printf("[SPI] Full re-initialization...\n");
/* 1. 禁用SPI */
gpSPI_regs->SPIGCR1 &= ~0x01;
TSC_delay_us(10);
/* 2. 软件复位 */
gpSPI_regs->SPIGCR0 = 0x01;
TSC_delay_us(100);
gpSPI_regs->SPIGCR0 = 0x00;
TSC_delay_us(100);
/* 3. 重新配置SPI(使用保存的配置) */
KeyStone_SPI_init(&s_spiConfig);
/* 4. 重新初始化Flash */
spiNorFlashInit();
printf("[SPI] Full re-initialization completed\n");
}
(3)在芯片初始化阶段读取FLASH中存储的IP及端口号信息,以便下电重启后板子可以顺利使用新的IP及端口号
cpp
/*---------------------------------------------------------------------
* Main Entry Point
*/
void main(void)
{
Uint32 dstAdd = (Uint32)SPI_NOR_FLASH_ADDR(0); //写入FLASH的地址
SPI_Config spiCfg;
SPI_Data_Format loopbackDataFormat =
{
/*.delayBetweenTrans_ns = */0,
/*.ShifDirection = */SPI_MSB_SHIFT_FIRST,
/*.disable_CS_timing = */0,
/*.clockPolarity = */SPI_CLOCK_LOW_INACTIVE,
/*.clockPhase = */1,
/*.clockSpeedKHz = */5000,
/*.wordLength = */8
};
KeyStone_main_PLL_init(312.5, 16, 5);
/* SPI set as master, clock rate is 500KHz */
memset(&spiCfg, 0, sizeof(spiCfg));
spiCfg.dataFormat[0] = &loopbackDataFormat;
spiCfg.dataFormat[1] = &loopbackDataFormat;
spiCfg.dataFormat[2] = &loopbackDataFormat;
spiCfg.dataFormat[3] = &loopbackDataFormat;
spiCfg.loopBack = FALSE;
spiCfg.DMA_requestEnable = FALSE;
spiCfg.number_SPI_pins = 5;
spiCfg.CS_polarity = SPI_CS_LOW_ACTIVE;
spiCfg.C2T_delay_ns = 10;
spiCfg.T2C_delay_ns = 10;
/* 初始化SPI */
KeyStone_SPI_init(&spiCfg);
/* 保存SPI配置供后续恢复使用 */
save_spi_config(&spiCfg, &loopbackDataFormat);
spiNorFlashInit();
/* 初始化Mailbox */
init_flash_mailbox();
// 设置默认网络配置,比如默认IP及端口
initDefaultNetworkConfig();
/*从 Flash读取并更新IP配置*/
memset(data_rd, 0, sizeof(struct_ip_config));
spiNorFlashRead(dstAdd, (Uint8 *)data_rd, sizeof(struct_ip_config));
if(validateIpConfig((struct_ip_config *)data_rd))
{
printf("[main]Using Flash Network IP Configuration!\n");
configNetParams(data_rd); // 将要使用的IP及端口更新为Flash中存储的配置
}
else
{
printf("[main]Flash IP Configuration is Invalid, Using defaults data!\n");
}
free(data_rd);
/* Start the BIOS 6 Scheduler */
BIOS_start();
}
(4).cfg文件中注册邮箱任务
cpp
/* 导入Mailbox模块 */
var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');
/* 计算消息结构体大小 */
var msgSize = 0x80; // disply_control_command_0E结构体大小约128字节
/* 创建Mailbox参数 */
var mbParams = new Mailbox.Params();
mbParams.buf = null; // 使用内部buffer
mbParams.bufSize = 0; // 自动分配
mbParams.heap = null; // 使用默认堆
/* 创建Mailbox实例 */
Program.global.ipConfigMailbox = Mailbox.create(msgSize, 3, mbParams);
/* Flash写入任务 */
var flashTaskParams = new Task.Params();
flashTaskParams.instance.name = "FlashWriteTask";
flashTaskParams.stackSize = 0x2000;
flashTaskParams.priority = 3;
Program.global.flashWriteTask = Task.create("&FlashWriteTask_Mailbox", flashTaskParams);
总结:以上关键代码,在工程中妥善安置之后即可实现IP及端口在线修改并生效的功能,无需手动下电重启设备,欢迎大家广泛使用并予以交流反馈,多谢!