AllJoyn/Samples/BACnetAdapter/bacnet-stack-0.8.2/ports/xplained/ASF/xmega/drivers/nvm/nvm.c
void nvm_flash_erase_and_write_buffer(flash_addr_t address,
    const void *buf,
    uint16_t len,
    bool b_blank_check)
{
    uint16_t w_value;
    uint16_t page_pos;
    bool b_flag_erase;
#if (FLASH_SIZE>0x10000)
    uint32_t page_address;
    uint32_t opt_address = address;
#else
    uint16_t page_address;
    uint16_t opt_address = (uint16_t) address;
#endif

    // Compute the start of the page to be modified
    page_address = opt_address - (opt_address % FLASH_PAGE_SIZE);

    // For each page
    while (len) {
        b_flag_erase = false;

        nvm_wait_until_ready();
        for (page_pos = 0; page_pos < FLASH_PAGE_SIZE; page_pos += 2) {
            if (b_blank_check) {
                // Read flash to know if the erase command is mandatory
                w_value = nvm_flash_read_word(page_address);
                if (w_value != 0xFFFF) {
                    b_flag_erase = true;        // The page is not empty
                }
            } else {
                w_value = 0xFFFF;
            }

            // Update flash buffer
            if (len) {
                if (opt_address == page_address) {
                    // The MSB of flash word must be changed
                    // because the address is even
                    len--;
                    opt_address++;
                    LSB(w_value) = *(uint8_t *) buf;
                    buf = (uint8_t *) buf + 1;
                }
            }
            if (len) {
                if (opt_address == (page_address + 1)) {
                    // The LSB of flash word must be changed
                    // because the user buffer is not empty
                    len--;
                    opt_address++;
                    MSB(w_value) = *(uint8_t *) buf;
                    buf = (uint8_t *) buf + 1;
                }
            }
            // Load flash buffer
            nvm_flash_load_word_to_buffer(page_address, w_value);
            page_address += 2;
        }

        // Write flash buffer
        if (b_flag_erase) {
            nvm_flash_atomic_write_app_page(page_address - FLASH_PAGE_SIZE);
        } else {
            nvm_flash_split_write_app_page(page_address - FLASH_PAGE_SIZE);
        }
    }
}
/**
 * \brief Erase and write specific parts of application flash section
 *
 * \param address        the address to where to write
 * \param buf            pointer to the data
 * \param len            the number of bytes to write
 * \param b_blank_check  if True then the page flash is checked before write
 *                       to run or not the erase page command.
 *
 * Set b_blank_check to false if all application flash is erased before.
 */


Set b_blank_check to false if all application flash is erased before.
Set b_blank_check to false if all application flash is erased before .
void nvm_flash_erase_and_write_buffer(flash_addr_t address,
    const void *buf,
    uint16_t len,
    bool b_blank_check)
{
    uint16_t w_value;
    uint16_t page_pos;
    bool b_flag_erase;
#if (FLASH_SIZE>0x10000)
    uint32_t page_address;
    uint32_t opt_address = address;
#else
    uint16_t page_address;
    uint16_t opt_address = (uint16_t) address;
#endif
    page_address = opt_address - (opt_address % FLASH_PAGE_SIZE);
    while (len) {
        b_flag_erase = false;
        nvm_wait_until_ready();
        for (page_pos = 0; page_pos < FLASH_PAGE_SIZE; page_pos += 2) {
            if (b_blank_check) {
                w_value = nvm_flash_read_word(page_address);
                if (w_value != 0xFFFF) {
                    b_flag_erase = true;        
                }
            } else {
                w_value = 0xFFFF;
            }
            if (len) {
                if (opt_address == page_address) {
                    len--;
                    opt_address++;
                    LSB(w_value) = *(uint8_t *) buf;
                    buf = (uint8_t *) buf + 1;
                }
            }
            if (len) {
                if (opt_address == (page_address + 1)) {
                    len--;
                    opt_address++;
                    MSB(w_value) = *(uint8_t *) buf;
                    buf = (uint8_t *) buf + 1;
                }
            }
            nvm_flash_load_word_to_buffer(page_address, w_value);
            page_address += 2;
        }
        if (b_flag_erase) {
            nvm_flash_atomic_write_app_page(page_address - FLASH_PAGE_SIZE);
        } else {
            nvm_flash_split_write_app_page(page_address - FLASH_PAGE_SIZE);
        }
    }
}
void nvm_flash_erase_and_write_buffer ( flash_addr_t address , const void * buf , uint16_t len , bool b_blank_check ) { uint16_t w_value ; uint16_t page_pos ; bool b_flag_erase ; #if ( FLASH_SIZE > 0x10000 ) uint32_t page_address ; uint32_t opt_address = address ; #else uint16_t page_address ; uint16_t opt_address = ( uint16_t ) address ; #endif page_address = opt_address - ( opt_address % FLASH_PAGE_SIZE ) ; while ( len ) { b_flag_erase = false ; nvm_wait_until_ready ( ) ; for ( page_pos = 0 ; page_pos < FLASH_PAGE_SIZE ; page_pos += 2 ) { if ( b_blank_check ) { w_value = nvm_flash_read_word ( page_address ) ; if ( w_value != 0xFFFF ) { b_flag_erase = true ; } } else { w_value = 0xFFFF ; } if ( len ) { if ( opt_address == page_address ) { len -- ; opt_address ++ ; LSB ( w_value ) = * ( uint8_t * ) buf ; buf = ( uint8_t * ) buf + 1 ; } } if ( len ) { if ( opt_address == ( page_address + 1 ) ) { len -- ; opt_address ++ ; MSB ( w_value ) = * ( uint8_t * ) buf ; buf = ( uint8_t * ) buf + 1 ; } } nvm_flash_load_word_to_buffer ( page_address , w_value ) ; page_address += 2 ; } if ( b_flag_erase ) { nvm_flash_atomic_write_app_page ( page_address - FLASH_PAGE_SIZE ) ; } else { nvm_flash_split_write_app_page ( page_address - FLASH_PAGE_SIZE ) ; } } }
\brief Erase and write specific parts of application flash section
 \param address        the address to where to write
 \param buf            pointer to the data
 \param len            the number of bytes to write
 \param b_blank_check  if True then the page flash is checked before write
                       to run or not the erase page command.
\ brief Erase and write specific parts of application flash section \ param address the address to where to write \ param buf pointer to the data \ param len the number of bytes to write \ param b_blank_check if True then the page flash is checked before write to run or not the erase page command .
// Compute the start of the page to be modified // For each page // Read flash to know if the erase command is mandatory // The page is not empty // Update flash buffer // The MSB of flash word must be changed // because the address is even // The LSB of flash word must be changed // because the user buffer is not empty // Load flash buffer // Write flash buffer