/** ************************************************************************** * @file at32f435_437_flash.c * @version v2.0.9 * @date 2022-06-28 * @brief contains all the functions for the flash firmware library ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include "at32f435_437_conf.h" /** @addtogroup AT32F435_437_periph_driver * @{ */ /** @defgroup FLASH * @brief FLASH driver modules * @{ */ #ifdef FLASH_MODULE_ENABLED /** @defgroup FLASH_private_functions * @{ */ /** * @brief check whether the specified flash flag is set or not. * @param flash_flag: specifies the flash flag to check. * this parameter can be one of flash flag status: * - FLASH_OBF_FLAG * - FLASH_ODF_FLAG * - FLASH_PRGMERR_FLAG * - FLASH_EPPERR_FLAG * - FLASH_BANK1_OBF_FLAG * - FLASH_BANK1_ODF_FLAG * - FLASH_BANK1_PRGMERR_FLAG * - FLASH_BANK1_EPPERR_FLAG * - FLASH_BANK2_OBF_FLAG * - FLASH_BANK2_ODF_FLAG * - FLASH_BANK2_PRGMERR_FLAG * - FLASH_BANK2_EPPERR_FLAG * - FLASH_USDERR_FLAG * @retval the new state of flash_flag (SET or RESET). */ flag_status flash_flag_get(uint32_t flash_flag) { flag_status status = RESET; uint32_t flag_position; flag_position = flash_flag & 0x70000000; flash_flag &= 0x8FFFFFFF; switch(flag_position) { case 0x00000000: if(FLASH->sts & flash_flag) status = SET; break; case 0x10000000: if(FLASH->sts2 & flash_flag) status = SET; break; case 0x40000000: if(FLASH->usd & flash_flag) status = SET; break; default: break; } /* return the new state of flash_flag (SET or RESET) */ return status; } /** * @brief clear the flash flag. * @param flash_flag: specifies the flash flags to clear. * this parameter can be any combination of the following values: * - FLASH_ODF_FLAG * - FLASH_PRGMERR_FLAG * - FLASH_EPPERR_FLAG * - FLASH_BANK1_ODF_FLAG * - FLASH_BANK1_PRGMERR_FLAG * - FLASH_BANK1_EPPERR_FLAG * - FLASH_BANK2_ODF_FLAG * - FLASH_BANK2_PRGMERR_FLAG * - FLASH_BANK2_EPPERR_FLAG * @retval none */ void flash_flag_clear(uint32_t flash_flag) { uint32_t flag_position; flag_position = flash_flag & 0x70000000; flash_flag &= 0x8FFFFFFF; switch(flag_position) { case 0x00000000: FLASH->sts = flash_flag; break; case 0x10000000: FLASH->sts2 = flash_flag; break; default: break; } } /** * @brief return the flash operation status. * @param none * @retval status: the returned value can be: FLASH_OPERATE_BUSY, * FLASH_PROGRAM_ERROR, FLASH_EPP_ERROR or FLASH_OPERATE_DONE. */ flash_status_type flash_operation_status_get(void) { flash_status_type flash_status = FLASH_OPERATE_DONE; if(FLASH->sts_bit.obf != RESET) { flash_status = FLASH_OPERATE_BUSY; } else if(FLASH->sts_bit.prgmerr != RESET) { flash_status = FLASH_PROGRAM_ERROR; } else if(FLASH->sts_bit.epperr != RESET) { flash_status = FLASH_EPP_ERROR; } else { flash_status = FLASH_OPERATE_DONE; } /* return the flash status */ return flash_status; } /** * @brief return the flash bank1 operation status. * @param none * @retval status: the returned value can be: FLASH_OPERATE_BUSY, * FLASH_PROGRAM_ERROR, FLASH_EPP_ERROR or FLASH_OPERATE_DONE. */ flash_status_type flash_bank1_operation_status_get(void) { flash_status_type flash_status = FLASH_OPERATE_DONE; if(FLASH->sts_bit.obf != RESET) { flash_status = FLASH_OPERATE_BUSY; } else if(FLASH->sts_bit.prgmerr != RESET) { flash_status = FLASH_PROGRAM_ERROR; } else if(FLASH->sts_bit.epperr != RESET) { flash_status = FLASH_EPP_ERROR; } else { flash_status = FLASH_OPERATE_DONE; } /* return the flash status */ return flash_status; } /** * @brief return the flash bank2 operation status. * @param none * @retval status: the returned value can be: FLASH_OPERATE_BUSY, * FLASH_PROGRAM_ERROR, FLASH_EPP_ERROR or FLASH_OPERATE_DONE. */ flash_status_type flash_bank2_operation_status_get(void) { flash_status_type flash_status = FLASH_OPERATE_DONE; if(FLASH->sts2_bit.obf != RESET) { flash_status = FLASH_OPERATE_BUSY; } else if(FLASH->sts2_bit.prgmerr != RESET) { flash_status = FLASH_PROGRAM_ERROR; } else if(FLASH->sts2_bit.epperr != RESET) { flash_status = FLASH_EPP_ERROR; } else { flash_status = FLASH_OPERATE_DONE; } /* return the flash status */ return flash_status; } /** * @brief wait for flash operation complete or timeout. * @param time_out: flash operation timeout * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_operation_wait_for(uint32_t time_out) { flash_status_type status = FLASH_OPERATE_DONE; /* check for the flash status */ status = flash_operation_status_get(); while((status == FLASH_OPERATE_BUSY) && (time_out != 0x00)) { status = flash_operation_status_get(); time_out--; } if(time_out == 0x00) { status = FLASH_OPERATE_TIMEOUT; } /* return the status */ return status; } /** * @brief wait for flash bank1 operation complete or timeout. * @param time_out: flash operation timeout * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_bank1_operation_wait_for(uint32_t time_out) { flash_status_type status = FLASH_OPERATE_DONE; /* check for the flash status */ status = flash_bank1_operation_status_get(); while((status == FLASH_OPERATE_BUSY) && (time_out != 0x00)) { status = flash_bank1_operation_status_get(); time_out--; } if(time_out == 0x00) { status = FLASH_OPERATE_TIMEOUT; } /* return the operation status */ return status; } /** * @brief wait for flash bank2 operation complete or timeout. * @param time_out: flash operation timeout * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_bank2_operation_wait_for(uint32_t time_out) { flash_status_type status = FLASH_OPERATE_DONE; /* check for the flash status */ status = flash_bank2_operation_status_get(); while((status == FLASH_OPERATE_BUSY) && (time_out != 0x00)) { status = flash_bank2_operation_status_get(); time_out--; } if(time_out == 0x00) { status = FLASH_OPERATE_TIMEOUT; } /* return the operation status */ return status; } /** * @brief unlock the flash controller. * @param none * @retval none */ void flash_unlock(void) { FLASH->unlock = FLASH_UNLOCK_KEY1; FLASH->unlock = FLASH_UNLOCK_KEY2; FLASH->unlock2 = FLASH_UNLOCK_KEY1; FLASH->unlock2 = FLASH_UNLOCK_KEY2; } /** * @brief unlock the flash bank1 controller. * @param none * @retval none */ void flash_bank1_unlock(void) { FLASH->unlock = FLASH_UNLOCK_KEY1; FLASH->unlock = FLASH_UNLOCK_KEY2; } /** * @brief unlock the flash bank2 controller. * @param none * @retval none */ void flash_bank2_unlock(void) { FLASH->unlock2 = FLASH_UNLOCK_KEY1; FLASH->unlock2 = FLASH_UNLOCK_KEY2; } /** * @brief lock the flash controller. * @param none * @retval none */ void flash_lock(void) { FLASH->ctrl_bit.oplk = TRUE; FLASH->ctrl2_bit.oplk = TRUE; } /** * @brief lock the flash bank1 controller. * @param none * @retval none */ void flash_bank1_lock(void) { FLASH->ctrl_bit.oplk = TRUE; } /** * @brief lock the flash bank2 controller. * @param none * @retval none */ void flash_bank2_lock(void) { FLASH->ctrl2_bit.oplk = TRUE; } /** * @brief erase a specified flash sector. * @param sector_address: the sector address to be erased. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_sector_erase(uint32_t sector_address) { flash_status_type status = FLASH_OPERATE_DONE; if((sector_address >= FLASH_BANK1_START_ADDR) && (sector_address <= FLASH_BANK1_END_ADDR)) { FLASH->ctrl_bit.secers = TRUE; FLASH->addr = sector_address; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(ERASE_TIMEOUT); /* disable the secers bit */ FLASH->ctrl_bit.secers = FALSE; } else if((sector_address >= FLASH_BANK2_START_ADDR) && (sector_address <= FLASH_BANK2_END_ADDR)) { FLASH->ctrl2_bit.secers = TRUE; FLASH->addr2 = sector_address; FLASH->ctrl2_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(ERASE_TIMEOUT); /* disable the secers bit */ FLASH->ctrl2_bit.secers = FALSE; } /* return the erase status */ return status; } /** * @brief erase a specified flash block. * @param block_address: the block address to be erased. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_block_erase(uint32_t block_address) { flash_status_type status = FLASH_OPERATE_DONE; if((block_address >= FLASH_BANK1_START_ADDR) && (block_address <= FLASH_BANK1_END_ADDR)) { FLASH->ctrl_bit.blkers = TRUE; FLASH->addr = block_address; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(ERASE_TIMEOUT); /* disable the blkers bit */ FLASH->ctrl_bit.blkers = FALSE; } else if((block_address >= FLASH_BANK2_START_ADDR) && (block_address <= FLASH_BANK2_END_ADDR)) { FLASH->ctrl2_bit.blkers = TRUE; FLASH->addr2 = block_address; FLASH->ctrl2_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(ERASE_TIMEOUT); /* disable the blkers bit */ FLASH->ctrl2_bit.blkers = FALSE; } /* return the erase status */ return status; } /** * @brief erase flash all internal sectors. * @param none * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_internal_all_erase(void) { flash_status_type status = FLASH_OPERATE_DONE; FLASH->ctrl_bit.bankers = TRUE; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(ERASE_TIMEOUT); /* disable the bankers bit */ FLASH->ctrl_bit.bankers = FALSE; if(status == FLASH_OPERATE_DONE) { /* if the previous operation is completed, continue to erase bank2 */ FLASH->ctrl2_bit.bankers = TRUE; FLASH->ctrl2_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(ERASE_TIMEOUT); /* disable the bankers bit */ FLASH->ctrl2_bit.bankers = FALSE; } /* return the erase status */ return status; } /** * @brief erase flash bank1 sectors. * @param none * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_bank1_erase(void) { flash_status_type status = FLASH_OPERATE_DONE; FLASH->ctrl_bit.bankers = TRUE; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(ERASE_TIMEOUT); /* disable the bankers bit */ FLASH->ctrl_bit.bankers = FALSE; /* return the erase status */ return status; } /** * @brief erase flash bank2 sectors. * @param none * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_bank2_erase(void) { flash_status_type status = FLASH_OPERATE_DONE; FLASH->ctrl2_bit.bankers = TRUE; FLASH->ctrl2_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(ERASE_TIMEOUT); /* disable the bankers bit */ FLASH->ctrl2_bit.bankers = FALSE; /* return the erase status */ return status; } /** * @brief erase the flash user system data. * @note this functions erase all user system data except the fap byte. * the eopb0 byte value change to 0xFF, sram size maybe change too. * @param none * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_user_system_data_erase(void) { flash_status_type status = FLASH_OPERATE_DONE; uint16_t fap_val = FAP_RELIEVE_KEY; /* get the flash access protection status */ if(flash_fap_status_get() != RESET) { fap_val = 0x0000; } /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); /* erase the user system data */ FLASH->ctrl_bit.usders = TRUE; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_operation_wait_for(ERASE_TIMEOUT); /* disable the usders bit */ FLASH->ctrl_bit.usders = FALSE; if((status == FLASH_OPERATE_DONE) && (fap_val == FAP_RELIEVE_KEY)) { /* enable the user system data programming operation */ FLASH->ctrl_bit.usdprgm = TRUE; /* restore the last flash access protection value */ USD->fap = (uint16_t)fap_val; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); /*disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; } /* return the status */ return status; } /** * @brief config the extend sram byte eopb0 in user system data. * @note the 256kb and below capacity mcu only support FLASH_EOPB0_SRAM_384K, * FLASH_EOPB0_SRAM_448K or FLASH_EOPB0_SRAM_512K. * @param data: the eopb0 value. * this parameter can be one of the following values: * - FLASH_EOPB0_SRAM_512K * - FLASH_EOPB0_SRAM_448K * - FLASH_EOPB0_SRAM_384K * - FLASH_EOPB0_SRAM_320K * - FLASH_EOPB0_SRAM_256K * - FLASH_EOPB0_SRAM_192K * - FLASH_EOPB0_SRAM_128K * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_eopb0_config(flash_usd_eopb0_type data) { flash_status_type status = FLASH_OPERATE_DONE; /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); /* enable the user system data programming operation */ FLASH->ctrl_bit.usdprgm = TRUE; /* restore the default eopb0 value */ USD->eopb0 = (uint16_t)data; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); /*disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; /* return the status */ return status; } /** * @brief program a word at a specified address. * @param address: specifies the address to be programmed, word alignment is recommended. * @param data: specifies the data to be programmed. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_word_program(uint32_t address, uint32_t data) { flash_status_type status = FLASH_OPERATE_DONE; if((address >= FLASH_BANK1_START_ADDR) && (address <= FLASH_BANK1_END_ADDR)) { FLASH->ctrl_bit.fprgm = TRUE; *(__IO uint32_t*)address = data; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl_bit.fprgm = FALSE; } else if((address >= FLASH_BANK2_START_ADDR) && (address <= FLASH_BANK2_END_ADDR)) { FLASH->ctrl2_bit.fprgm = TRUE; *(__IO uint32_t*)address = data; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl2_bit.fprgm = FALSE; } /* return the program status */ return status; } /** * @brief program a halfword at a specified address. * @param address: specifies the address to be programmed, halfword alignment is recommended. * @param data: specifies the data to be programmed. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_halfword_program(uint32_t address, uint16_t data) { flash_status_type status = FLASH_OPERATE_DONE; if((address >= FLASH_BANK1_START_ADDR) && (address <= FLASH_BANK1_END_ADDR)) { FLASH->ctrl_bit.fprgm = TRUE; *(__IO uint16_t*)address = data; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl_bit.fprgm = FALSE; } else if((address >= FLASH_BANK2_START_ADDR) && (address <= FLASH_BANK2_END_ADDR)) { FLASH->ctrl2_bit.fprgm = TRUE; *(__IO uint16_t*)address = data; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl2_bit.fprgm = FALSE; } /* return the program status */ return status; } /** * @brief program a byte at a specified address. * @note this function cannot be used to program spim. * @param address: specifies the address to be programmed. * @param data: specifies the data to be programmed. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_byte_program(uint32_t address, uint8_t data) { flash_status_type status = FLASH_OPERATE_DONE; if((address >= FLASH_BANK1_START_ADDR) && (address <= FLASH_BANK1_END_ADDR)) { FLASH->ctrl_bit.fprgm = TRUE; *(__IO uint8_t*)address = data; /* wait for operation to be completed */ status = flash_bank1_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl_bit.fprgm = FALSE; } else if((address >= FLASH_BANK2_START_ADDR) && (address <= FLASH_BANK2_END_ADDR)) { FLASH->ctrl2_bit.fprgm = TRUE; *(__IO uint8_t*)address = data; /* wait for operation to be completed */ status = flash_bank2_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the fprgm bit */ FLASH->ctrl2_bit.fprgm = FALSE; } /* return the program status */ return status; } /** * @brief program a halfword at a specified user system data address. * @param address: specifies the address to be programmed. * @param data: specifies the data to be programmed. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_user_system_data_program(uint32_t address, uint8_t data) { flash_status_type status = FLASH_OPERATE_DONE; if(address == USD_BASE) { if(data != 0xA5) return FLASH_OPERATE_DONE; } /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); /* enable the user system data programming operation */ FLASH->ctrl_bit.usdprgm = TRUE; *(__IO uint16_t*)address = data; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; /* return the user system data program status */ return status; } /** * @brief config erase/program protection for the desired sectors. * @param sector_bits: * the pointer of the address of the sectors to be erase/program protected. * general bit 0~31 every bit is used to protect the 4KB bytes, bit 62~32 * every bit is used to protect the 128KB bytes * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_epp_set(uint32_t *sector_bits) { uint16_t epp_data[4] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF}; flash_status_type status = FLASH_OPERATE_DONE; sector_bits[0] = (uint32_t)(~sector_bits[0]); epp_data[0] = (uint16_t)((sector_bits[0] >> 0) & 0xFF); epp_data[1] = (uint16_t)((sector_bits[0] >> 8) & 0xFF); epp_data[2] = (uint16_t)((sector_bits[0] >> 16) & 0xFF); epp_data[3] = (uint16_t)((sector_bits[0] >> 24) & 0xFF); /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); FLASH->ctrl_bit.usdprgm = TRUE; USD->epp0 = epp_data[0]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); if(status == FLASH_OPERATE_DONE) { USD->epp1 = epp_data[1]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } if(status == FLASH_OPERATE_DONE) { USD->epp2 = epp_data[2]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } if(status == FLASH_OPERATE_DONE) { USD->epp3 = epp_data[3]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } sector_bits[1] = (uint32_t)(~sector_bits[1]); epp_data[0] = (uint16_t)((sector_bits[1] >> 0) & 0xFF); epp_data[1] = (uint16_t)((sector_bits[1] >> 8) & 0xFF); epp_data[2] = (uint16_t)((sector_bits[1] >> 16) & 0xFF); epp_data[3] = (uint16_t)((sector_bits[1] >> 24) & 0xFF); if(status == FLASH_OPERATE_DONE) { USD->epp4 = epp_data[0]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } if(status == FLASH_OPERATE_DONE) { USD->epp5 = epp_data[1]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } if(status == FLASH_OPERATE_DONE) { USD->epp6 = epp_data[2]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } if(status == FLASH_OPERATE_DONE) { USD->epp7 = epp_data[3]; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } /* disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; /* return the erase/program protection operation status */ return status; } /** * @brief return the flash erase/program protection status. * @param sector_bits: pointer to get the epps register. * @retval none */ void flash_epp_status_get(uint32_t *sector_bits) { /* return the flash erase/program protection register value */ sector_bits[0] = (uint32_t)(FLASH->epps0); sector_bits[1] = (uint32_t)(FLASH->epps1); } /** * @brief enable or disable the flash access protection. * @note if the user has already programmed the other user system data before calling * this function, must re-program them since this function erase all user system data. * @param new_state: new state of the flash access protection. * this parameter can be: TRUE or FALSE. * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_fap_enable(confirm_state new_state) { flash_status_type status = FLASH_OPERATE_DONE; /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); FLASH->ctrl_bit.usders = TRUE; FLASH->ctrl_bit.erstr = TRUE; /* wait for operation to be completed */ status = flash_operation_wait_for(ERASE_TIMEOUT); /* disable the usders bit */ FLASH->ctrl_bit.usders = FALSE; if(status == FLASH_OPERATE_DONE) { /* enable the user system data programming operation */ FLASH->ctrl_bit.usdprgm = TRUE; /* restore the default eopb0 value */ USD->eopb0 = (uint16_t)0x0002; /* Wait for operation to be completed */ status = flash_operation_wait_for(ERASE_TIMEOUT); if(new_state == FALSE) { USD->fap = FAP_RELIEVE_KEY; /* Wait for operation to be completed */ status = flash_operation_wait_for(ERASE_TIMEOUT); } /* disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; } /* return the flash access protection operation status */ return status; } /** * @brief check the flash access protection status. * @param none * @retval flash access protection status(SET or RESET) */ flag_status flash_fap_status_get(void) { return (flag_status)FLASH->usd_bit.fap; } /** * @brief program the flash system setting byte in usd: wdt_ato_en / depslp_rst / stdby_rst / btopt. * @param usd_ssb: the system setting byte * @note this parameter usd_ssb must contain a combination of all the following 6 types of data * type 1: wdt_ato_en, select the wdt auto start * this data can be one of the following values: * - USD_WDT_ATO_DISABLE: disable wdt auto start * - USD_WDT_ATO_ENABLE: enable wdt auto start * type 2: depslp_rst, reset event when entering deepsleep mode. * this data can be one of the following values: * - USD_DEPSLP_NO_RST: no reset generated when entering in deepsleep * - USD_DEPSLP_RST: reset generated when entering in deepsleep * type 3: stdby_rst, reset event when entering standby mode. * this data can be one of the following values: * - USD_STDBY_NO_RST: no reset generated when entering in standby * - USD_STDBY_RST: reset generated when entering in standby * type 4: btopt, at startup,if boot pins are set in boot from user flash position,selected the device boot from bank1/bank2. * this data can be one of the following values: * - FLASH_BOOT_FROM_BANK1:boot from bank1 * - FLASH_BOOT_FROM_BANK2:boot from bank 2 or bank 1 * type 5: wdt_depslp, wdt stop/continue count when entering in deepsleep. * this data can be one of the following values: * - USD_WDT_DEPSLP_CONTINUE: wdt continue count * - USD_WDT_DEPSLP_STOP: wdt stop count * type 6: wdt_stdby, wdt stop/continue count when entering in standby. * this data can be one of the following values: * - USD_WDT_STDBY_CONTINUE: wdt continue count * - USD_WDT_STDBY_STOP: wdt stop count * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_ssb_set(uint8_t usd_ssb) { flash_status_type status = FLASH_OPERATE_DONE; /* unlock the user system data */ FLASH->usd_unlock = FLASH_UNLOCK_KEY1; FLASH->usd_unlock = FLASH_UNLOCK_KEY2; while(FLASH->ctrl_bit.usdulks==RESET); /* enable the user system data programming operation */ FLASH->ctrl_bit.usdprgm = TRUE; USD->ssb = usd_ssb; /* wait for operation to be completed */ status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); /* disable the usdprgm bit */ FLASH->ctrl_bit.usdprgm = FALSE; /* return the user system data program status */ return status; } /** * @brief return the flash system setting byte status. * @param none * @retval values from flash_usd register: wdt_ato_en(bit0), depslp_rst(bit1), * stdby_rst(bit2) and btopt(bit3). */ uint8_t flash_ssb_status_get(void) { /* return the system setting byte status */ return (uint8_t)(FLASH->usd >> 2); } /** * @brief enable or disable the specified flash interrupts. * @param flash_int: specifies the flash interrupt sources to be enabled or disabled. * this parameter can be any combination of the following values: * - FLASH_ERR_INT * - FLASH_ODF_INT * - FLASH_BANK1_ERR_INT * - FLASH_BANK1_ODF_INT * - FLASH_BANK2_ERR_INT * - FLASH_BANK2_ODF_INT * @param new_state: new state of the specified flash interrupts. * this parameter can be: TRUE or FALSE. * @retval none */ void flash_interrupt_enable(uint32_t flash_int, confirm_state new_state) { if(flash_int & FLASH_BANK1_ERR_INT) FLASH->ctrl_bit.errie = new_state; if(flash_int & FLASH_BANK1_ODF_INT) FLASH->ctrl_bit.odfie = new_state; if(flash_int & FLASH_BANK2_ERR_INT) FLASH->ctrl2_bit.errie = new_state; if(flash_int & FLASH_BANK2_ODF_INT) FLASH->ctrl2_bit.odfie = new_state; } /** * @brief enable security library function. * @param pwd: slib password * start_sector: security library start sector * inst_start_sector: security library i-bus area start sector * end_sector: security library end sector * @retval status: the returned value can be: FLASH_PROGRAM_ERROR, * FLASH_EPP_ERROR, FLASH_OPERATE_DONE or FLASH_OPERATE_TIMEOUT. */ flash_status_type flash_slib_enable(uint32_t pwd, uint16_t start_sector, uint16_t inst_start_sector, uint16_t end_sector) { uint32_t slib_range; flash_status_type status = FLASH_OPERATE_DONE; /*check range param limits*/ if((start_sector>=inst_start_sector) || ((inst_start_sector > end_sector) && \ (inst_start_sector != 0xFFFF)) || (start_sector > end_sector)) return FLASH_PROGRAM_ERROR; /* unlock slib cfg register */ FLASH->slib_unlock = SLIB_UNLOCK_KEY; while(FLASH->slib_misc_sts_bit.slib_ulkf==RESET); /* configure slib, set pwd and range */ FLASH->slib_set_pwd = pwd; status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); if(status == FLASH_OPERATE_DONE) { slib_range = ((uint32_t)(end_sector << 16) & FLASH_SLIB_END_SECTOR) | (start_sector & FLASH_SLIB_START_SECTOR); FLASH->slib_set_range0 = slib_range; status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); if(status == FLASH_OPERATE_DONE) { slib_range = (inst_start_sector & FLASH_SLIB_INST_START_SECTOR) | 0x80000000; FLASH->slib_set_range1 = slib_range; status = flash_operation_wait_for(PROGRAMMING_TIMEOUT); } } return status; } /** * @brief disable slib when slib enabled. * @param pwd: slib password * @retval success or error */ error_status flash_slib_disable(uint32_t pwd) { flash_status_type status = FLASH_OPERATE_DONE; /* write password to disable slib */ FLASH->slib_pwd_clr = pwd; status = flash_operation_wait_for(ERASE_TIMEOUT); if(status == FLASH_OPERATE_DONE) { if(FLASH->slib_misc_sts_bit.slib_pwd_ok) return SUCCESS; else return ERROR; } return ERROR; } /** * @brief get remaining count of slib(range: 256~0). * @param none * @retval uint32_t */ uint32_t flash_slib_remaining_count_get(void) { return (uint32_t)FLASH->slib_misc_sts_bit.slib_rcnt; } /** * @brief get the slib state. * @param none * @retval SET or RESET */ flag_status flash_slib_state_get(void) { if(FLASH->slib_sts0_bit.slib_enf) return SET; else return RESET; } /** * @brief get the start sector of slib. * @param none * @retval uint16_t */ uint16_t flash_slib_start_sector_get(void) { return (uint16_t)FLASH->slib_sts1_bit.slib_ss; } /** * @brief get the instruction start sector of slib. * @param none * @retval uint16_t */ uint16_t flash_slib_inststart_sector_get(void) { return (uint16_t)FLASH->slib_sts2_bit.slib_inst_ss; } /** * @brief get the end sector of slib. * @param none * @retval uint16_t */ uint16_t flash_slib_end_sector_get(void) { return (uint16_t)FLASH->slib_sts1_bit.slib_es; } /** * @brief flash crc calibration in main block. * @param start_sector: crc calibration start sector number * sector_cnt: crc calibration sector count * @retval uint32: crc calibration result */ uint32_t flash_crc_calibrate(uint32_t start_sector, uint32_t sector_cnt) { FLASH->crc_ctrl_bit.crc_ss = start_sector; FLASH->crc_ctrl_bit.crc_sn = sector_cnt; FLASH->crc_ctrl_bit.crc_strt = TRUE; flash_operation_wait_for(OPERATION_TIMEOUT); return FLASH->crc_chkr; } /** * @brief flash non-zero wait area boost enable. * @param new_state: new state of the flash non-zero wait area boost operation. * this parameter can be: TRUE or FALSE. * @retval none */ void flash_nzw_boost_enable(confirm_state new_state) { FLASH->psr_bit.nzw_bst = new_state; } /** * @brief flash continue read enable. * @param new_state: new state of the flash continue read enable operation. * this parameter can be: TRUE or FALSE. * @retval none */ void flash_continue_read_enable(confirm_state new_state) { FLASH->contr_bit.fcontr_en = new_state; } /** * @} */ #endif /** * @} */ /** * @} */