采用UDP协议的PIC32MZ ethernet bootloader

发布者:心愿成真最新更新时间:2017-01-20 来源: eefocus关键字:UDP协议  PIC32MZ  ethernet  bootloader 手机看文章 扫描二维码
随时随地手机看文章

经过千辛万苦,今天终于完工PIC32MZ EC Starter Kit的ethernet bootloader项目。我将整个项目, 命名为PhnBootloader。它分为两个部分。第一个部分是PC 端的host程序PhnLoader_v3.0。另一部分是单片机端boot程序PhnBoot_v3.0,是从Microchip AN1388 ethernet bootloader移植过来的。整个移植过程碰到很多困难,主要是由于ethernet bootloader使用到Microchip 的TCP/IP Stack,但是TCP/IP Stack不支持PIC32MZ。 这里我列出移植需要注意的地方:

1. PIC32MZ默认enable cache.

2. PIC32MZ ethernet module ports mapping

3. PIC32MZ EC Starter Kit的external PHY的LEDs和Start Kit的LED1,LED2复用

4. PIC32MZ EC Starter Kit的ethernet module有些port复用AN功能。

5. ethernet bootloader download完application后,跳转到application前 ,注意要清零所有使用到的register,包括disable interrupt。

  PhnLoader_v3.0和PhnBoot_v3.0之间采用UDP协议通信,通信数据包格式采用以下协定:

...

STX - Start of packet indicator
ETX - End of packet indicator
LEN - The length of true data 
DATA - General data 16 bytes, only first LEN of datas are true
CMD - Base command
ADDR - Address up to 32 bits  ( ADDRL , ADDRH , ADDRH, ADDRM)

  具体有以下Base command:

RD-VER:  0x00 -- Read Version Information (最终版本未实现)
RD_MEM: 0x01 -- Read Program Memory (最终版本未实现)
ER_MEM: 0x03 -- Erase Program Memory
WR_MEM: 0x02 -- Write Program Memory 
WR_CFG: 0x04 -- Write Configuration Registers (最终版本未实现)

  PhnLoader_v3.0

  PhnLoader_v3.0 是PC端host 程序。

      运行环境:Window + .NET Framework 4.5

      开发语言:C#

      通信类型:UDP Server

      IP 地址: 192.168.1.105

      端口号:  8720

      UI 如下图:

  C#源代码主要部分:


            try
            {                while (loaderReader.Peek() >= 0)
                {
                    pBarLoading.PerformStep();
                    recordLine = loaderReader.ReadLine();                    if (recordLine.Contains(EXTEND_TOKEN) == true)
                    {                        if (recordLine.Contains(USER_ID_TOKEN) == true)
                        {
                            isNextLineUserID = true;                            continue;
                        }                        //else if (recordLine.Contains(CONFIG_BITS_TOKEN) == true)                        //{                        //    const int ADDR_U_START_INDEX = 9;                        //    const int ADDR_U_LENGTH = 4;                        //    string addrU = recordLine.Substring(ADDR_U_START_INDEX, ADDR_U_LENGTH);                        //    loaderUpperAddr = Convert.ToInt32(addrU, 16) << 16;                        //    isNextLineConfigBits = true;                        //    continue;                        //}
                        else if (recordLine.Contains(PIC32_CONFIG_BITS_TOKEN) == true)
                        {                            const int ADDR_U_START_INDEX = 9;                            const int ADDR_U_LENGTH = 4;                            string addrU = recordLine.Substring(ADDR_U_START_INDEX, ADDR_U_LENGTH);
                            loaderUpperAddr = Convert.ToInt32(addrU, 16) << 16;
                            isNextLineConfigBits = true;                            continue;
                        }                        else
                        {                            const int ADDR_U_START_INDEX = 9;                            const int ADDR_U_LENGTH = 4;                            string addrU = recordLine.Substring(ADDR_U_START_INDEX, ADDR_U_LENGTH);
                            loaderUpperAddr = Convert.ToInt32(addrU, 16) << 16;                            continue;
                        }
                    }                    else if (recordLine.Contains(END_OF_HEX_FILE_TOKEN) == true)
                    {                        break;
                    }                    if (isNextLineUserID)
                    {
                        isNextLineUserID = false;                        // do nothing;                    }                    else if (isNextLineConfigBits)
                    {                        //if (!DownloadConfigLine(recordLine))                        //{                        //    Debug.WriteLine("Error found during configuration bits programming");                        //    loaderReader.Close();                        //    loaderServer.Close();                        //    btnDownload.Enabled = true;                        //    return;                        //}                        DownloadConfigLine(recordLine);
                        isNextLineConfigBits = false;
                    }                    else
                    {                        if (!DownloadDataLine(recordLine))
                        {
                            Debug.WriteLine("Error found during data programming");
                            loaderReader.Close();
                            loaderServer.Close();
                            btnDownload.Enabled = true;                            return;
                        }
                    }
                }
            }            catch (Exception ex)
            {
                Debug.WriteLine("Error: " + ex.Message);
                textBoxStatus.ForeColor = Color.Red;
                textBoxStatus.AppendText("Downloading failed\r\n");
                textBoxStatus.ForeColor = Color.Black;
                loaderServer.Close();
                loaderReader.Close();
                btnDownload.Enabled = true;                return;
            }


  PhnBoot_v3.0

  PhnBoot_v3.0 是单片机端Boot 程序。

      运行环境:PIC32MZ EC Starter Kit

      开发语言:C 语言 (Microchip XC32编译)

      通信类型:UDP Client

      IP 地址: 192.168.1.123

      端口号:  8740

  主要代码段:


        switch (GenUDPSt)
        {        case SM_HOME:
            ARPResolve(&ServerNode.IPAddr);
            startTime = TickGet();
            GenUDPSt++;            break;        case SM_ARP:            if (TickGet() - startTime < 5*TICK_SECOND)
            {                if (ARPIsResolved(&ServerNode.IPAddr,&ServerNode.MACAddr))
                {
                    MySock = UDPOpen(LOCAL_CLIENT_PORT,&ServerNode,REMOTE_SERVER_PORT);
                    startTime = TickGet();
                    GenUDPSt++; 
                }
            }            else
            {
                GenUDPSt = SM_HOME;
            }            break;        case SM_UDPOPEN:            if (TickGet() - startTime < TICK_SECOND)
            {                if (MySock != INVALID_UDP_SOCKET)
                {
                    startTime = TickGet();
                    GenUDPSt++;
                }
            }            else
            {
                GenUDPSt = SM_HOME;
            }            break;        case SM_UDPPUT:            if (TickGet() - startTime < 5*TICK_SECOND)
            {                if (UDPIsPutReady(MySock) > BUFFER_MAX)
                {
                    UDPPutString(ok);
                    UDPFlush();
                    GenUDPSt++;
                }
            }            else
            {
                GenUDPSt = SM_CLOSE;
            }            break;        case SM_UDPGET:            if (TickGet() - startTime < 5*TICK_SECOND)
            {
                udpPackets = UDPIsGetReady(MySock);                if (udpPackets >= BUFFER_MAX)
                {
                   UDPGetArray(frameBuffer, BUFFER_MAX);
                   UDPDiscard();                   if (frameBuffer[0] == STX && frameBuffer[BUFFER_MAX - 1] == ETX)
                   {
                    Uart_Putc('.');                    for(i=0;i= BUFFER_MAX)
                {
                    UDPPutArray(frameBuffer, BUFFER_MAX);
                    UDPFlush();
                }
                startTime = TickGet();
                GenUDPSt = SM_UDPGET;
            }            else
            {
                printf("xx");      // for debug
                GenUDPSt = SM_CLOSE;
            }            break;        case SM_CLOSE:
            printf("done\r\n");        // for debug            UDPClose(MySock);
            MySock = INVALID_UDP_SOCKET;
            GenUDPSt = SM_HOME;
            TRISCSET = 0x2000; // RC13 Input
            LATCCLR = 0x6000;  // Clear LATC 
            LATHCLR = (1<<2);
            TRISHSET = (1<<2);
            INTDisableInterrupts();
            T1CON = 0;
            ETHCON1 = 0;
            ETHCON2 = 0;
            CoreT_DelayMs(1);
            U1MODE = 0x0;
            U1STA = 0x0;
            (*((void(*)(void))USER_APP_RESET_ADDRESS))();            break;
        }


  如何使用PhnLoader_v3.0和PhnBoot_v3.0

      1. 使用XC32编译PhnBoot_v3.0(编译前,需先修改linker script)。

  2. 使用pickit3烧录PhnBoot_v3.0的Hex文件到目标板中。

  3. 拔除pickit3烧录器

  4. 连接目标板和PC到同一局域网,设置PC的IP地址,打开PhnLoader_v3.0,选择UDP协议,端口号,IP地址。

  5. 点击PhnLoader_v3.0用户界面上的“.."按钮加载需要烧录的应用程序Hex文件(编译前,需先修改linker script)

  6. 重启目标板,等到LED3 灯亮了,立刻在PhnLoader_v3.0界面上点击Download按钮。如果超时未点击Download按钮,会自动跳转到上次烧录的应用程序中去。

  7. 烧录完毕,再次重启目标板, 数秒后目标板开始正常运行应用程序。

  之后每次更新应用程序,只需重复步骤 4 ~ 7 就可以了。注意,整个烧录过程未能实现User ID/Configuration Bits的烧写,所以需要保持应用程序的Configuration Bits和Bootloader的Configuration Bits一致。


关键字:UDP协议  PIC32MZ  ethernet  bootloader 引用地址:采用UDP协议的PIC32MZ ethernet bootloader

上一篇:采用TCP协议的PIC32MZ ethernet bootloader
下一篇:C语言PIC32 serial bootloader和C#语言bootloader PC端串口通信程序

推荐阅读最新更新时间:2024-03-16 15:31

ARM裸机开发bootloader交叉工具链
今天跟随国嵌,初识linux下ARM的裸机开发全过程。现在总结如下: 首先说明为什么要学习裸机开发,一方面bootloader的编写要用到裸机开发的知识,另一方面就是驱动的开发。一般情况下我们进行系统上的开发,不会用到裸机开发。 学习要点 1、如何修改默认路径 用户 root #vim /root/.bashrc 添加:export PATH=$PATH:路径 生效路径:source /root/.bashrc 2、裸机开发流程:1编写裸机程序。2调试裸机程序。3生产二进制映像(编译、链接、格式转换)。4烧写/运行二进制映像。 led.lds led.SMakefile 编译:arm-linux-gcc -g
[单片机]
MC9S12XS128 MAL BootLoader(2)
用户程序就按照正常程序写即可,需要注意以下几点 程序写入固定的位置,不能和BootLoader程序的位置重合,否则有可能程序无法经过BootLoader下载后运行,同样也是在prm中进行相应的操作; 需要用到中断的,要对中断向量进行偏移; 对起始向量进行偏移; 写入地址对齐。 1.BootLoader程序写入固定位置: ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xEFDF; 确保不会和BootLoader的F000开始的地址重合; INTO ROM_C000/*, ROM_4000*/; 2.对中断向量进行偏移,中断发生时,将当前PC位置
[单片机]
怎么写stm8的IAP升级的bootloader和app
因为之前写个stm32的IAP升级程序,所以我总结了做IAP升级的三个主要的难点: 1、如何设置中断向量,也就是说中断向量的重定向 2、如何配置程序的起始地址 3、如何从IAP跳转到APP程序 4、使用库函数要注意的地方(防止被坑) 说文章的时候我已经完成了一个最简单的IAP升级程序,可以通过串口接收bin文件写入到flash里面,然后再运行。 1、如何设置中断向量,也就是说中断向量的重定向 stm8不像stm32那样有个一寄存器管理着中断向量的地址,所以stm32的中断可以任意设置(符合要求的情况之下),但是stm8的中断向量表是固定的 在0X8000地址,不能修改,所以BOOT区不能开中断,否则会和APP区的中断打架,但是AP
[单片机]
怎么写stm8的IAP升级的<font color='red'>bootloader</font>和app
BootLoader —— S3C2440
先来看看扬创的bootloader的实现方法: 首先:在汇编中初始化堆栈,中断向量表,MMU,时钟,串口等,然后跳到C语言的Main函数。这部分代码小于4K,放在block0。这个Main函数用来将第二段代码拷备到DRAM中并执行。 其次:进入第二段代码。第二段代码也是先在汇编中初始化堆栈,中断向量表等,然后跳到C语言的Main函数。这部分代码就不用有4K限制了,具体大小由第一段代码决定,因为它本身由第一段代码来搬运。这个Main函数用来显示开机图片以及进度条。然后视串口接收信息运行带有USB下载NK的Eboot或是读取NK映像,启动WINCE系统。 最后:进入第三段代码。这段代码用于通过USB将PC上的NK.nb0或
[单片机]
基于自编程功能的MCU Bootloader设计
Bootloader是在单片机上电启动时执行的一小段程序。也称作固件,通过这段程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用应用程序准备好正确的环境。 Boot代码由MCU启动时执行的指令组成。这里的loader指向MCU的Flash中写入新的应用程序。因此,Bootloader是依赖于特定的硬件而实现的,因此,在众多嵌入式产品中目前还不可能实现通用Bootloader。 Bootloader的最大优点是:在不需要外部编程器的情况下,对嵌入式产品的应用代码进行更新升级。它使得通过局域网或者Intemet远程更新程序成为可能。例如,如果有5 000个基于MCU的电
[单片机]
基于自编程功能的MCU <font color='red'>Bootloader</font>设计
STM8 Bootloader和APP设计(都可以使用中断)
1、本Bootloader适用范围: STM8S 和STM8A 2、Bootloader和APP的标志位 在EEPROM中的0x4000地址存放一个标志位 Bootloader 的标志位: 0x11; APP的标志位: 0x39; 3、Bootloader 和APP的地址分配 Bootloader 的存储空间为: 0x8000~ 0x9FFF; APP 的存储空间为: 0xA000~0x27FFF; 在0x8000开始的前128个字节,放置着bootloader重定位过的向量表(bootloader的真正的向量表放置在另外的地方) 在0xA000开始的前128个字节,放置着application的
[单片机]
STM8 <font color='red'>Bootloader</font>和APP设计(都可以使用中断)
PIC18系列单片机中使用BootLoader
引 言   PIC单片机的BootLoader属于需要自己写程序的那种,可以根据自己的需要写出各种功能的BootLoader程序来。目前,比较常见的BootLoader程序有Microchip公司的C18版本和着名的PICC编译器厂商HI-TECH公司(以下简称HI-TECH)的PICC18版本。它们的相似之处在于都占用了系统的0x00~0x1FF的程序空间。Microchip的版本是用纯彙编写的,而HI-TECH的版本是用C语言编写的。   在PIC系列单片机中,只有PIC18系列和PIC16F87X系列的单片机才有IAP功能,才能够使用BootLoader功能。下面只介绍PIC18的BootLoader,PIC16F87X的
[单片机]
PIC18系列单片机中使用<font color='red'>BootLoader</font>
嵌入式存储器以及BootLoader的一些总结
我在大学的时候很少关心单片机内部存储器的结构及应用,只是大概的知道RAM和ROM的区别,甚至只是知道程序下载到ROM中就能运行了。其他的如何工作程序如何启动的就不了了知了。因此在接触嵌入式的时候就会出现很多盲区。在此本人将工作三个多月以来接触到的一些关于嵌入式新的理解分享给大家,有什么错误的地方在所难免,希望大家给予指正。 RAM和ROM在单片机中的相关应用 ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。 RAM有两大类,
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved