自己用C语言写PIC32 serial bootloader

发布者:范隆最新更新时间:2017-01-20 来源: eefocus关键字:C语言  PIC32  serial  bootloader 手机看文章 扫描二维码
随时随地手机看文章

  从15年12月份以来我的空余时间都在折腾15年底买的PIC32MZ EC Starter kit。并陆续写了十多篇随笔记录我折腾的历程。最近新完成的是用C语言实现了PIC32的UART bootloader, 采用串口通信,适用于Microchip的PIC32MZ EC,稍作对应的修改也可适用于PIC32MX, PIC32MZ EF等。Uart bootloader是用XC32编译的,电脑端的通信软件是用超级终端--HyperTerminal (也可以使用SecureCRT). 和之前我写的HyperBootloader_PIC16/PIC18/dsPIC很类似,算是一个家族系列之一。为保证家族特性,我命其名为HyperBootloader_PIC32

     BOOTLOADER PLACEMENT

  HyperBootloader_PIC32 序放在引导闪存存储器中,如下图所示。

  BOOTLOADER LINKER SCRIPT

  由于需要将bootloader放置在特定位置,我们不能使用默认的linker script. 我们需要修改linker script来放置bootloader, 以下是修改后的主要部分。


_RESET_ADDR                    = 0xBFC00000;
_BEV_EXCPT_ADDR                = 0xBFC00380;
_DBG_EXCPT_ADDR                = 0xBFC00480;
_SIMPLE_TLB_REFILL_EXCPT_ADDR  = _ebase_address + 0;
_CACHE_ERR_EXCPT_ADDR          = _ebase_address + 0x100;
_GEN_EXCPT_ADDR                = _ebase_address + 0x180;/*************************************************************************
 * Memory Regions
 *
 * Memory regions without attributes cannot be used for orphaned sections.
 * Only sections specifically assigned to these regions can be allocated
 * into these regions.
 *
 * The Debug exception vector is located at 0x9FC00480.
 *
 * The config_
 sections are used to locate the config words at  * their absolute addresses.  *************************************************************************/MEMORY {/* Bootloader user code: Only in the Lower Boot Alias */   kseg0_program_mem     (rx)  : ORIGIN = 0x9FC02000, LENGTH = 0xDF00/* Lower Boot Alias last(5th) page: Not used */   kseg0_lba_last_page   (rx)  : ORIGIN = 0x9FC10000, LENGTH = 0x4000/* Interrupt Vector table */   kseg0_boot_mem              : ORIGIN = 0x9FC01000, LENGTH = 0x1000/* Reset and C Startup module */   kseg1_boot_mem              : ORIGIN = 0xBFC00000, LENGTH = 0x480/* Cache TLB Initialization Table */   kseg1_boot_mem_4B0          : ORIGIN = 0xBFC004B0, LENGTH = 0xB50


  BOOTLOADER MAIN CODE

  修改后的linker script加到bootloader的项目中后,接着是bootloader的coding,以下是bootloader code的主要部分


        if (linereceived)
        {            for (ix = 0; ix < incrbytes; ix++)
            {
                Uart_Putc(frameBuffer[ix]);
            }
            Uart_Putc('\n');
            cksum = bcount = GetXbyte(frameBuffer[LEN_NIBBLE1_INDEX],frameBuffer[LEN_NIBBLE2_INDEX]);
            SourceAddr.v[1] = GetXbyte(frameBuffer[ADDRH_NIBBLE1_INDEX],frameBuffer[ADDRH_NIBBLE2_INDEX]);
            SourceAddr.v[0] = GetXbyte(frameBuffer[ADDRL_NIBBLE1_INDEX],frameBuffer[ADDRL_NIBBLE2_INDEX]);
            rectype = GetXbyte(frameBuffer[TYPE_NIBBLE1_INDEX],frameBuffer[TYPE_NIBBLE2_INDEX]);            switch(rectype)
            {            case LINEAR_ADDRESS:
                SourceAddr.v[3] = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1],frameBuffer[TYPE_NIBBLE2_INDEX+2]);
                SourceAddr.v[2] = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+3],frameBuffer[TYPE_NIBBLE2_INDEX+4]);
                Checksum();                break;            case DATA:                if ((SourceAddr.word.HW == 0x1fc0)) break;                if (SourceAddr.Val >= (EraseAddr.Val+ PAGE_SIZE))
                {
                    EraseAddr.Val = (SourceAddr.Val/PAGE_SIZE) * PAGE_SIZE;
                    NVMErasePage(EraseAddr.Val);
                }
                linereceived = 0;                for (ix=0; ix < 2*bcount;)
                {
                    pData.byte.LB = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+0],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+1]);
                    pData.byte.HB = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+2],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+3]);
                    pData.byte.UB = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+4],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+5]);
                    pData.byte.MB = GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+6],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+7]);
                    unsigned int error = NVMWriteWord(SourceAddr.Val, pData.Val);                    if ((error & 0x3000) > 0) Uart_Putc('N');  // for debug
                    error = 0;
                    SourceAddr.Val += 4;
                    ix += 8;                    if (linereceived) Uart_Putc('X');        // for debug                }
                Checksum();                //Buf_Init();
                break;            case END:
                Checksum();
                U1MODE = 0x0;
                U1STA = 0x0;
                TRISCSET = 0x2000; /* RC13 Input */
                LATCCLR = 0x6000;  /* Clear LATC */
                IPC28CLR = 0x1F00; /* Clear IPC28 */
                IEC3bits.U1RXIE = 0; /* Clear IEC3 */
                (*((void(*)(void))USER_APP_RESET_ADDRESS))();                break;
            }
            linereceived = 0;
            incrbytes = 0;
        }


  Bootloader编译成功后,使用programmer烧录到target, 然后拔掉programmer。并且以后再更新application再也不需要programmer了。

  APPLICATION LINKER SCRIPT 

  Bootloader和appication同时放置在闪存存储器中,要两者都可以正常工作,就必修确保两者不能有overlap。所以application的放置需要避开bootloader,这样需要需改application 的linker script。 以下是修改后的主要部分。


_RESET_ADDR = 0x9D001000;
_SIMPLE_TLB_REFILL_EXCPT_ADDR = _ebase_address + 0;
_CACHE_ERR_EXCPT_ADDR = _ebase_address + 0x100;
_GEN_EXCPT_ADDR = _ebase_address + 0x180;/*************************************************************************
 * Memory Regions
 *
 * Memory regions without attributes cannot be used for orphaned sections.
 * Only sections specifically assigned to these regions can be allocated
 * into these regions.
 *
 * The Debug exception vector is located at 0x9FC00480.
 * The config_
 sections are used to locate the config words at  * their absolute addresses.  *************************************************************************/MEMORY {     kseg1_boot_mem : ORIGIN = 0x9D001000, LENGTH = 0x480     kseg0_program_mem (rx) : ORIGIN = 0x9D000000 + 0x1000 + 0x480, LENGTH = 0x200000 - (0x1000 + 0x480) /* All C files will be located here */          kseg0_boot_mem : ORIGIN = 0x9D000000, LENGTH = 0x0    kseg0_data_mem (w!x) : ORIGIN = 0x80000000, LENGTH = 0x80000   sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000   kseg2_ebi_data_mem : ORIGIN = 0xC0000000, LENGTH = 0x4000000   kseg2_sqi_data_mem : ORIGIN = 0xD0000000, LENGTH = 0x4000000   kseg3_ebi_data_mem : ORIGIN = 0xE0000000, LENGTH = 0x4000000   kseg3_sqi_data_mem : ORIGIN = 0xF0000000, LENGTH = 0x4000000}


  HOW TO USE HYPERBOOTLOADER_PIC32

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

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

  3. 拔除pickit3烧录器,连接目标板与PC的串口,打开超级终端,设置如下:115200-8-None-1-None, Line Delay-20ms。

  4. 重启目标板,超级终端会出现Booting... 字样。

  5. 6秒内,打开Send Text File对话框,选择期望烧录的application的hex文件(编译前,需先修改linker script),点击确认, HyperBootloader会将接收到的数据传回到电脑超级终端上,并将数据烧录到目标板程序存储器的正确位置。

  6. 烧录完毕,自动跳转去执行application。

  之后每次更新application,只需重复步骤 4 ~ 6 就可以了。

  NOTE

      HyperBootloader不支持configuration bits的烧写,需要application的configuration bits 和HyperBootloader_PIC32的configuration bits保持一致。


关键字:C语言  PIC32  serial  bootloader 引用地址:自己用C语言写PIC32 serial bootloader

上一篇:C语言PIC32 serial bootloader和C#语言bootloader PC端串口通信程序
下一篇:PIC32MZ tutorial -- UART Communication

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

PIC单片机C语言延时程序和循环子程序
很多朋友说C中不能精确控制延时时间,不能象汇编那样直观。 其实不然,对延时函数深入了解一下就能设计出一个理想的框价出来。 一般的我们都用 for(x=100;--x;){;}此句等同与x=100;while(--x){;}; 或for(x=0;x 100;x++){;} 来写一个延时函数。 在这里要特别注意:X=100,并不表示只运行100个指令时间就跳出循环。 可以看看编译后的汇编: x=100;while(--x){;} 汇编后: movlw 100 bcf 3,5 bcf 3,6 movwf_delay l2 decfsz _delay goto l2 return 从代码可以看出总的
[单片机]
基于PIC32的以太网与CAN总线的网桥设计
立项背景 当今社会对大学生的创新能力有很高的要求,实验室为学生提供了很好地学习平台,但是实验室开放时间有限制,不方便学生在课余及假期前去做实验。另外实验室管理制度不够完善,往往存在仪器损坏、老化却得不到及时维护等问题。 该设计以PIC32自带的以太网模块作为和外界网络联系的桥梁,实现对实验室(模型)的系统化管理。该系统可通过以太网远程开启实验室门禁,并对实验室内各种设备仪器的工作状态进行监控。在实验室内部采用物理结构简单、成本低廉的CAN总线实现实验室的各个设备的连接与通信。 本系统以方便老师方便学生为宗旨,即使在节假日老师也可以为学生提供一个实验平台,且不用到实验室就可以了解实验室的各种状况。为学校实验教学提供
[单片机]
基于<font color='red'>PIC32</font>的以太网与CAN总线的网桥设计
FM31xx的控制软件(8052)(C语言)和相关电路图
;仅供参考 cn_f__12308.c ; 路泽阳 while(1) //////////////////////////// { ADDRESS2=0x01; ADDRESS1=0x00; for(i=0;i 14;i++) { save_char(ADDRESS1,ADDRESS2,SAVE_DATA); } _NOP(); ADDRESS2=0x01; ADDRESS1=0x00; for(j=0;j 14;j++
[单片机]
单片机C语言教程:附录1 C51编译器的扩展关键字
附表1-1 ANSIC标准关键字 附表1-2 C51编译器的扩展关键字
[单片机]
单片机<font color='red'>C语言</font>教程:附录1 C51编译器的扩展关键字
采用TCP协议实现PIC18F97J60 ethernet bootloader
 TCP/IP Stack   Microchip TCP/IP Stack是免费的,广泛应用于PIC单片机中。由于有远程更新程序的需求,我决定开发基于TCP协议的ethernet bootloader, 主要使用了Microchip TCP/IP Stack的TCP模块。最终我开发出来的ethernet bootloader 在PIC18F97J60上验证通过。整个实现上分两部分,一部分是单片机端的基于TCP协议的bootloader程序,我将其命名为PhnBoot_v2.0, 另外一部分是同样基于TCP协议与单片机互动的PC端通信程序,我将其命名为PhnLoader_v2.0。我还定义了PhnBoot_v2.0和PhnLo
[单片机]
ARM裸机开发bootloader内存初始化
一、从内部看内存 内存由于其访问速度快,访问方式简单成为PC机与嵌入式设备不可缺少的部件。 1、内存的分类 内存分为DRAM和SRAM,其中DRAM又包含SDRAM、DDR、DDR2。 DRAM:它的基本部件是小电容,电容可以再两个极板上保留电荷,但是需要定期的充电(刷新),否则数据就好丢失。缺点:要进行不断的刷新才能保持数据,存取速度较慢。 SRAM:它是一种具有静止存取功能的内存,不需要定期刷新电路就能保持它们内部存储的数据。其优点:存取的速度快;但是缺点是:功耗大,成本高。常用于存储容量不高,但存取速度快的场合,比如stepping stone。 DRAM的分类:在嵌入式系统中,除了CPU内部的垫脚石采用SRAM外,
[单片机]
ARM裸机开发<font color='red'>bootloader</font>内存初始化
单片机C语言中code是什么意思
在51系列中data,idata,xdata,pdata的区别 code:程序存储区。 data:固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。 idata:固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。idata是用类似C中的指针方式访问的。汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好) xdata:外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。 pdata:外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用mov
[单片机]
小容量单片机系统的C语言程序结构
引 言:   2002年初,笔者着手写一个IC卡预付费电表的工作程序,该电表使用Philips公司的8位51扩展型单片机87LPC764,要求实现很多功能,包括熄显示、负荷计算与控制、指示闪烁以及电表各种参数的查询等,总之,要使用时间的单元很多。笔者当时使用ASM51完成了这个程序的编写,完成后的程序量是2KB多一点。后来,由于种种原因,这个程序并没有真正使用,只是作了一些改动之后用在一个老化设备上进行计时与负荷计算。约一年后,笔者又重新改写了这些代码。 1 系统的改进   可以说,这个用ASM51实现的代码是没有什么组织性可言的,要什么功能就加入什么功能,弄得程序的结构非常松散,其实这也是导致笔者最终决定重新改写这些代
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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