PIC18F26K40 芯片Flash读写函数

芯片平台:PIC18F26K40

软件版本:MPLAB X IDE v5.20

在使用MPLAB X编译器的过程中,使用自带的MCC代码生成工具,加入memory模块生成的flash读写接口,对单个地址读写时没有问题,但是在进行连续区域地址读写时,就会出现数据读写异常的情况,比如要进行bootloader程序的设计,使用memory的flash读写函数就会出现问题。经过一番摸索,发现使用MCC代码生成工具里面的bootloader模块,里面的flash读写接口是可以正常使用的,为了便于使用,对这个flash读写接口进行了修改,代码如下:

/**
  Section: Macro Declarations
*/

#define WRITE_FLASH_BLOCKSIZE    32
#define ERASE_FLASH_BLOCKSIZE    32
#define END_FLASH                0x010000

// *****************************************************************************
    #include "flash.h"

// To be device independent, these are set by mcc in memory.h
    #define  LAST_WORD_MASK              (WRITE_FLASH_BLOCKSIZE - 1)

// Force variables into Unbanked for 1-cycle accessibility 
    uint8_t EE_Key_1    __at(0x0);
    uint8_t EE_Key_2    __at(0x1);
    
    void StartWrite();

// *****************************************************************************
// Read Flash
// *****************************************************************************    
uint8_t Read_Flash(uint32_t flashAddr, uint8_t *data, uint16_t data_len)
{   
    if (data == NULL)
        return 0;
    
    TBLPTRU = (uint8_t)((flashAddr & 0x00FF0000) >> 16);
    TBLPTRH = (uint8_t)((flashAddr & 0x0000FF00)>> 8);
    TBLPTRL = (uint8_t)(flashAddr & 0x000000FF);
    
    NVMCON1 = 0x80;
    for (uint16_t i = 0; i < data_len; i ++)
    {
        asm("TBLRD *+");
        data[i]  = TABLAT;
    }

    return (data_len);
}

// *****************************************************************************
// Write Flash
// data_len <= WRITE_FLASH_BLOCKSIZE
// *****************************************************************************
uint8_t Write_Flash(uint32_t flashAddr, uint8_t *data, uint16_t data_len)
{   
    if (data == NULL)
        return 0;
    
    uint8_t GIEBitValue = INTCONbits.GIE;     // Save interrupt enable
    INTCONbits.GIE = 0; // Disable interrupts
    
    EE_Key_1 = 0x55;  // write EE Keys
    EE_Key_2 = 0xAA;
    
    TBLPTRU = (uint8_t)((flashAddr & 0x00FF0000) >> 16);
    TBLPTRH = (uint8_t)((flashAddr & 0x0000FF00)>> 8);
    TBLPTRL = (uint8_t)(flashAddr & 0x000000FF);
    
	NVMCON1 = 0xA4;       // Setup writes
    for (uint16_t  i = 0; i < data_len; i ++)
    {
        TABLAT = data[i];
        if (TBLPTR >= END_FLASH)
        {            
            return (0);
        }
        asm("TBLWT *+");
        if (((TBLPTRL & LAST_WORD_MASK) == 0x00)
          || (i == data_len - 1))
        {
            asm("TBLRD *-");
            StartWrite();
            asm("TBLRD *+");
        }
    }
    
    EE_Key_1 = 0x00;  // erase EE Keys
    EE_Key_2 = 0x00;
    
    INTCONbits.GIE = GIEBitValue;   // Restore interrupt enable
    
    return (1);
}

// *****************************************************************************
// Erase Program Memory
// Erases data_length rows from program memory
// *****************************************************************************
uint8_t Erase_Flash (uint32_t flashAddr, uint16_t data_len)
{   
    uint8_t GIEBitValue = INTCONbits.GIE;     // Save interrupt enable
    INTCONbits.GIE = 0; // Disable interrupts
    
    EE_Key_1 = 0x55;  // write EE Keys
    EE_Key_2 = 0xAA;
    
    TBLPTRU = (uint8_t)((flashAddr & 0x00FF0000) >> 16);
    TBLPTRH = (uint8_t)((flashAddr & 0x0000FF00)>> 8);
    TBLPTRL = (uint8_t)(flashAddr & 0x000000FF);
    
    for (uint16_t i=0; i < data_len; i++)
    {
        if (TBLPTR >= END_FLASH)
        {            
            return (0);
        }
        NVMCON1 = 0x94;       // Setup writes
        StartWrite();
        TBLPTR += ERASE_FLASH_BLOCKSIZE;
    }
   
    EE_Key_1 = 0x00;  // erase EE Keys
    EE_Key_2 = 0x00;
    
    INTCONbits.GIE = GIEBitValue;   // Restore interrupt enable
    
    return (1);
}

// *****************************************************************************
// Unlock and start the write or erase sequence.
// *****************************************************************************
void StartWrite()
{
    __asm ("banksel NVMCON2");
    __asm ("movf _EE_Key_1, w, c");
    __asm ("movwf NVMCON2, b");
    __asm ("movf _EE_Key_2, w, c");
    __asm ("movwf NVMCON2, b");
    __asm ("bsf   NVMCON1,1");       // Start the write
    NOP();
    NOP();
    return;
}

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智小星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值