1、STM8的外设库驱动提供了很多代码,要求不高的话直接用库驱动即可
2、Flash块擦写速度快,但是必须要把函数放到RAM中执行(因为MCU的是NorFlash,普通的函数都是直接在Flash上执行的)
官方库如下
/**
* @brief Erases a block in the program or data memory.
* @note This function should be executed from RAM.
* @param FLASH_MemType : The type of memory to erase
* @param BlockNum : Indicates the block number to erase
* @retval None.
*/
IN_RAM(void FLASH_EraseBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType))
{
uint32_t startaddress = 0;
#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||
defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x)
uint32_t PointerAttr *pwFlash;
#elif defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF62Ax) || defined (STM8AF52Ax)
uint8_t PointerAttr *pwFlash;
#endif
/* Check parameters */
assert_param(IS_MEMORY_TYPE_OK(FLASH_MemType));
if(FLASH_MemType == FLASH_MEMTYPE_PROG)
{
assert_param(IS_FLASH_PROG_BLOCK_NUMBER_OK(BlockNum));
startaddress = FLASH_PROG_START_PHYSICAL_ADDRESS;
}
else
{
assert_param(IS_FLASH_DATA_BLOCK_NUMBER_OK(BlockNum));
startaddress = FLASH_DATA_START_PHYSICAL_ADDRESS;
}
/* Point to the first block address */
#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF62Ax) || defined (STM8AF52Ax)
pwFlash = (PointerAttr uint8_t *)(MemoryAddressCast)(startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE));
#elif defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||
defined(STM8S001) || defined (STM8S903) || defined (STM8AF626x) || defined (STM8AF622x)
pwFlash = (PointerAttr uint32_t *)(MemoryAddressCast)(startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE));
#endif /* STM8S208, STM8S207 */
/* Enable erase block mode */
FLASH->CR2 |= FLASH_CR2_ERASE;
FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NERASE);
#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||
defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x)
*pwFlash = (uint32_t)0;
#elif defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF62Ax) ||
defined (STM8AF52Ax)
*pwFlash = (uint8_t)0;
*(pwFlash + 1) = (uint8_t)0;
*(pwFlash + 2) = (uint8_t)0;
*(pwFlash + 3) = (uint8_t)0;
#endif
}
/**
* @brief Programs a memory block
* @note This function should be executed from RAM.
* @param FLASH_MemType : The type of memory to program
* @param BlockNum : The block number
* @param FLASH_ProgMode : The programming mode.
* @param Buffer : Pointer to buffer containing source data.
* @retval None.
*/
IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType,
FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer))
{
uint16_t Count = 0;
uint32_t startaddress = 0;
/* Check parameters */
assert_param(IS_MEMORY_TYPE_OK(FLASH_MemType));
assert_param(IS_FLASH_PROGRAM_MODE_OK(FLASH_ProgMode));
if(FLASH_MemType == FLASH_MEMTYPE_PROG)
{
assert_param(IS_FLASH_PROG_BLOCK_NUMBER_OK(BlockNum));
startaddress = FLASH_PROG_START_PHYSICAL_ADDRESS;
}
else
{
assert_param(IS_FLASH_DATA_BLOCK_NUMBER_OK(BlockNum));
startaddress = FLASH_DATA_START_PHYSICAL_ADDRESS;
}
/* Point to the first block address */
startaddress = startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE);
/* Selection of Standard or Fast programming mode */
if(FLASH_ProgMode == FLASH_PROGRAMMODE_STANDARD)
{
/* Standard programming mode */ /*No need in standard mode */
FLASH->CR2 |= FLASH_CR2_PRG;
FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NPRG);
}
else
{
/* Fast programming mode */
FLASH->CR2 |= FLASH_CR2_FPRG;
FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NFPRG);
}
/* Copy data bytes from RAM to FLASH memory */
for(Count = 0; Count < FLASH_BLOCK_SIZE; Count++)
{
*((PointerAttr uint8_t*) (MemoryAddressCast)startaddress + Count) = ((uint8_t)(Buffer[Count]));
}
}
默认IN_RAM是不打开,需要#define RAM_EXECUTION (1)
这样就可以用库里的块擦写函数了
3、分析一下库的代码,发现
擦除和写入命令差不多:首先操作FLASH->CR2和FLASH->NCR2,然后在相应的Flash上写数据,擦除写4个0即可
于是自己重写一下驱动
typedef byte (* flashProgramCodeInRamFun)(byte cr2, byte ncr2, word BlockNum, byte length, byte *Buffer);
__ramfunc byte LaunchFlashCommand(byte cr2, byte ncr2, word BlockNum, byte length, byte *Buffer)
{
uint16_t Count = 0;
uint32_t addr;
addr = BlockNum;
addr *= FLASH_BLOCK_SIZE;
addr += FLASH_PROG_START_PHYSICAL_ADDRESS;
/* Unlock program memory */
FLASH->PUKR = FLASH_RASS_KEY1;
FLASH->PUKR = FLASH_RASS_KEY2;
FLASH->CR2 |= cr2;
FLASH->NCR2 &= (uint8_t)(~ncr2);
for (Count = 0; Count < length; Count++)
{
*((PointerAttr uint8_t*) (uint32_t)addr + Count) = ((uint8_t)(Buffer[Count]));
}
while( (FLASH->IAPSR & (FLASH_IAPSR_EOP | FLASH_IAPSR_WR_PG_DIS)) == 0);
/* Lock memory */
FLASH->IAPSR &= (uint8_t)FLASH_MEMTYPE_PROG;
return FLASH_NO_ERROR;
}
byte PFlashEraseBlock(dword gAddr)
{
static byte data[]={0,0,0,0};
byte ret = 0;
dword blockNum = (gAddr - FLASH_PROG_START_PHYSICAL_ADDRESS) / FLASH_SECTOR_SIZE;
ret = ((flashProgramCodeInRamFun)DRIVER_ADDR)(FLASH_CR2_ERASE, FLASH_NCR2_NERASE, blockNum, 4, data);
return ret;
}
byte PFlashProg(dword gAddr, byte len, byte *pDat)
{
byte ret = 0;
dword blockNum = (gAddr - FLASH_PROG_START_PHYSICAL_ADDRESS) / FLASH_SECTOR_SIZE;
ret = ((flashProgramCodeInRamFun)DRIVER_ADDR)(FLASH_CR2_PRG, FLASH_NCR2_NPRG, blockNum, FLASH_SECTOR_SIZE, pDat);
return ret;
}
(1)那么我想把地址直接传到LaunchFlashCommand中不用BlockNum行不行呢?
答案是分情况:如果参数是u16则完全没问题,适合32K以内的小容量MCU,如果是u32的参数则会出问题,程序跑飞
因此地址空间只有8000~FFFF=32K
(2)我想把函数放到固定地址上,参数是u16的BlockNum,不用__ramfunc 行不行?
答案也是分情况:如果在LaunchFlashCommand不用u32就可以,因此地址空间仍是32K
方法如下:
在icf中设置place at address mem: 0x0000CE00 { readonly section .funflash };
然后函数定义时:byte LaunchFlashCommand(byte cr2, byte ncr2, word BlockNum, byte length, byte *Buffer) @ ".funflash"
使用时手动将数据copy到ram中,长度在hex文件中查看
(3)为什么不能直接传u32的地址?为什么不用__ramfunc自己直接copy机器码,函数中使用u32就不行?
这问题我回答不上来,使用飞思卡尔的16位MCU也有类似的现象,自己指定函数地址,copy到ram,函数里如果使用u32则会出错。比较一下生成的hex文件,两种方式生成的机器码也不一样。
4、如何提取Flash驱动呢?
在汽车ECU上,OEM处于于安全考虑要求Flash的擦写函数不能保存在Flash中;执行Bootloader之前首先将Flash擦写函数(称之为驱动)发给MCU,MCU放到RAM里执行,用毕清空。
因此如何提取呢?
(1)查找map文件,找到LaunchFlashCommand的地址和长度
(2)仿真时,查看RAM窗口,找到LaunchFlashCommand部分的数据,选中复制
(3)将复制的数据做成s19或者hex文件
上一篇:STM8S——Clock control(CLK)
下一篇:stm8s eeprom读写
推荐阅读
史海拾趣
随着国内市场的饱和,CTI开始将目光投向海外市场。公司制定了国际化发展战略,积极开拓国际市场。通过设立海外分支机构、参加国际展会等方式,CTI的产品逐渐打入国际市场,并获得了良好的口碑。同时,公司还与国外企业开展技术合作和产品研发,进一步提升了公司的国际化水平。
CyOptics Inc公司自创立以来,一直专注于磷化铟(InP)光学芯片及组件的研发和生产。凭借其在光学领域的深厚积累和技术创新,CyOptics逐渐在数据通讯及电信市场上树立了技术领先的形象。公司的850nm多模VCSEL和PIN器件等产品,因其高性能和可靠性,被广泛应用于短距离数据通信网络中,获得了市场的广泛认可。
在电子行业竞争日益激烈的背景下,安普康深知创新是企业发展的核心动力。因此,公司始终将研发投入作为重要战略之一。通过引进先进的生产设备和技术,安普康不断提升产品的品质和性能。同时,公司还积极与国内外知名企业和研究机构合作,共同开展技术研发和创新。这些努力使得安普康在光纤产品、布线产品等领域取得了多项专利,并成功推出了一系列具有市场竞争力的新产品。
Babcock Inc公司的创立源于创始人对电子技术的深厚热爱和前瞻视野。在创业初期,公司便致力于电子技术的研发与创新,不断积累核心技术和专利。通过持续的技术投入和人才培养,Babcock逐渐在电子行业崭露头角,为后续的快速发展奠定了坚实的基础。
随着消费者对家庭娱乐和智能生活的需求不断增长,Cavium Networks 敏锐地捕捉到了这一市场趋势。公司推出了面向消费者市场的无线显示解决方案 WiVu,利用最新的笔记本电脑技术如嵌入式 DisplayPort 和显示迷你卡(DMC),为多房间和交互式应用提供了高性能的 Wi-Fi 无线显示解决方案。WiVu 的推出不仅满足了消费者对便捷、高效、高质量的娱乐体验的需求,也引领了市场的新潮流,进一步巩固了 Cavium Networks 在电子行业中的地位。
《程序员》杂志,最近要100期了,关注了一下。 不知道这本杂志,合适我们做嵌入式开发的么?有没有相关的WinCE嵌入式专题? 值得订阅么?… 查看全部问答∨ |
|
求 ps2鼠标和cpu的连线图! 小弟过2天就要交毕业设计了,老师非得让我加个图.我的论文题目是基于嵌入式的PS/2鼠标接口设计. 拜托各位大哥大姐帮我下. 小弟不胜感激!在线等图. 把图发上 ...… 查看全部问答∨ |
使用同样的AT指令分别在超级终端下和用代码方式发向手机模块,结果前者可以收到结果而后都却收不到。 请问这是什么原因呢?我估计是配置问题,像波特率等。你的看法呢?谢谢。 … 查看全部问答∨ |
整了很多天的STM32 汇编,想通过HJTAG 进行源码级调试,一直未成功。 有什么法子?还是HJTAG不支持STM32的源码级调试?真闷啊!… 查看全部问答∨ |
|
想不通,为什么我板子和数据线放在朋友电脑上,然后用mucisp烧录后,就有反应,在我电脑上只是lcd晾着 是不是有地方还要设置呢?从哪里发现? 有没有什么检查的方法… 查看全部问答∨ |