【dsPIC33E】Bootloader移植记

本文顺承自哪里

感谢Beatfan_N的无私分享。本文记述的是BootLoader代码从dsPIC33EP256GP506上移植到dsPIC33EP128GP502上的移植过程。前文参阅
1.https://blog.csdn.net/u010875635/article/details/84660611
2.https://blog.csdn.net/u010875635/article/details/84660665
3.https://blog.csdn.net/u010875635/article/details/84660722
4.https://blog.csdn.net/u010875635/article/details/84660792
5.https://blog.csdn.net/u010875635/article/details/85316570
同时感谢老俞的无私分享。
1.http://blog.xueming.org/archives/63
2.http://blog.xueming.org/archives/68
3.http://blog.xueming.org/archives/89
4.http://blog.xueming.org/archives/225
5.http://blog.xueming.org/archives/283

dsPIC33EP-Flash不得不知的知识点

  1. dsPIC33EP64(及以上)的Flash被分段为指令页和行,每个指令页包含1024个指令字(0x400个)。

  2. 一个指令页占用的地址空间应该是0x800,共2048个地址。所以第一个指令页的地址范围是0x000-0x7FF

  3. dsPIC33EP128Flash支持双指令字编程。

  4. dsPIC33EP128每个指令字为24位实际占用32位(4个字节、2个地址),最高8位为虚字节,总是00。对于大多数应用,24位中的高8位不用于存储数据,建议便成为NOP指令或者非法操作码值。

  5. dsPIC33EP128每个指令字占2个地址,例如0x000和0x001都是表示第一个指令字。地址总是以偶数呈现(0x002/0x004/0x006),读取奇数地址获取到的与读取前一个偶数地址获得到的是一致的,所以读取奇数地址没有意义。这个很好理解,一个指令字才是一个整体,0x000和0x001虽是两个地址,但确是同一个指令字。

  6. dsPIC33E系列若擦除指令页中任意地址,都会擦除该地址所在的整个指令页。之后应在一个写周期内写入一个编程块中的所有数据。

  7. 对于dsPIC33E/PIC24E,每个程序存储器地址都是乘了一个2来获取字节地址,即从Hex文件中反推,需要除以2。也就是MPLAB生成的Hex文件,读取之后需要把地址除以2才能还原到真实的地址。
    在这里插入图片描述

BootLoader程序的改动点

改动分为以下几个部分。

1.gld文件的修改

.gld文件需要更换为128GP502的。
路径如下-> C:\Program Files (x86)\Microchip\xc16\v1.35\support\dsPIC33E\gld
之后对内存区域进行修改,这个是原来的:

program (xr)   : ORIGIN = 0x200,         LENGTH = 0x155EC

改成这样:

program (xr)   : ORIGIN = 0x800,         LENGTH = 0x6400

下面的__CODE_BASE也要做相应的改动。以下是修改之后的:

__CODE_BASE = 0x800; 
__CODE_LENGTH = 0x6400;
...
__DATA_BASE = 0x1000;
__DATA_LENGTH = 0x1000;

DATA_LENGTH这里的修改让人奇怪,为什么修改为0x1000呢?

2.UserAppFlash.c文件的修改

对擦除函数要进行修改。33EP256GP506擦除3大页,由于配置字在最后一页,不能完全擦除最后一页。对于33EP128GP502因内存减半,只能擦除2大页,且不能完全擦除最后一页。
dsPIC33E系列若擦除页中任意地址,都会擦除该地址所在的页。
这里有一个大页的概念。每页包含1024个指令字,一个指令字占用两个地址,但仅有24个位。
因此每个占用2048个地址,长度为0x800。
每20个页为一个大页大页的长度为0x10000。
这里要注意一个逻辑,每次擦除0x400个指令字,实际占用地址为0x800,例如擦除0x0,实际会擦除到0x7ff。所以擦除的首地址的尾部三位只能为0x800和0x000,不会有其他的值。
第二件事,配置字所在的位置不能被擦除,因此这里有讲究了。33EP128GP502的配置字根据.gld文件的描述,位置在0x157F0,所属页的首地址是0x15000,也即这页是断然不能擦的。下面是擦除函数的代码。

void UserFlash_EraseIvtAndUserAppBlock()
{
    //擦除0x0000~0x07FE,reset and ivt
    EraseLargePage(0);  //擦除0x000000-0x00000800,0x008000-0x00FFFF
    EraseLargePage(1);  //擦除0x010000-0x01FFFE 配置字在15000,所以不能擦除
//    EraseLargePage(2);  //擦除0x020000-0x02F7FE
    
    //配置字 0x2AFF0~0x2AFFA,处于页0x02A800-0x02AFFE (33EP256GP506)0x02A800之后的地址不能擦除
    //配置字 0x157F0~0x157FA, 处于页0x015000-0x0157FE  (33EP128GP502))0x015000之后的地址不能擦除
}

EraseLargePage()函数的小分支也需要修改。先看case 0(第0大页)这里,无需修改。从0x8000擦到0xF800(0xF8FE)。

        case 0:
            //擦除外设配置
            flashAddr.Uint16Addr.LowAddr = 0;
            InnerFlash_EraseFlashPage(flashAddr);
            //第零大页
            for(offset=0x8000;offset<=0xF800;offset+=0x800)
            {
                flashAddr.Uint16Addr.LowAddr = offset;
                InnerFlash_EraseFlashPage(flashAddr);
                if(offset>=0xF800)
                break;
            }
            break;

第1大页是需要改动的,第2大页是需要删除的。第1大页中的offset限制为小于0x5000,即不能刷0x5000这个页。

        case 1:
        //第一大页
        for(offset=0;offset<0x5000;offset+=0x800)  //modify
        {
            flashAddr.Uint16Addr.LowAddr = offset;
            InnerFlash_EraseFlashPage(flashAddr);
        }
        break;
//        case 2:
//        //第二大页
//        for(offset=0;offset<0xA800;offset+=0x800)
//        {
//            flashAddr.Uint16Addr.LowAddr = offset;
//            InnerFlash_EraseFlashPage(flashAddr);
//        }
//        break;
        default:break;
    }
}

3.DataRecord.c文件的修改

定义存储数据所在空间(也即配置字所在空间)的起始地址,为0x015000。
但通过查找用例,发现DataRecord.c中的函数,除了EraseLargePage()都没有用到。

#define DATA_RECORD_START_PAGE 0x0001
#define DATA_RECORD_START_ADDR 0x5000

4.system.c文件的修改

和BootLoader无关。涉及配置字的修改和Pin脚的设定。

5.User段.gld文件的修改

Bootloader烧写时,会擦除中断向量表以及用户软件块。
对于33EP256GP506,在gld文件中,User段程序的起始地址要修改为0x8000,长度要相应的改短。
// 未修改时: program (xr) : ORIGIN = 0x200, LENGTH = 0x2ADEC
// User(二段程序):ORIGIN = 0x8000, LENGTH = 0x7000 (因为0x15000为配置字,不能覆盖)
对于33EP128GP502,也要做出同样的改动。
// 未修改时: program (xr) : ORIGIN = 0x200, LENGTH = 0x155EC

program (xr)   : ORIGIN = 0x8000,        LENGTH = 0x4000 /*modify*/
......
__CODE_BASE = 0x8000;/*modify*/
__CODE_LENGTH = 0x4000;/*modify*/
__IVT_BASE  = 0x4;
__DATA_BASE = 0x1000;
__DATA_LENGTH = 0x1000;/*modify*/
__YDATA_BASE = 0x3000;

之前的情况是能够将User段烧写进去,但是烧写结束后,程序无法跳转到0x8000,而是重新执行BootLoader段的程序。复盘发现,我在第五步的时候忘记修改了program的长度。program的Length一定要修改到0x7000或更少。因为0x15000为配置字所在位置。如果program的长度超了就会导致失败。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值