/** * \brief Set flash wait state. * * \param ul_address Flash bank start address. * \param ul_fws The number of wait states in cycle (no shift). * * \return 0 if successful; otherwise returns an error code. */ uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws) { Efc *p_efc; translate_address(&p_efc, ul_address, NULL, NULL); efc_set_wait_state(p_efc, ul_fws); return FLASH_RC_OK; }
/** * \brief Set flash wait state. * * \param ul_address Flash bank start address. * \param ul_fws The number of wait states in cycle (no shift). * * \return 0 if successful; otherwise returns an error code. */ uint32_t flash_set_wait_state_adaptively(uint32_t ul_address) { Efc *p_efc; uint32_t clock = SystemCoreClock; translate_address(&p_efc, ul_address, NULL, NULL); /* Set FWS for embedded Flash access according to operating frequency */ if (clock < CHIP_FREQ_FWS_0) { efc_set_wait_state(p_efc, 0); } else if (clock < CHIP_FREQ_FWS_1) { efc_set_wait_state(p_efc, 1); } else if (clock < CHIP_FREQ_FWS_2) { efc_set_wait_state(p_efc, 2); } else if (clock < CHIP_FREQ_FWS_3) { efc_set_wait_state(p_efc, 3); } else { efc_set_wait_state(p_efc, 4); } return FLASH_RC_OK; }
/** * \brief Set flash wait state. * * \param ul_address Flash bank start address. * \param ul_fws The number of wait states in cycle (no shift). * * \return 0 if successful; otherwise returns an error code. */ uint32_t flash_set_wait_state_adaptively(uint32_t ul_address) { Efc *p_efc; uint32_t clock = sysclk_get_cpu_hz(); translate_address(&p_efc, ul_address, NULL, NULL); /* Set FWS for embedded Flash access according to operating frequency */ if (clock < CHIP_FREQ_FWS_0) { efc_set_wait_state(p_efc, 0); } else if (clock < CHIP_FREQ_FWS_1) { efc_set_wait_state(p_efc, 1); } else if (clock < CHIP_FREQ_FWS_2) { efc_set_wait_state(p_efc, 2); #if (SAM3XA || SAM3U) } else if (clock < CHIP_FREQ_FWS_3) { efc_set_wait_state(p_efc, 3); } else { efc_set_wait_state(p_efc, 4); } #elif (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM) } else if (clock < CHIP_FREQ_FWS_3) {
/** * \brief Write a data buffer on flash. * * \note This function works in polling mode, and thus only returns when the * data has been effectively written. * \note For dual bank flash, this function doesn't support cross write from * bank 0 to bank 1. In this case, flash_write must be called twice (ie for * each bank). * * \param ul_address Write address. * \param p_buffer Data buffer. * \param ul_size Size of data buffer in bytes. * \param ul_erase_flag Flag to set if erase first. * * \return 0 if successful, otherwise returns an error code. */ uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag) { Efc *p_efc; uint32_t ul_fws_temp; uint16_t us_page; uint16_t us_offset; uint32_t writeSize; uint32_t ul_page_addr; uint16_t us_padding; uint32_t ul_error; uint32_t ul_idx; uint32_t *p_aligned_dest; uint8_t *puc_page_buffer = (uint8_t *) gs_ul_page_buffer; translate_address(&p_efc, ul_address, &us_page, &us_offset); /* According to the errata, set the wait state value to 6. */ ul_fws_temp = efc_get_wait_state(p_efc); efc_set_wait_state(p_efc, 6); /* Write all pages */ while (ul_size > 0) { /* Copy data in temporary buffer to avoid alignment problems. */ writeSize = Min((uint32_t) IFLASH_PAGE_SIZE - us_offset, ul_size); compute_address(p_efc, us_page, 0, &ul_page_addr); us_padding = IFLASH_PAGE_SIZE - us_offset - writeSize; /* Pre-buffer data */ memcpy(puc_page_buffer, (void *)ul_page_addr, us_offset); /* Buffer data */ memcpy(puc_page_buffer + us_offset, p_buffer, writeSize); /* Post-buffer data */ memcpy(puc_page_buffer + us_offset + writeSize, (void *)(ul_page_addr + us_offset + writeSize), us_padding); /* Write page. * Writing 8-bit and 16-bit data is not allowed and may lead to * unpredictable data corruption. */ p_aligned_dest = (uint32_t *) ul_page_addr; for (ul_idx = 0; ul_idx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ul_idx) { *p_aligned_dest++ = gs_ul_page_buffer[ul_idx]; } if (ul_erase_flag) { ul_error = efc_perform_command(p_efc, EFC_FCMD_EWP, us_page); } else { ul_error = efc_perform_command(p_efc, EFC_FCMD_WP, us_page); } if (ul_error) { return ul_error; } /* Progression */ p_buffer = (void *)((uint32_t) p_buffer + writeSize); ul_size -= writeSize; us_page++; us_offset = 0; } /* According to the errata, restore the wait state value. */ efc_set_wait_state(p_efc, ul_fws_temp); return FLASH_RC_OK; }