本帖最后由 yewuyi 于 2011-6-23 10:11 编辑
在ST官方提供的STM8S函数库中,找到了三个函数:
1、uint16_t FLASH_ReadOptionByte(uint16_t Address);
2、void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data);
3、void FLASH_EraseOptionByte(uint16_t Address);
第一个是读Option byte,第二个对编程Option byte,第三个擦除Option byte,具体函数实现如下:
/**
* @brief Programs option byte
* @param Address : option byte address to program
* @param Data : Value to write
* @retval None
*/
void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data)
{
/* Check parameter */
assert_param(IS_OPTION_BYTE_ADDRESS_OK(Address));
/* Enable write access to option bytes */
FLASH->CR2 |= FLASH_CR2_OPT;
FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NOPT);
/* check if the option byte to program is ROP*/
if (Address == 0x4800)
{
/* Program option byte*/
*((NEAR uint8_t*)Address) = Data;
}
else
{
/* Program option byte and his complement */
*((NEAR uint8_t*)Address) = Data;
*((NEAR uint8_t*)((uint16_t)(Address + 1))) = (uint8_t)(~Data);
}
FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG);
/* Disable write access to option bytes */
FLASH->CR2 &= (uint8_t)(~FLASH_CR2_OPT);
FLASH->NCR2 |= FLASH_NCR2_NOPT;
}
/**
* @brief Erases option byte
* @param Address : Option byte address to erase
* @retval None
*/
void FLASH_EraseOptionByte(uint16_t Address)
{
/* Check parameter */
assert_param(IS_OPTION_BYTE_ADDRESS_OK(Address));
/* Enable write access to option bytes */
FLASH->CR2 |= FLASH_CR2_OPT;
FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NOPT);
/* check if the option byte to erase is ROP */
if (Address == 0x4800)
{
/* Erase option byte */
*((NEAR uint8_t*)Address) = FLASH_CLEAR_BYTE;
}
else
{
/* Erase option byte and his complement */
*((NEAR uint8_t*)Address) = FLASH_CLEAR_BYTE;
*((NEAR uint8_t*)((uint16_t)(Address + (uint16_t)1 ))) = FLASH_SET_BYTE;
}
FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG);
/* Disable write access to option bytes */
FLASH->CR2 &= (uint8_t)(~FLASH_CR2_OPT);
FLASH->NCR2 |= FLASH_NCR2_NOPT;
}
/**
* @brief Reads one option byte
* @param Address option byte address to read.
* @retval Option byte read value + its complement
*/
uint16_t FLASH_ReadOptionByte(uint16_t Address)
{
uint8_t value_optbyte, value_optbyte_complement = 0;
uint16_t res_value = 0;
/* Check parameter */
assert_param(IS_OPTION_BYTE_ADDRESS_OK(Address));
value_optbyte = *((NEAR uint8_t*)Address); /* Read option byte */
value_optbyte_complement = *(((NEAR uint8_t*)Address) + 1); /* Read option byte complement */
/* Read-out protection option byte */
if (Address == 0x4800)
{
res_value = value_optbyte;
}
else
{
if (value_optbyte == (uint8_t)(~value_optbyte_complement))
{
res_value = (uint16_t)((uint16_t)value_optbyte << 8);
res_value = res_value | (uint16_t)value_optbyte_complement;
}
else
{
res_value = FLASH_OPTIONBYTE_ERROR;
}
}
return(res_value);
}
这些库函数做的非常棒,这说明编译器完全可以在源代码中将选项字节部分的数据编译到烧写芯片的HEX中,但STVD+COSMIC为何单单不给出这个方法,而只给出了在程序代码中通过程序来操作FLASH的方式的写入选项字节。
我实在想不懂STVD+COSMIC如此这般的原因,如果用户根本就不需要在程序烧写后调整选项字节,但按照现在这种方法,依然需要写一大段代码,这岂不是白白浪费代码空间和工程师精力?而且在源代码中加入了这么一段操作选项字节的代码,那么从概率上讲,当MCU的PC指针异常后,完全可能出现非法操作选项字节的可能,这岂不是工程师给自己找麻烦,肯定是吃力不讨好嘛。
总体来说,一个产品设计完毕后,99.999%的用户不太可能再去修改选项字节,STVD+COSMIC为何霍视这绝大多数用户的要求,强烈呼吁ST和COSMIC增加直接在源代码中对选项字节的赋值操作,当然,目前的这三个库函数也应该继续保留,这样也可以满足一些特殊用户的需求。 |