#include "board.h" #define FLASH_BYPASS do{M0P_FLASH->BYPASS = 0x5A5A;\ M0P_FLASH->BYPASS = 0xA5A5; }while(0) // HC32L196 // page Size:512bytes // total size:256Kbyes(512page) // space :0x08000000 ~ 0x0803FFFF void McuFlash_init(void) { rt_base_t level; level = rt_hw_interrupt_disable(); #if defined(SYSCLK_4M_MODE) FLASH_BYPASS; M0P_FLASH->TNVS = 0x020u; FLASH_BYPASS; M0P_FLASH->TPGS = 0x017u; FLASH_BYPASS; M0P_FLASH->TPROG = 0x01Bu; FLASH_BYPASS; M0P_FLASH->TSERASE = 0x04650u; FLASH_BYPASS; M0P_FLASH->TMERASE = 0x0222E0u; FLASH_BYPASS; M0P_FLASH->TPRCV = 0x018u; FLASH_BYPASS; M0P_FLASH->TSRCV = 0x0F0u; FLASH_BYPASS; M0P_FLASH->TMRCV = 0x03E8u; #elif defined(SYSCLK_8M_MODE) FLASH_BYPASS; M0P_FLASH->TNVS = 0x040u; FLASH_BYPASS; M0P_FLASH->TPGS = 0x02Eu; FLASH_BYPASS; M0P_FLASH->TPROG = 0x036u; FLASH_BYPASS; M0P_FLASH->TSERASE = 0x08CA0u; FLASH_BYPASS; M0P_FLASH->TMERASE = 0x0445C0u; FLASH_BYPASS; M0P_FLASH->TPRCV = 0x030u; FLASH_BYPASS; M0P_FLASH->TSRCV = 0x1E0u; FLASH_BYPASS; M0P_FLASH->TMRCV = 0x07D0u; #elif defined(SYSCLK_16M_MODE) FLASH_BYPASS; M0P_FLASH->TNVS = 0x080u; FLASH_BYPASS; M0P_FLASH->TPGS = 0x05Cu; FLASH_BYPASS; M0P_FLASH->TPROG = 0x06Cu; FLASH_BYPASS; M0P_FLASH->TSERASE = 0x11940u; FLASH_BYPASS; M0P_FLASH->TMERASE = 0x088B80u; FLASH_BYPASS; M0P_FLASH->TPRCV = 0x060u; FLASH_BYPASS; M0P_FLASH->TSRCV = 0x3C0u; FLASH_BYPASS; M0P_FLASH->TMRCV = 0x0FA0u; #endif rt_hw_interrupt_enable(level); } void McuFlash_WaitBusy(void) { while(M0P_FLASH->CR_f.BUSY){ // wait until not busy } } void McuFlash_Unlock(void) { rt_base_t level; level = rt_hw_interrupt_disable(); FLASH_BYPASS; M0P_FLASH->SLOCK0 = 0xFFFFFFFF; // 0:forbid PE; 1:allow PE; FLASH_BYPASS; M0P_FLASH->SLOCK1 = 0xFFFFFFFF; FLASH_BYPASS; M0P_FLASH->SLOCK2 = 0xFFFFFFFF; FLASH_BYPASS; M0P_FLASH->SLOCK3 = 0xFFFFFFFF; rt_hw_interrupt_enable(level); } void McuFlash_Lock(void) { rt_base_t level; McuFlash_WaitBusy(); level = rt_hw_interrupt_disable(); FLASH_BYPASS; M0P_FLASH->SLOCK0 = 0x00000000; // 0:forbid PE; 1:allow PE; FLASH_BYPASS; M0P_FLASH->SLOCK1 = 0x00000000; FLASH_BYPASS; M0P_FLASH->SLOCK2 = 0x00000000; FLASH_BYPASS; M0P_FLASH->SLOCK3 = 0x00000000; rt_hw_interrupt_enable(level); } #ifndef BOOTLOADER_ENABLE void McuFlash_ErasePage(uint32_t addr) { rt_base_t level; McuFlash_WaitBusy(); level = rt_hw_interrupt_disable(); FLASH_BYPASS; M0P_FLASH->CR_f.OP = 0x2u; // 0:read; 1:probram; 2:sector rease; 3:chip erase *((volatile uint8_t *)addr) = 0xFFu; // start erase page rt_hw_interrupt_enable(level); } void McuFlash_WordPP(uint32_t addr, uint32_t data) { rt_base_t level; McuFlash_WaitBusy(); level = rt_hw_interrupt_disable(); FLASH_BYPASS; M0P_FLASH->CR_f.OP = 0x1u; // 0:read; 1:probram; 2:sector rease; 3:chip erase *((volatile uint32_t *)addr) = data; // start program rt_hw_interrupt_enable(level); } #endif void McuFlash_EraseSegment(uint32_t start, uint32_t len) { uint32_t end; // Page size = 512byts // total 512xPages end = start+len-1; // be sure start + len < 0xFFFFFFFFu - 0xFFu while(start<=end){ McuFlash_ErasePage(start); start += 512; } } // prepare for word programming void McuFlash_OpenWP(uint32_t addr, McuFlash_WP_t *p) { p->addr = addr & ~0x3u; // must 4 bytes aligned p->idx = 0; } // program words from buffer void McuFlash_Buf2WP(uint8_t *buf, uint32_t len, McuFlash_WP_t *p) { while(len--){ // program size is 4 byte p->u.byte[p->idx] = *buf++; if (p->idx==3){ p->idx = 0; McuFlash_WordPP(p->addr, p->u.word); p->addr += 4; } else { p->idx++; } } } // program last not enough gathered word if exists void McuFlash_CloseWP(McuFlash_WP_t *p) { if (p->idx!=0){ while(p->idx<4){ p->u.byte[p->idx] = 0xFFu; p->idx++; } p->idx = 0; McuFlash_WordPP(p->addr, p->u.word); p->addr += 4; } }