/* ********************************************************************************************************* * * 模块名称 : 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) { re = STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 2000); /* 1000ms超时 */ } else { re = STM8_WaitIAPSR_Flag(STM8_FLASH_IAPSR_EOP, 1, 50); /* 50ms超时 */ } if (re == 0) { goto err_quit; } 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) { 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; } /* ********************************************************************************************************* * 函 数 名: 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) *********************************/