TI TMS320C6678芯片实现IP及端口在线修改并生效

一、具体步骤如下:

(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及端口在线修改并生效的功能,无需手动下电重启设备,欢迎大家广泛使用并予以交流反馈,多谢!

相关推荐
CET中电技术1 小时前
不用外挂传感器、不用停机检测——CET中电技术如何重构电动机运维范式?
单片机·嵌入式硬件
0x3F(小茶)2 小时前
嵌入式C设计模式完全指南(基于《C嵌入式编程设计模式》)
c语言·开发语言·单片机·嵌入式硬件·设计模式
老高学长2 小时前
金融机构文档加密软件哪个好|合规与安全兼顾|2026新测评
网络·人工智能·安全
lpfasd1232 小时前
docker中默认网络的作用和注意事项
网络·docker·容器
都在酒里2 小时前
FreeRTOS 手动移植教程(二):任务管理——多任务创建、优先级抢占与删除
stm32·单片机·嵌入式硬件·rtos
大江东去浪淘尽千古风流人物2 小时前
【KV-Tracker】Transformer 实时位姿跟踪:KV-Cache 加速多视图几何网络达 27FPS
网络·深度学习·transformer·slam·位姿估计·kv-cache
提伯斯6462 小时前
Jetson_Pixhawk局域网UDP连接QGC
linux·网络·嵌入式硬件·网络协议·udp·jetson
zbtlink2 小时前
2.5G路由器,你家能用上吗?
网络·智能路由器
Agent_Sea2 小时前
私有化部署AI平台的成本临界点判断:从调用量、合规强度和业务周期三个维度核查
网络·人工智能·ai平台