933 lines
27 KiB
C
Raw Normal View History

/*
*********************************************************************************************************
*
* : 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 : 01
* _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 STM8SSTM8L个系列均相同
* : 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_PROGFLASH_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_PROGFLASH_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 : 1block
* : 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 : 1block
* : 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_PROGFLASH_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_PROGFLASH_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 : 1block
* : 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解锁过程获得的数据
* :
* : 1OK, 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) *********************************/