933 lines
27 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
*
* 模块名称 : stm8系列flash访问程序
* 文件名称 : stm8_flash.c
* 版 本 : V1.0
* 说 明 : STM8 flash编程函数。根据STM8各个系列的固件库汇总而成。
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2020-02-08 armfly 原创。
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "DAP_config.h"
#include "stm8_swim.h"
#include "stm8_flash.h"
#include "stm8.h"
///* STM8S 寄存器定义 */
//#define STM8_FLASH_OPT 0x00004800
//#define STM8_FLASH_PUKR 0x00005062
//#define STM8_FLASH_DUKR 0x00005064
//#define STM8_FLASH_CR2 0x0000505B
//#define STM8_FLASH_IAPSR 0x0000505f
//#define STM8_FLASH_FPR 0x0000505D
//#define CLK_SWIMCCR 0x000050CD
//#define SWIM_CSR 0x00007F80
//#define DM_CSR2 0x00007F99
//#define STM8_FLASH_EOF 0x04
//#define STM8_FLASH_WR_PG_DIS 0x01
//#define STM8_FLASH_HVOFF 0x40
//#define PAGE_BLOCK_SIZE_64 64
//#define PAGE_BLOCK_SIZE_128 128
//static const uint8_t OPT_UNL[16] = {0x00,0x00,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0x55};
//static const uint8_t OPT_LCK[16] = {0xAA,0x00,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0,0xFF,0x55};
uint16_t s_STM8_SerialType = 0; /* 0 = STM8S, 1 = STM8L */
uint16_t s_STM8_BlockSize = 64; /* 块大小64或者128字节 */
uint16_t s_STM8_HVOFF = 0; /* 等待完成的标志选择 */
uint32_t s_STM8_FlashSize = 32 * 1024; /* FLASH 容量 */
uint32_t s_STM8_EEPromSize = 32 * 1024; /* EEPROM 容量 */
//#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) ||
// defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined(STM8AF626x)
// FLASH_FLAG_HVOFF = (uint8_t)0x40, /*!< End of high voltage flag */
//#endif /* STM8S208, STM8S207, STM8S105, STM8AF62Ax, STM8AF52Ax, STM8AF626x */
#define STM8_ERASE_BLOCK_TIMEOUT 100 /* 100ms */
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_WaitForLastOperation
* 功能说明: 等待内部写操作完成. STM8_FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG);
* 形 参: _uiTimeout : 超时时间ms
* 返 回 值:
*********************************************************************************************************
*/
uint8_t STM8_FLASH_WaitForLastOperation(uint8_t FLASH_MemType, uint32_t _uiTimeout)
{
uint32_t re = 0;
int32_t s_time;
s_time = bsp_GetRunTime();
if (FLASH_MemType == FLASH_MEMTYPE_PROG)
{
while (1)
{
if (s_STM8_SerialType == STM8S)
{
re = SWIM_ReadByte(STM8S_FLASH_IAPSR);
}
else if (s_STM8_SerialType == STM8L)
{
re = SWIM_ReadByte(STM8L_FLASH_IAPSR);
}
if (re & (STM8_FLASH_IAPSR_EOP | STM8_FLASH_IAPSR_WR_PG_DIS))
{
re = 1;
break;
}
if (bsp_CheckRunTime(s_time) >= _uiTimeout)
{
re = 0;
break;
}
}
return re;
}
else if (FLASH_MemType == FLASH_MEMTYPE_DATA) /* EEPROM 的判断条件复杂些 */
{
while (1)
{
if (s_STM8_SerialType == STM8S)
{
re = SWIM_ReadByte(STM8S_FLASH_IAPSR);
}
else if (s_STM8_SerialType == STM8L)
{
re = SWIM_ReadByte(STM8L_FLASH_IAPSR);
}
if (s_STM8_HVOFF == 1)
{
if (re & (STM8_FLASH_IAPSR_HVOFF | STM8_FLASH_IAPSR_WR_PG_DIS))
{
re = 1;
break;
}
}
else
{
if (re & (STM8_FLASH_IAPSR_EOP | STM8_FLASH_IAPSR_WR_PG_DIS))
{
re = 1;
break;
}
}
if (bsp_CheckRunTime(s_time) >= _uiTimeout)
{
re = 0;
break;
}
}
return re;
}
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_WaitIAPSR_Flag
* 功能说明: 等待内部操作完成. 读STM8S_FLASH_IAPSR
* 形 参: _Flag : 判断标志位
* _BitValue : 0或1表示返回的条件
* _uiTimeout : 超时时间ms
* 返 回 值: 0 超时1 成功
*********************************************************************************************************
*/
uint8_t STM8_WaitIAPSR_Flag(uint8_t _Flag, uint8_t _BitValue, uint32_t _uiTimeout)
{
uint8_t re = 0;
int32_t s_time;
s_time = bsp_GetRunTime();
while (1)
{
if (s_STM8_SerialType == STM8S)
{
re = SWIM_ReadByte(STM8S_FLASH_IAPSR);
}
else if (s_STM8_SerialType == STM8L)
{
re = SWIM_ReadByte(STM8L_FLASH_IAPSR);
}
if (_BitValue == 0)
{
if ((re & _Flag) == 0)
{
re = 1;
break;
}
}
else
{
if ((re & _Flag) == _Flag)
{
re = 1;
break;
}
}
if (bsp_CheckRunTime(s_time) >= _uiTimeout)
{
re = 0;
break;
}
}
return re;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_Unlock
* 功能说明: 解锁允许写flash和eeprom。 STM8S、STM8L个系列均相同
* 形 参: FlashAddr : 地址
* 返 回 值: 无
*********************************************************************************************************
*/
void STM8_FLASH_Unlock(void)
{
if (s_STM8_SerialType == STM8S)
{
/* Unlock program memory */
SWIM_WriteByte(STM8S_FLASH_PUKR, STM8_FLASH_RASS_KEY1);
// bsp_DelayUS(50);
SWIM_WriteByte(STM8S_FLASH_PUKR, STM8_FLASH_RASS_KEY2);
// bsp_DelayUS(50);
/* Unlock data memory */
/* Warning: keys are reversed on data memory !!! */
SWIM_WriteByte(STM8S_FLASH_DUKR, STM8_FLASH_RASS_KEY2);
// bsp_DelayUS(50);
SWIM_WriteByte(STM8S_FLASH_DUKR, STM8_FLASH_RASS_KEY1);
// bsp_DelayUS(50);
}
else if (s_STM8_SerialType == STM8L)
{
/* Unlock program memory */
SWIM_WriteByte(STM8L_FLASH_PUKR, STM8_FLASH_RASS_KEY1);
// bsp_DelayUS(50);
SWIM_WriteByte(STM8L_FLASH_PUKR, STM8_FLASH_RASS_KEY2);
// bsp_DelayUS(50);
/* Unlock data memory */
/* Warning: keys are reversed on data memory !!! */
SWIM_WriteByte(STM8L_FLASH_DUKR, STM8_FLASH_RASS_KEY2);
// bsp_DelayUS(50);
SWIM_WriteByte(STM8L_FLASH_DUKR, STM8_FLASH_RASS_KEY1);
// bsp_DelayUS(50);
}
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_DUL | STM8_FLASH_IAPSR_PUL, 1, 20);
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_Lock
* 功能说明: Locks the program or data EEPROM memory
* 形 参: _FLASH_MemType : FLASH_MEMTYPE_PROG、FLASH_MEMTYPE_DATA
* 返 回 值: 无
*********************************************************************************************************
*/
void STM8_FLASH_Lock(uint32_t FlashAddr)
{
FLASH_MemType_TypeDef FLASH_MemType;
if (FlashAddr < 0x8000)
{
FLASH_MemType = FLASH_MEMTYPE_DATA;
}
else
{
FLASH_MemType = FLASH_MEMTYPE_PROG;
}
if (s_STM8_SerialType == STM8S)
{
uint8_t iapsr;
iapsr = SWIM_ReadByte(STM8S_FLASH_IAPSR);
iapsr &= (uint8_t)FLASH_MemType;
/* Lock memory */
SWIM_WriteByte(STM8S_FLASH_IAPSR, iapsr);
}
else if (s_STM8_SerialType == STM8L)
{
uint8_t iapsr;
iapsr = SWIM_ReadByte(STM8L_FLASH_IAPSR);
iapsr &= (uint8_t)FLASH_MemType;
/* Lock memory */
SWIM_WriteByte(STM8L_FLASH_IAPSR, iapsr);
}
}
/*
*********************************************************************************************************
* 函 数 名: STM8_WriteReg_CR2
* 功能说明: 写CR2寄存器. 比如 STM8_WriteReg_CR2(STM8_FLASH_CR2_OPT)
* 形 参: _value : 0禁止 1是使能
* 返 回 值: 无
*********************************************************************************************************
*/
void STM8_WriteReg_CR1(uint8_t _value)
{
uint8_t buf[1];
buf[0] = _value;
if (s_STM8_SerialType == STM8S)
{
SWIM_WriteBuf(STM8S_FLASH_CR1, buf, 1);
}
else if (s_STM8_SerialType == STM8L)
{
SWIM_WriteBuf(STM8L_FLASH_CR1, buf, 1);
}
}
/*
*********************************************************************************************************
* 函 数 名: STM8_WriteReg_CR2
* 功能说明: 写CR2寄存器. 比如 STM8_WriteReg_CR2(STM8_FLASH_CR2_OPT)
* 形 参: _value : 0禁止 1是使能
* 返 回 值: 无
*********************************************************************************************************
*/
void STM8_WriteReg_CR2(uint8_t _value)
{
uint8_t buf[2];
buf[0] = _value;
buf[1] = ~buf[0];
if (s_STM8_SerialType == STM8S)
{
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2);
}
else if (s_STM8_SerialType == STM8L)
{
SWIM_WriteBuf(STM8L_FLASH_CR2, buf, 1);
}
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_EraseBlock
* 功能说明: Erases a block in the program or data memory.
* 形 参: FlashAddr : 绝对地址。 必须是block首地址
* FLASH_MemType : FLASH_MEMTYPE_PROG、FLASH_MEMTYPE_DATA
* 返 回 值: 无
*********************************************************************************************************
*/
void STM8_FLASH_EraseBlock(uint32_t FlashAddr)
{
uint32_t BlockAddr = 0;
const uint8_t zefo[4] = {0,0,0,0};
BlockAddr = (FlashAddr / s_STM8_BlockSize) * s_STM8_BlockSize;
/* Enable erase block mode */
STM8_WriteReg_CR2(STM8_FLASH_CR2_ERASE);
SWIM_WriteBuf(BlockAddr, (uint8_t *)zefo, 4);
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 10);
// if (BlockAddr < 0x8000)
// {
// STM8_FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA, 100);
// }
// else
// {
// STM8_FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG, 100);
// }
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_ProgramBlock
* 功能说明: Programs a memory block
* 形 参: FlashAddr : 绝对地址。 必须是block首地址
* Buffer : Pointer to buffer containing source data.
* 返 回 值: 0:失败 1:成功
*********************************************************************************************************
*/
uint8_t STM8_FLASH_ProgramBlock(uint32_t FlashAddr, uint8_t *Buffer)
{
FLASH_MemType_TypeDef FLASH_MemType;
uint32_t BlockAddr = 0;
uint8_t re;
BlockAddr = (FlashAddr / s_STM8_BlockSize) * s_STM8_BlockSize;
if (BlockAddr < 0x8000)
{
FLASH_MemType = FLASH_MEMTYPE_DATA;
}
else
{
FLASH_MemType = FLASH_MEMTYPE_PROG;
}
if (s_STM8_SerialType == STM8L)
{
STM8_WriteReg_CR2(STM8_FLASH_CR2_PRG);
}
else
{
STM8_WriteReg_CR1(STM8_FLASH_PROGRAMTIME_TPROG); /* 设置快速编程模式 */
bsp_DelayUS(100);
STM8_WriteReg_CR2(STM8_FLASH_CR2_FPRG);
}
re = SWIM_WriteBuf(BlockAddr, Buffer, s_STM8_BlockSize);
if (re == 0) goto err_quit;
bsp_DelayUS(100);
#if 1
re = STM8_FLASH_WaitForLastOperation(FLASH_MemType, STM8_ERASE_BLOCK_TIMEOUT);
#else
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 20);
#endif
if (re == 0) goto err_quit;
return 1;
err_quit:
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_ProgramBuf
* 功能说明: Programs a memory block
* 形 参: _FlashAddr : 绝对地址。
* _Buff : Pointer to buffer containing source data.
* _Size : 数据大小可以大于1个block
* 返 回 值: 0 : 出错; 1 : 成功
*********************************************************************************************************
*/
uint8_t STM8_FLASH_ProgramBuf(uint32_t _FlashAddr, uint8_t *_Buff, uint32_t _Size)
{
uint32_t i;
uint32_t BlockAddr = 0;
uint8_t buf0[128]; /* 一般就是64或者128 */
uint8_t *pSrc;
uint32_t size;
uint8_t re = 0;
pSrc = _Buff;
/* 计算block首地址 */
BlockAddr = (_FlashAddr / s_STM8_BlockSize) * s_STM8_BlockSize;
/* 烧录第一个block */
if (BlockAddr != _FlashAddr)
{
uint16_t offset;
uint16_t len;
re = SWIM_ReadBuf(BlockAddr, buf0, s_STM8_BlockSize);
if (re == 0)
{
goto err_quit;
}
if (CheckBlankBuf((char *)buf0, s_STM8_BlockSize, 0) == 0)
{
STM8_FLASH_EraseBlock(BlockAddr);
}
offset = _FlashAddr - BlockAddr;
if (offset + _Size < s_STM8_BlockSize)
{
len = _Size;
}
else
{
len = s_STM8_BlockSize - offset;
}
for (i = 0; i < len; i++)
{
buf0[i + offset] = *pSrc++;
_Size--;
_FlashAddr++;
}
re = STM8_FLASH_ProgramBlock(BlockAddr, buf0);
if (re == 0)
{
goto err_quit;
}
}
/* 烧录中间block */
size = _Size;
for (i = 0; i < size / s_STM8_BlockSize; i++)
{
// re = SWIM_ReadBuf(BlockAddr, buf0, s_STM8_BlockSize);
// if (re == 0)
// {
// goto err_quit;
// }
//
// if (CheckBlankBuf((char *)buf0, s_STM8_BlockSize, 0) == 0)
// {
// STM8_FLASH_EraseBlock(BlockAddr);
// }
re = STM8_FLASH_ProgramBlock(_FlashAddr, pSrc);
if (re == 0)
{
goto err_quit;
}
pSrc += s_STM8_BlockSize;
_Size -= s_STM8_BlockSize;
_FlashAddr += s_STM8_BlockSize;
}
/* 烧录最后一个block */
if (_Size > 0)
{
re = SWIM_ReadBuf(BlockAddr, buf0, s_STM8_BlockSize);
if (re == 0)
{
goto err_quit;
}
if (CheckBlankBuf((char *)buf0, s_STM8_BlockSize, 0) == 0)
{
STM8_FLASH_EraseBlock(BlockAddr);
}
for (i = 0; i < _Size; i++)
{
buf0[i] = *pSrc++;
}
re = STM8_FLASH_ProgramBlock(_FlashAddr, buf0);
if (re == 0)
{
goto err_quit;
}
}
return 1;
err_quit:
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_ProgramOptionBytes
* 功能说明: Programs option byte
* 形 参: _AddrBuf : 地址数组,大端模式排列.
* _AddrLen : _AddrLen
* _DataBuf : 输入数据
* _DataLen : 数据大小可以大于1个block
* 返 回 值: 0 : 出错; 1 : 成功
*********************************************************************************************************
*/
uint8_t STM8_ProgramOptionBytes(uint8_t *_AddrBuf, uint16_t _AddrLen, uint8_t *_DataBuf, uint16_t _DataLen)
{
uint8_t re;
uint16_t Address;
uint16_t LastAddress;
uint8_t LastData;
if (_DataLen == 0 || _AddrLen == 0 || (_AddrLen % 2) != 0)
{
goto err_quit;
}
while (_AddrLen)
{
STM8_FLASH_Unlock(); /* 允许写Flash和EEProm */
STM8_WriteReg_CR2(STM8_FLASH_CR2_OPT); /* 编程OPT */
Address = BEBufToUint16(_AddrBuf);
_AddrBuf += 2;
bsp_DelayUS(200);
if (Address == 0xFFFF) /* 上一个字节取反写入 */
{
re = SWIM_WriteByte(LastAddress + 1, ~LastData);
if (re == 0)
{
goto err_quit;
}
}
else
{
LastAddress = Address;
LastData = *_DataBuf;
re = SWIM_WriteByte(LastAddress, LastData);
if (re == 0)
{
goto err_quit;
}
_DataBuf++;
}
_AddrLen -= 2;
/* STM8L151 实测寄存器变化 2A 2A 2A -> 4E 判断结束 */
bsp_DelayUS(500);
if (Address == 0x4800)
{
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 1000); /* 1000ms超时 */
}
else
{
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 50); /* 50ms超时 */
}
bsp_DelayUS(50);
STM8_WriteReg_CR2(0); /* 不确定是否需要这句话 解除编程操作*/
bsp_DelayUS(50);
}
return 1; /* 成功 */
err_quit:
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_EraseChip
* 功能说明: 擦除全片FLASH (PROG). 事先需要unlock
* 形 参: FlashAddr : 绝对地址。 0x08000 或者 0x04000
* FLASH_MemType : FLASH_MEMTYPE_PROG、FLASH_MEMTYPE_DATA
* 返 回 值: 0 失败 1 成功
*********************************************************************************************************
*/
uint8_t STM8_FLASH_EraseChip(uint32_t _FlashAddr)
{
#if 0
uint8_t value;
value = 0xAA;
STM8_ProgramOptionBytes(0x4800, &value, 1);
bsp_DelayUS(100);
SWIM_EntrySequence();
STM8_ProgramOptionBytes(0x4800, &value, 1);
bsp_DelayUS(100);
#else
uint32_t i;
const uint8_t zefo[4] = {0,0,0,0};
uint8_t re;
uint32_t FlashSize;
STM8_FLASH_Unlock();
if (_FlashAddr == 0x08000)
{
FlashSize = s_STM8_FlashSize;
}
else if (_FlashAddr == 0x04000)
{
FlashSize = s_STM8_EEPromSize;
}
else
{
goto err_quit;
}
for (i = 0; i < FlashSize / s_STM8_BlockSize; i++)
{
STM8_WriteReg_CR2(STM8_FLASH_CR2_ERASE);
re = SWIM_WriteBuf(_FlashAddr, (uint8_t *)zefo, 4);
if (re == 0)
{
goto err_quit;
}
re = STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 10);
if (re == 0)
{
goto err_quit;
}
_FlashAddr += s_STM8_BlockSize;
}
return 1;
err_quit:
return 0;
#endif
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_EraseSector
* 功能说明: 擦除扇区
* 形 参: FlashAddr : 绝对地址。 0x08000 或者 0x04000
* FLASH_MemType : FLASH_MEMTYPE_PROG、FLASH_MEMTYPE_DATA
* 返 回 值: 0 失败 1 成功
*********************************************************************************************************
*/
uint8_t STM8_FLASH_EraseSector(uint32_t _FlashAddr)
{
const uint8_t zefo[4] = {0,0,0,0};
uint8_t re;
STM8_FLASH_Unlock();
STM8_WriteReg_CR2(STM8_FLASH_CR2_ERASE);
re = SWIM_WriteBuf(_FlashAddr, (uint8_t *)zefo, 4);
if (re == 0)
{
goto err_quit;
}
re = STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 10);
if (re == 0)
{
goto err_quit;
}
return 1;
err_quit:
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_FLASH_ReadBuf
* 功能说明: 读flash
* 形 参: _FlashAddr : 绝对地址。
* _Buff : Pointer to buffer containing source data.
* _Size : 数据大小可以大于1个block
* 返 回 值: 0 : 出错; 1 : 成功
*********************************************************************************************************
*/
uint8_t STM8_FLASH_ReadBuf(uint32_t _FlashAddr, uint8_t *_Buff, uint32_t _Size)
{
uint32_t i;
uint8_t *pSrc;
uint32_t size;
uint8_t re = 0;
pSrc = _Buff;
size = _Size;
for (i = 0; i < size / s_STM8_BlockSize; i++)
{
re = SWIM_ReadBuf(_FlashAddr, pSrc, s_STM8_BlockSize);
if (re == 0)
{
goto err_quit;
}
pSrc += s_STM8_BlockSize;
_Size -= s_STM8_BlockSize;
_FlashAddr += s_STM8_BlockSize;
}
if (_Size > 0)
{
re = SWIM_ReadBuf(_FlashAddr, pSrc, _Size);
if (re == 0)
{
goto err_quit;
}
}
return 1;
err_quit:
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: STM8_UnlockReadProtect
* 功能说明: 解除读保护. 逻辑分析仪跟踪ST-LINK解锁过程获得的数据。
* 形 参: 无
* 返 回 值: 1表示OK, 0表示出错
*********************************************************************************************************
*/
uint8_t STM8_UnlockReadProtect(void)
{
uint8_t buf[8];
uint8_t re;
// SWIM_WriteByte(0x7F80, 0xB0); /* 切换到速模式 */
//
// g_HighSpeed = 1;
//
// bsp_DelayUS(400); /* 延迟400us */
//
// SWIM_WriteByte(0x7F80, 0xB4); /* */
//
// bsp_DelayUS(200); /* 延迟200us */
// SWIM_WriteByte(STM8_CLK_CKDIVR, 0x00); /* STM8_CLK_CKDIVR = 0x50C6 */
//
// SWIM_ReadBuf(0x4FFC, buf, 4); /* 返回 0x67 0x67 0x10 0x03 */
//
// bsp_DelayMS(5); /* 延迟5ms */
//
// SWIM_ReadByte(0x505F); /* 返回 0x80 */
re = SWIM_ReadByte(0x4800); /* 返回 0x71*/
if (re == 0)
bsp_DelayUS(500); /* 延迟500us */
// 42681
SWIM_WriteByte(STM8S_FLASH_PUKR, 0x56); /* STM8S_FLASH_PUKR = 0x5062 */
bsp_DelayUS(260); /* 延迟260us */
// 43058
SWIM_WriteByte(STM8S_FLASH_PUKR, 0xAE); /* STM8S_FLASH_PUKR = 0x5062 */
bsp_DelayUS(260); /* 延迟260us */
SWIM_WriteByte(STM8S_FLASH_DUKR, 0xAE); /* STM8S_FLASH_DUKR = 0x5064 */
bsp_DelayUS(260);
SWIM_WriteByte(STM8S_FLASH_DUKR, 0x56);
bsp_DelayUS(260);
//#define STM8_FLASH_IAPSR_HVOFF ((uint8_t)0x40) /*!< End of high voltage flag mask */
//#define STM8_FLASH_IAPSR_DUL ((uint8_t)0x08) /*!< Data EEPROM unlocked flag mask */
//#define STM8_FLASH_IAPSR_EOP ((uint8_t)0x04) /*!< End of operation flag mask */
//#define STM8_FLASH_IAPSR_PUL ((uint8_t)0x02) /*!< Flash Program memory unlocked flag mask */
//#define STM8_FLASH_IAPSR_WR_PG_DIS ((uint8_t)0x01) /*!< Write attempted to protected page mask */
SWIM_ReadByte(0x505F); /* 返回 0xCA 1100 1010 */
bsp_DelayUS(500);
buf[0] = STM8_FLASH_CR2_OPT; /* STM8_FLASH_CR2_OPT = 0x80 */
buf[1] = ~buf[0];
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2); /* STM8S_FLASH_CR2 = 0x505B */
SWIM_WriteByte(0x4800, 0);
// SWIM_ReadByte(0x505F); /* 返回 AB 1010 1011 STM8S_FLASH_IAPSR = 0x505F */
// SWIM_ReadByte(0x505F); /* 返回 AB 1010 1011 */
//
// SWIM_ReadByte(0x505F); /* 返回 AA 1010 1010 */
// SWIM_ReadByte(0x505F); /* 返回 AA 1010 1010 */
//
// // 48063
// SWIM_ReadByte(0x505F); /* 返回 4E 0100 1110 */
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_WR_PG_DIS | STM8_FLASH_IAPSR_EOP, 1, 50);
bsp_DelayUS(500);
buf[0] = 0x00;
buf[1] = 0xFF;
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2); /* STM8S_FLASH_CR2 = 0x505B */
// 50261
SWIM_WriteByte(STM8S_FLASH_PUKR, 0x56); /* STM8S_FLASH_PUKR = 0x5062 */
bsp_DelayUS(1500);
// 50661
SWIM_WriteByte(STM8S_FLASH_PUKR, 0xAE);
bsp_DelayUS(300);
//51072
SWIM_WriteByte(STM8S_FLASH_DUKR, 0xAE); /* STM8S_FLASH_DUKR = 0x5064 */
// 51432.US
SWIM_WriteByte(STM8S_FLASH_DUKR, 0x56);
bsp_DelayUS(200);
SWIM_ReadByte(0x505F); /* 返回 */
bsp_DelayUS(500);
buf[0] = STM8_FLASH_CR2_OPT; /* STM8_FLASH_CR2_OPT = 0x80 */
buf[1] = ~buf[0]; /* 7F */
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2); /* STM8S_FLASH_CR2 = 0x505B */
bsp_DelayUS(200);
SWIM_WriteByte(0x4801, 0x00);
// SWIM_ReadByte(0x505F); /* 返回 2A 0010 1010 */
// SWIM_ReadByte(0x505F); /* 返回 2A 0010 1010 */
// SWIM_ReadByte(0x505F); /* 返回 6A 0110 1010 */
// SWIM_ReadByte(0x505F); /* 返回 4E 0100 1110 */
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_WR_PG_DIS | STM8_FLASH_IAPSR_EOP, 1, 50);
// 56544
SWIM_WriteByte(0x4802, 0xFF);
// SWIM_ReadByte(0x505F); /* 返回 4E */
// SWIM_ReadByte(0x505F);
// SWIM_ReadByte(0x505F);
// SWIM_ReadByte(0x505F);
// SWIM_ReadByte(0x505F);
STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_WR_PG_DIS | STM8_FLASH_IAPSR_EOP, 1, 50);
// 60.01877
buf[0] = 0x00;
buf[1] = ~buf[0];
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2); /* STM8S_FLASH_CR2 = 0x505B */
bsp_DelayUS(900);
//61129
SWIM_WriteByte(0x5062, 0x56);
bsp_DelayUS(200);
// 61526
SWIM_WriteByte(0x5062, 0xAE);
bsp_DelayUS(200);
// 61915
SWIM_WriteByte(0x5064, 0xAE);
bsp_DelayUS(200);
// 62217
SWIM_WriteByte(0x5064, 0x56);
bsp_DelayUS(200);
// 62527
SWIM_ReadByte(0x505F); /* 返回 4A 0100 1010 */
// 62992
bsp_DelayUS(500);
buf[0] = STM8_FLASH_CR2_OPT; /* STM8_FLASH_CR2_OPT = 0x80 */
buf[1] = ~buf[0]; /* 7F */
SWIM_WriteBuf(STM8S_FLASH_CR2, buf, 2); /* STM8S_FLASH_CR2 = 0x505B */
return 1;
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/