📄 flashc.c
字号:
void flashc_lock_region(unsigned int region, Bool lock)
{
flashc_lock_page_region(flashc_get_region_first_page_number(region), lock);
}
void flashc_lock_all_regions(Bool lock)
{
unsigned int error_status = 0;
unsigned int region = AVR32_FLASHC_REGIONS;
while (region)
{
flashc_lock_region(--region, lock);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
}
//! @}
/*! \name Access to General-Purpose Fuses
*/
//! @{
Bool flashc_read_gp_fuse_bit(unsigned int gp_fuse_bit)
{
return ((AVR32_FLASHC.fgpfr & AVR32_FLASHC_FGPFR_GPF00_MASK << (gp_fuse_bit & 0x1F)) != 0);
}
U32 flashc_read_gp_fuse_bitfield(unsigned int pos, unsigned int width)
{
return AVR32_FLASHC.fgpfr >> (AVR32_FLASHC_FGPFR_GPF00_OFFSET + (pos & 0x1F)) &
((1 << min(width, 32)) - 1);
}
U8 flashc_read_gp_fuse_byte(unsigned int gp_fuse_byte)
{
return AVR32_FLASHC.fgpfr >> (AVR32_FLASHC_FGPFR_GPF00_OFFSET + ((gp_fuse_byte & 0x03) << 3));
}
U32 flashc_read_all_gp_fuses(void)
{
return AVR32_FLASHC.fgpfr;
}
Bool flashc_erase_gp_fuse_bit(unsigned int gp_fuse_bit, Bool check)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EGPB, gp_fuse_bit & 0x1F);
return (check) ? flashc_read_gp_fuse_bit(gp_fuse_bit) : TRUE;
}
Bool flashc_erase_gp_fuse_bitfield(unsigned int pos, unsigned int width, Bool check)
{
unsigned int error_status = 0;
unsigned int gp_fuse_bit;
pos &= 0x1F;
width = min(width, 32);
for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++)
{
flashc_erase_gp_fuse_bit(gp_fuse_bit, FALSE);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
return (check) ? (flashc_read_gp_fuse_bitfield(pos, width) == (1 << width) - 1) : TRUE;
}
Bool flashc_erase_gp_fuse_byte(unsigned int gp_fuse_byte, Bool check)
{
unsigned int error_status;
unsigned int current_gp_fuse_byte;
U32 value = flashc_read_all_gp_fuses();
flashc_erase_all_gp_fuses(FALSE);
error_status = flashc_error_status;
for (current_gp_fuse_byte = 0; current_gp_fuse_byte < 4; current_gp_fuse_byte++, value >>= 8)
{
if (current_gp_fuse_byte != gp_fuse_byte)
{
flashc_write_gp_fuse_byte(current_gp_fuse_byte, value);
error_status |= flashc_error_status;
}
}
flashc_error_status = error_status;
return (check) ? (flashc_read_gp_fuse_byte(gp_fuse_byte) == 0xFF) : TRUE;
}
Bool flashc_erase_all_gp_fuses(Bool check)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EAGPF, -1);
return (check) ? (flashc_read_all_gp_fuses() == 0xFFFFFFFF) : TRUE;
}
void flashc_write_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value)
{
if (!value)
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WGPB, gp_fuse_bit & 0x1F);
}
void flashc_write_gp_fuse_bitfield(unsigned int pos, unsigned int width, U32 value)
{
unsigned int error_status = 0;
unsigned int gp_fuse_bit;
pos &= 0x1F;
width = min(width, 32);
for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1)
{
flashc_write_gp_fuse_bit(gp_fuse_bit, value & 0x01);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
}
void flashc_write_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_PGPFB, (gp_fuse_byte & 0x03) | value << 2);
}
void flashc_write_all_gp_fuses(U32 value)
{
unsigned int error_status = 0;
unsigned int gp_fuse_byte;
for (gp_fuse_byte = 0; gp_fuse_byte < 4; gp_fuse_byte++, value >>= 8)
{
flashc_write_gp_fuse_byte(gp_fuse_byte, value);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
}
void flashc_set_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value)
{
if (value)
flashc_erase_gp_fuse_bit(gp_fuse_bit, FALSE);
else
flashc_write_gp_fuse_bit(gp_fuse_bit, FALSE);
}
void flashc_set_gp_fuse_bitfield(unsigned int pos, unsigned int width, U32 value)
{
unsigned int error_status = 0;
unsigned int gp_fuse_bit;
pos &= 0x1F;
width = min(width, 32);
for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1)
{
flashc_set_gp_fuse_bit(gp_fuse_bit, value & 0x01);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
}
void flashc_set_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value)
{
unsigned int error_status;
switch (value)
{
case 0xFF:
flashc_erase_gp_fuse_byte(gp_fuse_byte, FALSE);
break;
case 0x00:
flashc_write_gp_fuse_byte(gp_fuse_byte, 0x00);
break;
default:
flashc_erase_gp_fuse_byte(gp_fuse_byte, FALSE);
error_status = flashc_error_status;
flashc_write_gp_fuse_byte(gp_fuse_byte, value);
flashc_error_status |= error_status;
}
}
void flashc_set_all_gp_fuses(U32 value)
{
unsigned int error_status;
switch (value)
{
case 0xFFFFFFFF:
flashc_erase_all_gp_fuses(FALSE);
break;
case 0x00000000:
flashc_write_all_gp_fuses(0x00000000);
break;
default:
flashc_erase_all_gp_fuses(FALSE);
error_status = flashc_error_status;
flashc_write_all_gp_fuses(value);
flashc_error_status |= error_status;
}
}
//! @}
/*! \name Access to Flash Pages
*/
//! @{
void flashc_clear_page_buffer(void)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_CPB, -1);
}
Bool flashc_is_page_erased(void)
{
return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_QPRR_MASK) != 0);
}
Bool flashc_quick_page_read(int page_number)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_QPR, page_number);
return flashc_is_page_erased();
}
Bool flashc_erase_page(int page_number, Bool check)
{
Bool page_erased = TRUE;
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EP, page_number);
if (check)
{
unsigned int error_status = flashc_error_status;
page_erased = flashc_quick_page_read(-1);
flashc_error_status |= error_status;
}
return page_erased;
}
Bool flashc_erase_all_pages(Bool check)
{
Bool all_pages_erased = TRUE;
unsigned int error_status = 0;
unsigned int page_number = flashc_get_page_count();
while (page_number)
{
all_pages_erased &= flashc_erase_page(--page_number, check);
error_status |= flashc_error_status;
}
flashc_error_status = error_status;
return all_pages_erased;
}
void flashc_write_page(int page_number)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WP, page_number);
}
Bool flashc_check_user_page_erase(void)
{
volatile U64 *user_page_ptr = (U64 *)AVR32_FLASHC_USER_PAGE;
while (user_page_ptr < (U64 *)(AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE))
{
if (*user_page_ptr++ != 0xFFFFFFFFFFFFFFFFULL)
return FALSE;
}
return TRUE;
}
Bool flashc_erase_user_page(Bool check)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EUP, -1);
return (check) ? flashc_check_user_page_erase() : TRUE;
}
void flashc_write_user_page(void)
{
flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WUP, -1);
}
volatile void *flashc_memset8(volatile void *dst, U8 src, size_t nbytes, Bool erase)
{
return flashc_memset16(dst, src | (U16)src << 8, nbytes, erase);
}
volatile void *flashc_memset16(volatile void *dst, U16 src, size_t nbytes, Bool erase)
{
return flashc_memset32(dst, src | (U32)src << 16, nbytes, erase);
}
volatile void *flashc_memset32(volatile void *dst, U32 src, size_t nbytes, Bool erase)
{
return flashc_memset64(dst, src | (U64)src << 32, nbytes, erase);
}
volatile void *flashc_memset64(volatile void *dst, U64 src, size_t nbytes, Bool erase)
{
// Use aggregated pointers to have several alignments available for a same address.
UnionCVPtr flash_array_end;
UnionVPtr dest;
Union64 source = {0};
StructCVPtr dest_end;
UnionCVPtr flash_page_source_end;
Bool incomplete_flash_page_end;
Union64 flash_dword;
UnionVPtr tmp;
unsigned int error_status = 0;
unsigned int i;
// Reformat arguments.
flash_array_end.u8ptr = AVR32_FLASH + flashc_get_flash_size();
dest.u8ptr = dst;
for (i = (Get_align((U32)dest.u8ptr, sizeof(U64)) - 1) & (sizeof(U64) - 1);
src; i = (i - 1) & (sizeof(U64) - 1))
{
source.u8[i] = src;
src >>= 8;
}
dest_end.u8ptr = dest.u8ptr + nbytes;
// If destination is outside flash, go to next flash page if any.
if (dest.u8ptr < AVR32_FLASH)
{
dest.u8ptr = AVR32_FLASH;
}
else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHC_USER_PAGE)
{
dest.u8ptr = AVR32_FLASHC_USER_PAGE;
}
// If end of destination is outside flash, move it to the end of the previous flash page if any.
if (dest_end.u8ptr > AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE)
{
dest_end.u8ptr = AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE;
}
else if (AVR32_FLASHC_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr)
{
dest_end.u8ptr = flash_array_end.u8ptr;
}
// Align each end of destination pointer with its natural boundary.
dest_end.u16ptr = (U16 *)Align_down((U32)dest_end.u8ptr, sizeof(U16));
dest_end.u32ptr = (U32 *)Align_down((U32)dest_end.u16ptr, sizeof(U32));
dest_end.u64ptr = (U64 *)Align_down((U32)dest_end.u32ptr, sizeof(U64));
// While end of destination is not reached...
while (dest.u8ptr < dest_end.u8ptr)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -