@@ -88,31 +88,48 @@ static bool arm_nvm_region_lock_check(arm_t *arm) {
8888 return false;
8989}
9090
91+ static bool arm_nvm_aux_region_check (arm_t * arm ) {
92+ return (arm -> mem .nvmctrl .ADDR .bit .ADDR << 1 & - FLASH_USER_PAGE_SIZE ) == NVMCTRL_USER - NVMCTRL_USER_PAGE_ADDRESS ;
93+ }
94+
9195static void arm_nvm_clear_page_buffer (arm_mem_t * mem ) {
9296 memset (mem -> pb , ~0 , FLASH_PAGE_SIZE );
9397}
9498
95- static void arm_nvm_erase_row (arm_t * arm , bool aux ) {
96- assert (!aux && "Not implemented" );
99+ static void arm_nvm_erase_row (arm_t * arm ) {
97100 if (likely (arm_nvm_region_lock_check (arm ))) {
98101 memset (& arm -> mem .nvm [(arm -> mem .nvmctrl .ADDR .bit .ADDR << 1 &
99102 (FLASH_SIZE - 1 ) & - FLASH_ROW_SIZE ) >> 2 ],
100103 ~0 , FLASH_ROW_SIZE );
101104 }
102105}
103106
104- static void arm_nvm_write_page (arm_t * arm , bool aux ) {
105- uint32_t idx = (arm -> mem .nvmctrl .ADDR .bit .ADDR << 1 &
106- (FLASH_SIZE - 1 ) & - FLASH_PAGE_SIZE ) >> 2 ;
107- assert (!aux && "Not implemented" );
107+ static void arm_nvm_erase_aux_row (arm_t * arm ) {
108+ if (likely (arm_nvm_aux_region_check (arm ))) {
109+ memset (arm -> mem .aux , ~0 , FLASH_USER_PAGE_SIZE );
110+ }
111+ }
112+
113+ static void arm_nvm_write_page (arm_t * arm ) {
108114 if (likely (arm_nvm_region_lock_check (arm ))) {
115+ uint32_t idx = (arm -> mem .nvmctrl .ADDR .bit .ADDR << 1 &
116+ (FLASH_SIZE - 1 ) & - FLASH_PAGE_SIZE ) >> 2 ;
109117 for (uint32_t off = 0 ; off != FLASH_PAGE_SIZE >> 2 ; ++ off ) {
110118 arm -> mem .nvm [idx + off ] &= arm -> mem .pb [off ];
111119 }
112120 }
113121 arm_nvm_clear_page_buffer (& arm -> mem );
114122}
115123
124+ static void arm_nvm_write_aux_page (arm_t * arm ) {
125+ if (likely (arm_nvm_aux_region_check (arm ))) {
126+ for (uint32_t off = 0 ; off != FLASH_USER_PAGE_SIZE >> 2 ; ++ off ) {
127+ arm -> mem .aux [off ] &= arm -> mem .pb [off ];
128+ }
129+ }
130+ arm_nvm_clear_page_buffer (& arm -> mem );
131+ }
132+
116133static void arm_mem_sercom_reset (SERCOM_Type * sercom ) {
117134 memset (sercom , 0 , sizeof (* sercom ));
118135}
@@ -306,14 +323,11 @@ static uint32_t arm_mem_load_any(arm_t *arm, uint32_t addr) {
306323 return arm -> mem .nvm [(addr - FLASH_ADDR ) >> 2 ];
307324 } else if (likely (addr - HMCRAMC0_ADDR < HMCRAMC0_SIZE )) { // Internal SRAM
308325 return arm -> mem .ram [(addr - HMCRAMC0_ADDR ) >> 2 ];
309- } else if (unlikely (addr < HPB0_ADDR )) {
310- if (addr - NVMCTRL_OTP1 < 8 ) {
311- return 0 ;
312- }
313- if (addr - NVMCTRL_OTP2 < 8 ) {
314- return 0 ;
326+ } else if (unlikely (addr < HPB0_ADDR )) { // Auxiliary Flash
327+ if (addr - NVMCTRL_USER < FLASH_USER_PAGE_SIZE ) {
328+ return arm -> mem .aux [(addr - NVMCTRL_USER ) >> 2 ];
315329 }
316- if (addr - NVMCTRL_OTP4 < 8 ) {
330+ if (addr - NVMCTRL_OTP4 < 16 ) {
317331 return 0 ;
318332 }
319333 if (addr == 0x80A00C ) {
@@ -801,21 +815,32 @@ static void arm_mem_store_any(arm_t *arm, uint32_t val, uint32_t mask, uint32_t
801815 uint8_t offset = addr >> 2 & 0xFF ;
802816 assert (!((addr & 3 ) | (val & mask )) &&
803817 "Address should be aligned and mask should be valid" );
804- if (unlikely (addr - FLASH_ADDR < FLASH_SIZE )) { // Page Buffer
818+ if (likely (addr - HMCRAMC0_ADDR < HMCRAMC0_SIZE )) { // Internal SRAM
819+ uint32_t * ptr = & arm -> mem .ram [(addr - HMCRAMC0_ADDR ) >> 2 ];
820+ * ptr = (* ptr & mask ) | val ;
821+ return ;
822+ } else if (unlikely (addr - FLASH_ADDR < FLASH_SIZE )) { // Page Buffer
805823 if (likely (!(mask & mask >> 16 ))) { // no 8-bit writes
806824 uint32_t * ptr = & arm -> mem .pb [((addr - FLASH_ADDR ) & (FLASH_PAGE_SIZE - 1 )) >> 2 ];
807825 * ptr = (* ptr & mask ) | val ;
808826 arm -> mem .nvmctrl .ADDR .bit .ADDR = (addr - FLASH_ADDR ) >> 1 | (mask & 1 );
809827 if (unlikely (!(mask >> 16 ) && !~(addr | - FLASH_PAGE_SIZE | 3 ) &&
810- !arm -> mem .nvmctrl .CTRLB .bit .MANW )) {
811- arm_nvm_write_page (arm , false);
828+ !arm -> mem .nvmctrl .CTRLB .bit .MANW )) {
829+ arm_nvm_write_page (arm );
830+ }
831+ return ;
832+ }
833+ } else if (unlikely (addr - NVMCTRL_USER < FLASH_USER_PAGE_SIZE )) { // User Page Buffer
834+ if (likely (!(mask & mask >> 16 ))) { // no 8-bit writes
835+ uint32_t * ptr = & arm -> mem .pb [((addr - NVMCTRL_USER ) & (FLASH_USER_PAGE_SIZE - 1 )) >> 2 ];
836+ * ptr = (* ptr & mask ) | val ;
837+ arm -> mem .nvmctrl .ADDR .bit .ADDR = (addr - FLASH_USER_PAGE_ADDR ) >> 1 | (mask & 1 );
838+ if (unlikely (!(mask >> 16 ) && !~(addr | - FLASH_USER_PAGE_SIZE | 3 ) &&
839+ !arm -> mem .nvmctrl .CTRLB .bit .MANW )) {
840+ arm_nvm_write_aux_page (arm );
812841 }
813842 return ;
814843 }
815- } else if (likely (addr - HMCRAMC0_ADDR < HMCRAMC0_SIZE )) { // Internal SRAM
816- uint32_t * ptr = & arm -> mem .ram [(addr - HMCRAMC0_ADDR ) >> 2 ];
817- * ptr = (* ptr & mask ) | val ;
818- return ;
819844 } else if (unlikely (addr < HPB0_ADDR )) {
820845 } else if (unlikely (addr < HPB1_ADDR )) { // Peripheral Bridge A
821846 uint32_t id = ID_PAC0 + ((addr - HPB0_ADDR ) >> 10 );
@@ -969,16 +994,16 @@ static void arm_mem_store_any(arm_t *arm, uint32_t val, uint32_t mask, uint32_t
969994 if ((val & NVMCTRL_CTRLA_CMDEX_Msk ) == NVMCTRL_CTRLA_CMDEX_KEY ) {
970995 switch (val & NVMCTRL_CTRLA_CMD_Msk ) {
971996 case NVMCTRL_CTRLA_CMD_ER :
972- arm_nvm_erase_row (arm , false );
997+ arm_nvm_erase_row (arm );
973998 return ;
974999 case NVMCTRL_CTRLA_CMD_WP :
975- arm_nvm_write_page (arm , false );
1000+ arm_nvm_write_page (arm );
9761001 return ;
9771002 case NVMCTRL_CTRLA_CMD_EAR :
978- arm_nvm_erase_row (arm , true );
1003+ arm_nvm_erase_aux_row (arm );
9791004 return ;
9801005 case NVMCTRL_CTRLA_CMD_WAP :
981- arm_nvm_write_page (arm , true );
1006+ arm_nvm_write_aux_page (arm );
9821007 return ;
9831008 case NVMCTRL_CTRLA_CMD_SF :
9841009 break ;
0 commit comments