沁恒V203flash,0x35flash擦除编写

关于读flash ,两款芯片关于读flash 操作一致,都可采用相同读操作

1 读操作

在通用地址空间内进行直接寻址,任何 8/16/32 位数据的读操作都能访问闪存模块的内容并得到

相应的数据。相应代码如下:

/**@brief FLASH读字节
 *
 * @param[in] Addr    指明地址
 *
 * @retval 返回字节数据
 */
INT8U bsp_flash_read_byte(INT32U Addr)
{
        INT8U Temp;
        Temp = (INT8U)(*((INT8U*)Addr));
        return Temp;
}
INT32U bsp_flash_read_dword(INT32U Addr)
{
    INT32U Temp;
    Temp = (INT32U)(*((INT32U*)Addr));
    return Temp;
}
INT16U bsp_flash_read_word(INT32U Addr)
{
     INT16U Temp;
     Temp = (INT16U)(*((INT32U*)Addr));
     return Temp;
}

对于解锁闪存锁,两款芯片也是一致的,需要通过写入序列到特定寄存器才能进行解锁:

解除闪存

系统复位后,闪存控制器(FPEC)和 FLASH_CTLR 寄存器是被锁定的,不可访问。通过写入序列

到 FLASH_KEYR 寄存器可解锁闪存控制器模块。

解锁序列:

1) 向 FLASH_KEYR 寄存器写入 KEY1 = 0x45670123(第 1 步必须是 KEY1);

2) 向 FLASH_KEYR 寄存器写入 KEY2 = 0xCDEF89AB(第 2 步必须是 KEY2)。

上述操作必须按序并连续执行,否则属于错误操作,会锁死 FPEC 模块和 FLASH_CTLR 寄存器并产

生总线错误,直到下次系统复位。

闪存控制器(FPEC)和 FLASH_CTLR 寄存器可以通过将 FLASH_CTLR 寄存器的“LOCK”位,置 1 来

再次锁定。

/* Flash Operation Key */
volatile uint32_t Flash_Operation_Key0;
volatile uint32_t Flash_Operation_Key1;
 /* Verify Keys, No flash operation if keys are not correct */
    if((Flash_Operation_Key0 != DEF_FLASH_OPERATION_KEY_CODE_0) || (Flash_Operation_Key1 != DEF_FLASH_OPERATION_KEY_CODE_1))
    {
        /* ERR: Risk of code running away */
        return 0xFF;
    }

对于写入flash操作,V203和0x35有不一样的差别

V203主存储器标准编程 2字节,4字节

标准编程每次可以写入 2 字节。当 FLASH_CTLR 寄存器的 PG 位为‘1’时,每次向闪存地址写入

半字(2 字节)将启动一次编程,写入任何非半字数据,FPEC 都会产生总线错误。编程过程中,BSY

位为‘1’,编程结束,BSY 位为‘0’,EOP 位为‘1’。

注:当 BSY 位为‘1’时,将禁止对任何寄存器执行写操作。

代码如下:

INT32U bsp_flash_write_dword(INT32U Addr, INT32U Data)
{
    FLASH_Status status = FLASH_COMPLETE;
    status = FLASH_ProgramWord(Addr, Data);
    return (status == FLASH_COMPLETE) ? 1 : 0;
}

INT16U bsp_flash_write_word(INT32U Addr, INT16U Data)
{
    FLASH_Status status = FLASH_COMPLETE;
    status = FLASH_ProgramHalfWord(Addr, Data);
    return (status == FLASH_COMPLETE) ? 1 : 0;
}

V203主存储器快速编程 256B

/*********************************************************************
 * @fn      FLASH_ProgramPage_Fast
 *
 * @brief   Program a specified FLASH page (1page = 256Byte).
 *
 * @param   Page_Address - The page address to be programed.
 *
 * @return  none
 */
void FLASH_ProgramPage_Fast(uint32_t Page_Address, uint32_t *pbuf)
{
    uint8_t size = 64;

    Page_Address &= 0xFFFFFF00;

    FLASH->CTLR |= CR_PAGE_PG;
    while(FLASH->STATR & SR_BSY);
    while(FLASH->STATR & SR_WR_BSY);

    while(size)
    {
        *(uint32_t *)Page_Address = *(uint32_t *)pbuf;
        Page_Address += 4;
        pbuf += 1;
        size -= 1;
        while(FLASH->STATR & SR_WR_BSY);
    }

    FLASH->CTLR |= CR_PG_STRT;
    while(FLASH->STATR & SR_BSY);
    FLASH->CTLR &= ~CR_PAGE_PG;
}

V203主存储器标准擦除:

闪存可以擦除256B,4K,32K

/*********************************************************************
 * @fn      ROM_ERASE
 *
 * @brief   Select erases a specified FLASH .
 *
 * @param   StartAddr - Erases Flash start address(StartAddr%256 == 0).
 *          Cnt - Erases count.
 *          Erase_Size - Erases size select.The returned value can be:
 *          Size_32KB, Size_4KB, Size_256B.
 *
 * @return  none.
 */
static void ROM_ERASE(uint32_t StartAddr, uint32_t Cnt, uint32_t Erase_Size)
{
    do{
        if(Erase_Size == Size_32KB)
        {
            FLASH->CTLR |= CR_BER32;
        }
        else if(Erase_Size == Size_4KB)
        {
            FLASH->CTLR |= CR_PER_Set;
        }
        else if(Erase_Size == Size_256B)
        {
            FLASH->CTLR |= CR_PAGE_ER;
        }

        FLASH->ADDR = StartAddr;
        FLASH->CTLR |= CR_STRT_Set;
        while(FLASH->STATR & SR_BSY)
            ;

        if(Erase_Size == Size_32KB)
        {
            FLASH->CTLR &= ~CR_BER32;
            StartAddr += Size_32KB;
        }
        else if(Erase_Size == Size_4KB)
        {
            FLASH->CTLR &= ~CR_PER_Set;
            StartAddr += Size_4KB;
        }
        else if(Erase_Size == Size_256B)
        {
            FLASH->CTLR &= ~CR_PAGE_ER;
            StartAddr += Size_256B;
        }
    }while(--Cnt);
}

闪存可以擦除256B的倍数

/*********************************************************************
 * @fn      FLASH_ROM_ERASE
 *
 * @brief   Erases a specified FLASH .
 *
 * @param   StartAddr - Erases Flash start address(StartAddr%256 == 0).
 *          Length - Erases Flash start Length(Length%256 == 0).
 *
 * @return  FLASH Status - The returned value can be: FLASH_ADR_RANGE_ERROR,
 *        FLASH_ALIGN_ERROR, FLASH_OP_RANGE_ERROR or FLASH_COMPLETE.
 */
FLASH_Status FLASH_ROM_ERASE(uint32_t StartAddr, uint32_t Length)
{
    uint32_t Addr0 = 0, Addr1 = 0, Length0 = 0, Length1 = 0;

    FLASH_Status status = FLASH_COMPLETE;

    if((StartAddr < ValidAddrStart) || (StartAddr >= ValidAddrEnd))
    {
        return FLASH_ADR_RANGE_ERROR;
    }

    if((StartAddr + Length) > ValidAddrEnd)
    {
        return FLASH_OP_RANGE_ERROR;
    }

    if((StartAddr & (Size_256B-1)) || (Length & (Size_256B-1)) || (Length == 0))
    {
        return FLASH_ALIGN_ERROR;
    }

    /* Authorize the FPEC of Bank1 Access */
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;

    /* Fast mode unlock */
    FLASH->MODEKEYR = FLASH_KEY1;
    FLASH->MODEKEYR = FLASH_KEY2;

    Addr0 = StartAddr;

    if(Length >= Size_32KB)
    {
        Length0 = Size_32KB - (Addr0 & (Size_32KB - 1));
        Addr1 = StartAddr + Length0;
        Length1 = Length - Length0;
    }
    else if(Length >= Size_4KB)
    {
        Length0 = Size_4KB - (Addr0 & (Size_4KB - 1));
        Addr1 = StartAddr + Length0;
        Length1 = Length - Length0;
    }
    else if(Length >= Size_256B)
    {
        Length0 = Length;
    }

    /* Erase 32KB */
    if(Length0 >= Size_32KB)//front
    {
        Length = Length0;
        if(Addr0 & (Size_32KB - 1))
        {
            Length0 = Size_32KB - (Addr0 & (Size_32KB - 1));
        }
        else
        {
            Length0 = 0;
        }

        ROM_ERASE((Addr0 + Length0), ((Length - Length0) >> 15), Size_32KB);
    }

    if(Length1 >= Size_32KB)//back
    {
        StartAddr = Addr1;
        Length = Length1;

        if((Addr1 + Length1) & (Size_32KB - 1))
        {
            Addr1 = ((StartAddr + Length1) & (~(Size_32KB - 1)));
            Length1 = (StartAddr + Length1) & (Size_32KB - 1);
        }
        else
        {
            Length1 = 0;
        }

        ROM_ERASE(StartAddr, ((Length - Length1) >> 15), Size_32KB);
    }

    /* Erase 4KB */
    if(Length0 >= Size_4KB) //front
    {
        Length = Length0;
        if(Addr0 & (Size_4KB - 1))
        {
            Length0 = Size_4KB - (Addr0 & (Size_4KB - 1));
        }
        else
        {
            Length0 = 0;
        }

        ROM_ERASE((Addr0 + Length0), ((Length - Length0) >> 12), Size_4KB);
    }

    if(Length1 >= Size_4KB) //back
    {
        StartAddr = Addr1;
        Length = Length1;

        if((Addr1 + Length1) & (Size_4KB - 1))
        {
            Addr1 = ((StartAddr + Length1) & (~(Size_4KB - 1)));
            Length1 = (StartAddr + Length1) & (Size_4KB - 1);
        }
        else
        {
            Length1 = 0;
        }

        ROM_ERASE(StartAddr, ((Length - Length1) >> 12), Size_4KB);
    }

    /* Erase 256B */
    if(Length0)//front
    {
        ROM_ERASE(Addr0, (Length0 >> 8), Size_256B);
    }

    if(Length1)//back
    {
        ROM_ERASE(Addr1, (Length1 >> 8), Size_256B);
    }

    FLASH->CTLR |= CR_FLOCK_Set;
    FLASH->CTLR |= CR_LOCK_Set;

    return status;
}

V203主存储器快速擦除:

闪存可以按256字节,4K,32K,64K字节擦除,也可以整片擦除

代码如下:

/*********************************************************************
 * @fn      FLASH_ErasePage_Fast
 *
 * @brief   Erases a specified FLASH page (1page = 256Byte).
 *
 * @param   Page_Address - The page address to be erased.
 *
 * @return  none
 */
void FLASH_ErasePage_Fast(uint32_t Page_Address)
{
    Page_Address &= 0xFFFFFF00;

    FLASH->CTLR |= CR_PAGE_ER;
    FLASH->ADDR = Page_Address;
    FLASH->CTLR |= CR_STRT_Set;
    while(FLASH->STATR & SR_BSY);
    FLASH->CTLR &= ~CR_PAGE_ER;
}

/*********************************************************************
 * @fn      FLASH_EraseBlock_32K_Fast
 *
 * @brief   Erases a specified FLASH Block (1Block = 32KByte).
 *
 * @param   Block_Address - The block address to be erased.
 *
 * @return  none
 */
void FLASH_EraseBlock_32K_Fast(uint32_t Block_Address)
{
    Block_Address &= 0xFFFF8000;

    FLASH->CTLR |= CR_BER32;
    FLASH->ADDR = Block_Address;
    FLASH->CTLR |= CR_STRT_Set;
    while(FLASH->STATR & SR_BSY);
    FLASH->CTLR &= ~CR_BER32;
}

/*********************************************************************
 * @fn      FLASH_EraseBlock_64K_Fast
 *
 * @brief   Erases a specified FLASH Block (1Block = 64KByte).
 *
 * @param   Block_Address - The block address to be erased.
 *
 * @return  none
 */
void FLASH_EraseBlock_64K_Fast(uint32_t Block_Address)
{
    Block_Address &= 0xFFFF0000;

    FLASH->CTLR |= CR_BER64;
    FLASH->ADDR = Block_Address;
    FLASH->CTLR |= CR_STRT_Set;
    while(FLASH->STATR & SR_BSY);
    FLASH->CTLR &= ~CR_BER64;
}

而在x035这款芯片当中,仅仅只保留了标准的flash函数进行flash 编程

X035主存储器标准编程:

闪存只能写入256B的倍数大小

/*********************************************************************
 * @fn      FLASH_ROM_WRITE
 *
 * @brief   Writes a specified FLASH .
 *
 * @param   StartAddr - Writes Flash start address(StartAddr%256 == 0).
 *          Length - Writes Flash start Length(Length%256 == 0).
 *          pbuf - Writes Flash value buffer.
 *
 * @return  FLASH Status - The returned value can be: FLASH_ADR_RANGE_ERROR,
 *        FLASH_ALIGN_ERROR, FLASH_OP_RANGE_ERROR or FLASH_COMPLETE.
 */
FLASH_Status FLASH_ROM_WRITE(uint32_t StartAddr, uint32_t *pbuf, uint32_t Length)
{
    uint32_t i, adr;
    uint8_t size;

    FLASH_Status status = FLASH_COMPLETE;

    if((StartAddr < ValidAddrStart) || (StartAddr >= ValidAddrEnd))
    {
        return FLASH_ADR_RANGE_ERROR;
    }

    if((StartAddr + Length) > ValidAddrEnd)
    {
        return FLASH_OP_RANGE_ERROR;
    }

    if((StartAddr & (Size_256B-1)) || (Length & (Size_256B-1)) || (Length == 0))
    {
        return FLASH_ALIGN_ERROR;
    }
    adr = StartAddr;
    i = Length >> 8;

    /* Authorize the FPEC of Bank1 Access */
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;

    /* Fast program mode unlock */
    FLASH->MODEKEYR = FLASH_KEY1;
    FLASH->MODEKEYR = FLASH_KEY2;
        
        FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset);

    do{
        FLASH->CTLR |= CR_PAGE_PG;
        FLASH->CTLR |= CR_BUF_RST;
        while(FLASH->STATR & SR_BSY)
            ;
        size = 64;
        while(size)
        {
            *(uint32_t *)StartAddr = *(uint32_t *)pbuf;
            FLASH->CTLR |= CR_BUF_LOAD;
            while(FLASH->STATR & SR_BSY)
                ;
            StartAddr += 4;
            pbuf += 1;
            size -= 1;
        }

        FLASH->ADDR = adr;
        FLASH->CTLR |= CR_STRT_Set;
        while(FLASH->STATR & SR_BSY)
            ;
        FLASH->CTLR &= ~CR_PAGE_PG;
        adr += 256;
    }while(--i);

    FLASH->CTLR |= CR_FLOCK_Set;
    FLASH->CTLR |= CR_LOCK_Set;

    return status;
}

还有一个4字节的flash写入函数FLASH_BufLoadFLASH_BufLoad函数中使用了CR_PAGE_PG(页编程模式)和CR_BUF_LOAD(缓冲区加载)等控制位,这些操作通常用于页编程的中间步骤(例如先加载数据到缓冲区,再批量写入整页),而非独立的 4 字节写入。所以FLASH_BufLoad函数不能单独用于写入 4 字节 FLASH,它需要配合页编程的完整流程(解锁、擦除、页数据加载、编程启动等)使用。

/*********************************************************************
 * @fn      FLASH_BufLoad
 *
 * @brief   Flash Buffer load(4Byte).
 *
 * @param   Address - specifies the address to be programmed.
 *          Data0 - specifies the data0 to be programmed.
 *
 * @return  none
 */
void FLASH_BufLoad(uint32_t Address, uint32_t Data0)
{
        FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset);

    FLASH->CTLR |= CR_PAGE_PG;
    *(__IO uint32_t *)(Address) = Data0;
    FLASH->CTLR |= CR_BUF_LOAD;
    while(FLASH->STATR & SR_BSY)
        ;
    FLASH->CTLR &= ~CR_PAGE_PG;
}

X035主存储器标准擦除:

256B,1K,32K擦除

/*********************************************************************
 * @fn      ROM_ERASE
 *
 * @brief   Select erases a specified FLASH .
 *
 * @param   StartAddr - Erases Flash start address(StartAddr%256 == 0).
 *          Cnt - Erases count.
 *          Erase_Size - Erases size select.The returned value can be:
 *          Size_32KB, Size_1KB, Size_256B.
 *
 * @return  none.
 */
static void ROM_ERASE(uint32_t StartAddr, uint32_t Cnt, uint32_t Erase_Size)
{
        FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset);

    do{
        if(Erase_Size == Size_32KB)
        {
            FLASH->CTLR |= CR_BER32;
        }
        else if(Erase_Size == Size_1KB)
        {
            FLASH->CTLR |= CR_PER_Set;
        }
        else if(Erase_Size == Size_256B)
        {
            FLASH->CTLR |= CR_PAGE_ER;
        }

        FLASH->ADDR = StartAddr;
        FLASH->CTLR |= CR_STRT_Set;
        while(FLASH->STATR & SR_BSY)
            ;

        if(Erase_Size == Size_32KB)
        {
            FLASH->CTLR &= ~CR_BER32;
            StartAddr += Size_32KB;
        }
        else if(Erase_Size == Size_1KB)
        {
            FLASH->CTLR &= ~CR_PER_Set;
            StartAddr += Size_1KB;
        }
        else if(Erase_Size == Size_256B)
        {
            FLASH->CTLR &= ~CR_PAGE_ER;
            StartAddr += Size_256B;
        }
    }while(--Cnt);
}

256B倍数擦除

/*********************************************************************
 * @fn      FLASH_ROM_ERASE
 *
 * @brief   Erases a specified FLASH .
 *
 * @param   StartAddr - Erases Flash start address(StartAddr%256 == 0).
 *          Length - Erases Flash start Length(Length%256 == 0).
 *
 * @return  FLASH Status - The returned value can be: FLASH_ADR_RANGE_ERROR,
 *        FLASH_ALIGN_ERROR, FLASH_OP_RANGE_ERROR or FLASH_COMPLETE.
 */
FLASH_Status FLASH_ROM_ERASE(uint32_t StartAddr, uint32_t Length)
{
    uint32_t Addr0 = 0, Addr1 = 0, Length0 = 0, Length1 = 0;

    FLASH_Status status = FLASH_COMPLETE;

    if((StartAddr < ValidAddrStart) || (StartAddr >= ValidAddrEnd))
    {
        return FLASH_ADR_RANGE_ERROR;
    }

    if((StartAddr + Length) > ValidAddrEnd)
    {
        return FLASH_OP_RANGE_ERROR;
    }

    if((StartAddr & (Size_256B-1)) || (Length & (Size_256B-1)) || (Length == 0))
    {
        return FLASH_ALIGN_ERROR;
    }

    /* Authorize the FPEC of Bank1 Access */
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;

    /* Fast mode unlock */
    FLASH->MODEKEYR = FLASH_KEY1;
    FLASH->MODEKEYR = FLASH_KEY2;

    Addr0 = StartAddr;

    if(Length >= Size_32KB)
    {
        Length0 = Size_32KB - (Addr0 & (Size_32KB - 1));
        Addr1 = StartAddr + Length0;
        Length1 = Length - Length0;
    }
    else if(Length >= Size_1KB)
    {
        Length0 = Size_1KB - (Addr0 & (Size_1KB - 1));
        Addr1 = StartAddr + Length0;
        Length1 = Length - Length0;
    }
    else if(Length >= Size_256B)
    {
        Length0 = Length;
    }

    /* Erase 32KB */
    if(Length0 >= Size_32KB)//front
    {
        Length = Length0;
        if(Addr0 & (Size_32KB - 1))
        {
            Length0 = Size_32KB - (Addr0 & (Size_32KB - 1));
        }
        else
        {
            Length0 = 0;
        }

        ROM_ERASE((Addr0 + Length0), ((Length - Length0) >> 15), Size_32KB);
    }

    if(Length1 >= Size_32KB)//back
    {
        StartAddr = Addr1;
        Length = Length1;

        if((Addr1 + Length1) & (Size_32KB - 1))
        {
            Addr1 = ((StartAddr + Length1) & (~(Size_32KB - 1)));
            Length1 = (StartAddr + Length1) & (Size_32KB - 1);
        }
        else
        {
            Length1 = 0;
        }

        ROM_ERASE(StartAddr, ((Length - Length1) >> 15), Size_32KB);
    }

    /* Erase 1KB */
    if(Length0 >= Size_1KB) //front
    {
        Length = Length0;
        if(Addr0 & (Size_1KB - 1))
        {
            Length0 = Size_1KB - (Addr0 & (Size_1KB - 1));
        }
        else
        {
            Length0 = 0;
        }

        ROM_ERASE((Addr0 + Length0), ((Length - Length0) >> 10), Size_1KB);
    }

    if(Length1 >= Size_1KB) //back
    {
        StartAddr = Addr1;
        Length = Length1;

        if((Addr1 + Length1) & (Size_1KB - 1))
        {
            Addr1 = ((StartAddr + Length1) & (~(Size_1KB - 1)));
            Length1 = (StartAddr + Length1) & (Size_1KB - 1);
        }
        else
        {
            Length1 = 0;
        }

        ROM_ERASE(StartAddr, ((Length - Length1) >> 10), Size_1KB);
    }

    /* Erase 256B */
    if(Length0)//front
    {
        ROM_ERASE(Addr0, (Length0 >> 8), Size_256B);
    }

    if(Length1)//back
    {
        ROM_ERASE(Addr1, (Length1 >> 8), Size_256B);
    }

    FLASH->CTLR |= CR_FLOCK_Set;
    FLASH->CTLR |= CR_LOCK_Set;

    return status;
}

X035主存储器快速擦除:

256B,32K

/*********************************************************************
 * @fn      FLASH_ErasePage_Fast
 *
 * @brief   Erases a specified FLASH page (1page = 256Byte).
 *
 * @param   Page_Address - The page address to be erased.
 *
 * @return  none
 */
void FLASH_ErasePage_Fast(uint32_t Page_Address)
{
        FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset);

    FLASH->CTLR |= CR_PAGE_ER;
    FLASH->ADDR = Page_Address;
    FLASH->CTLR |= CR_STRT_Set;
    while(FLASH->STATR & SR_BSY)
        ;
    FLASH->CTLR &= ~CR_PAGE_ER;
}

/*********************************************************************
 * @fn      FLASH_EraseBlock_32K_Fast
 *
 * @brief   Erases a specified FLASH Block (1Block = 32KByte).
 *
 * @param   Block_Address - The block address to be erased.
 *
 * @return  none
 */
void FLASH_EraseBlock_32K_Fast(uint32_t Block_Address)
{
        FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset);

    Block_Address &= 0xFFFF8000;

    FLASH->CTLR |= CR_BER32;
    FLASH->ADDR = Block_Address;
    FLASH->CTLR |= CR_STRT_Set;
    while(FLASH->STATR & SR_BSY)
        ;
    FLASH->CTLR &= ~CR_BER32;
}

好的,关于v203和0x35两款芯片的flash擦除和写入基本上就是这些函数,基本上分为标准和快速,在快速模式下,flash写入和擦除速度会比标准模式快上许多,适合在高速率通信下使用,两款芯片使用flash的读、写、擦除函数大部分一致,如果想要看具体如何使用,可以去沁恒官方下载案例分析。在不同场景下合理利用这些函数,能够使工作效率大大提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值