STM32L系列写保护设置

发布于 2020-09-10  575 次阅读


uint32_t StartPage = 0, EndPage = 0, StartBank = 0, EndBank = 0;

static FLASH_OBProgramInitTypeDef OptionsBytesStruct, OptionsBytesStruct2;

static uint32_t GetPage(uint32_t Address);
static uint32_t GetBank(uint32_t Address);

void app_ob_flash_write(rt_uint32_t startaddr, rt_uint32_t endaddr)
{
    /* Unlock the Flash to enable the flash control register access *************/
    HAL_FLASH_Unlock();

    /* Clear OPTVERR bit set on virgin samples */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);

    /* Unlock the Options Bytes *************************************************/
    HAL_FLASH_OB_Unlock();

    /* Get the number of the start and end pages */
    StartPage = GetPage(startaddr);
    EndPage = GetPage(endaddr);

    /* Get the bank of the start and end pages */
    StartBank = GetBank(startaddr);
    EndBank = GetBank(endaddr);

    if (StartBank == EndBank)
    {
        /* WRP area is only on one bank */
        if (StartBank == FLASH_BANK_1)
        {
            OptionsBytesStruct.WRPArea = OB_WRPAREA_BANK1_AREAA;
            OptionsBytesStruct2.WRPArea = OB_WRPAREA_BANK1_AREAB;
        }
        else
        {
            OptionsBytesStruct.WRPArea = OB_WRPAREA_BANK2_AREAA;
            OptionsBytesStruct2.WRPArea = OB_WRPAREA_BANK2_AREAB;
        }
    }
    else
    {
        goto _exit;
    }

    /* Get pages write protection status ****************************************/
    HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
    HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct2);

    /* write option bytes**************************/
    /* Check if desired pages are not yet write protected ***********************/
    if ((OptionsBytesStruct.WRPStartOffset <= StartPage) && (OptionsBytesStruct.WRPEndOffset >= (StartPage - 1)))
    {
        /* Current area is adjacent to pages to be write protected */
        if (OptionsBytesStruct.WRPEndOffset < EndPage)
        {
            /* Current area will be extended to include the pages to be write protected */
            OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;
            OptionsBytesStruct.WRPEndOffset = EndPage;
        }
    }
    else if ((OptionsBytesStruct.WRPStartOffset <= (EndPage + 1)) && (OptionsBytesStruct.WRPEndOffset >= EndPage))
    {
        /* Current area is adjacent to pages to be write protected */
        if (OptionsBytesStruct.WRPStartOffset > StartPage)
        {
            /* Current area will be extended to include the pages to be write protected */
            OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;
            OptionsBytesStruct.WRPStartOffset = StartPage;
        }
    }
    else if ((OptionsBytesStruct.WRPStartOffset > StartPage) && (OptionsBytesStruct.WRPEndOffset < EndPage))
    {
        /* Current area is included in pages to be write protected */
        OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;
        OptionsBytesStruct.WRPStartOffset = StartPage;
        OptionsBytesStruct.WRPEndOffset = EndPage;
    }
    else if ((OptionsBytesStruct2.WRPStartOffset <= StartPage) && (OptionsBytesStruct2.WRPEndOffset >= (StartPage - 1)))
    {
        /* Current area is adjacent to pages to be write protected */
        if (OptionsBytesStruct2.WRPEndOffset < EndPage)
        {
            /* Current area will be extended to include the pages to be write protected */
            OptionsBytesStruct2.OptionType = OPTIONBYTE_WRP;
            OptionsBytesStruct2.WRPEndOffset = EndPage;
        }
    }
    else if ((OptionsBytesStruct2.WRPStartOffset <= (EndPage + 1)) && (OptionsBytesStruct2.WRPEndOffset >= EndPage))
    {
        /* Current area is adjacent to pages to be write protected */
        if (OptionsBytesStruct2.WRPStartOffset > StartPage)
        {
            /* Current area will be extended to include the pages to be write protected */
            OptionsBytesStruct2.OptionType = OPTIONBYTE_WRP;
            OptionsBytesStruct2.WRPStartOffset = StartPage;
        }
    }
    else if ((OptionsBytesStruct2.WRPStartOffset > StartPage) && (OptionsBytesStruct2.WRPEndOffset < EndPage))
    {
        /* Current area is included in pages to be write protected */
        OptionsBytesStruct2.OptionType = OPTIONBYTE_WRP;
        OptionsBytesStruct2.WRPStartOffset = StartPage;
        OptionsBytesStruct2.WRPEndOffset = EndPage;
    }
    else if (OptionsBytesStruct.WRPStartOffset > OptionsBytesStruct.WRPEndOffset)
    {
        /* Current area is not used => it will be configured to protect the pages */
        OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;
        OptionsBytesStruct.WRPStartOffset = StartPage;
        OptionsBytesStruct.WRPEndOffset = EndPage;
    }
    else if (OptionsBytesStruct2.WRPStartOffset > OptionsBytesStruct2.WRPEndOffset)
    {
        /* Current area is not used => it will be configured to protect the pages */
        OptionsBytesStruct2.OptionType = OPTIONBYTE_WRP;
        OptionsBytesStruct2.WRPStartOffset = StartPage;
        OptionsBytesStruct2.WRPEndOffset = EndPage;
    }
    else
    {
        /* No more area available to protect the pages */
        /* => Error : not possible to activate the pages indicated */
        goto _exit;
    }
    /*write option bytes**************************/

    if (OptionsBytesStruct.OptionType == OPTIONBYTE_WRP)
    {
        if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
        {
            goto _exit;
            /* Error occurred while options bytes programming. **********************/
        }
    }

    if (OptionsBytesStruct2.OptionType == OPTIONBYTE_WRP)
    {
        if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct2) != HAL_OK)
        {
            goto _exit;
            /* Error occurred while options bytes programming. **********************/
        }
    }

    _exit:
    /* Lock the Options Bytes *************************************************/
    HAL_FLASH_OB_Lock();
    /* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
    HAL_FLASH_Lock();

}

void app_ob_flash_launch(void)
{

    if ((OptionsBytesStruct.OptionType == OPTIONBYTE_WRP) || (OptionsBytesStruct2.OptionType == OPTIONBYTE_WRP))
    {
        LOG_I("write protect launch");
        /* Unlock the Flash to enable the flash control register access *************/
        HAL_FLASH_Unlock();
        /* Clear OPTVERR bit set on virgin samples */
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
        /* Unlock the Options Bytes *************************************************/
        HAL_FLASH_OB_Unlock();
        HAL_FLASH_OB_Launch();
        /* Lock the Options Bytes *************************************************/
        HAL_FLASH_OB_Lock();
        /* Lock the Flash to disable the flash control register access (recommended
         to protect the FLASH memory against possible unwanted operation) *********/
        HAL_FLASH_Lock();
    }
}

/**
 * @brief  Gets the page of a given address
 * @param  Addr: Address of the FLASH Memory
 * @retval The page of a given address
 */
static uint32_t GetPage(uint32_t Addr)
{
    uint32_t page = 0;

    if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
    {
        /* Bank 1 */
        page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
    }
    else
    {
        /* Bank 2 */
        page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
    }

    return page;
}

/**
 * @brief  Gets the bank of a given address
 * @param  Addr: Address of the FLASH Memory
 * @retval The bank of a given address
 */
static uint32_t GetBank(uint32_t Addr)
{
    uint32_t bank = 0;

    if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0)
    {
        /* No Bank swap */
        if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
        {
            bank = FLASH_BANK_1;
        }
        else
        {
            bank = FLASH_BANK_2;
        }
    }
    else
    {
        /* Bank swap */
        if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
        {
            bank = FLASH_BANK_2;
        }
        else
        {
            bank = FLASH_BANK_1;
        }
    }

    return bank;
}

int flash_ob_test(void)
{
    app_ob_flash_write(0x08000000, 0x0801f800);
    app_ob_flash_write(0x08020000, 0x0803c000);
    app_ob_flash_launch();
    return 0;
}

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。