123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- /**
- * @file flash.c
- * @author chipsea
- * @brief Contains all functions support for flash driver
- * @version 0.1
- * @date 2020-11-30
- * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
- * @note
- */
- #include "sdk_config.h"
- #include "flash.h"
- #include "log.h"
- #include "types.h"
- #include "error.h"
- #include "pwrmgr.h"
- #include <string.h>
- #include "rom_sym_def.h"
- #define FLASH_LOCK_504K 0x04//0x00-0x7DFFF
- #define FLASH_LOCK_496K 0x08//0x00-0x7BFFF
- #define FLASH_LOCK_480K 0x0C//0x00-0x77FFF
- #define FLASH_LOCK_448K 0x10//0x00-0x6FFFF
- #define FLASH_LOCK_384K 0x14//0x00-0x5FFFF
- #define FLASH_LOCK_HALF 0x18//0x00-0x3FFFF
- #define FLASH_LOCK_ALL 0x1C//0x00-0x7FFFF
- #define FLASH_UNLOCK 0x00
- #define WRITE_ENABLE 0x6000001
- #define WRITE_PROTECT 0x1008001
- #define REG_FLASH_BP (*((volatile unsigned int *)(0x4000c8a8)))
- #define REG_FLASH_WRITE_CTRL (*((volatile unsigned int *)(0x4000c890)))
- #define SPIF_WAIT_IDLE_CYC (32)
- #define SPIF_STATUS_WAIT_IDLE(n) \
- do \
- { \
- while((AP_SPIF->fcmd &0x02)==0x02); \
- { \
- volatile int delay_cycle = n; \
- while (delay_cycle--){;} \
- } \
- while ((AP_SPIF->config & 0x80000000) == 0);\
- } while (0);
-
- #define HAL_CACHE_ENTER_BYPASS_SECTION() do{ \
- HAL_ENTER_CRITICAL_SECTION();\
- AP_CACHE->CTRL0 = 0x02; \
- AP_PCR->CACHE_RST = 0x02;\
- AP_PCR->CACHE_BYPASS = 1; \
- HAL_EXIT_CRITICAL_SECTION();\
- }while(0);
- #define HAL_CACHE_EXIT_BYPASS_SECTION() do{ \
- HAL_ENTER_CRITICAL_SECTION();\
- AP_CACHE->CTRL0 = 0x00;\
- AP_PCR->CACHE_RST = 0x03;\
- AP_PCR->CACHE_BYPASS = 0;\
- HAL_EXIT_CRITICAL_SECTION();\
- }while(0);
- #define spif_wait_nobusy(flg, tout_ns, return_val) {if(_spif_wait_nobusy_x(flg, tout_ns)){if(return_val){ return return_val;}}}
- typedef struct {
- sysclk_t spif_ref_clk;
- uint32_t rd_instr;
- }xflash_Ctx_t;
- static xflash_Ctx_t s_xflashCtx = {.spif_ref_clk=SYS_CLK_RC_32M,.rd_instr=XFRD_FCMD_READ_DUAL};
- extern int _spif_wait_nobusy(uint8_t flg, uint32_t tout_ns);
- extern int spif_write(uint32_t addr, uint8_t* data, uint32_t size);
- extern int spif_write_dma(uint32_t addr, uint8_t* data, uint32_t size);
- extern int spif_read(uint32_t addr, uint8_t* data, uint32_t size);
- extern int spif_read_dma(uint32_t addr, uint8_t* data, uint32_t size);
- extern int spif_erase_sector(unsigned int addr);
- extern int spif_erase_block64(unsigned int addr);
- extern int spif_erase_all(void);
- extern uint8_t spif_flash_status_reg_0(void);
- extern int spif_write_protect(bool en);
- extern void spif_cmd(uint8_t op, uint8_t addrlen, uint8_t rdlen, uint8_t wrlen, uint8_t mbit, uint8_t dummy);
- extern void spif_rddata(uint8_t* data, uint8_t len);
- extern int spif_config(sysclk_t ref_clk, uint8_t div, uint32_t rd_instr, uint8_t mode_bit, uint8_t QE);
- static inline uint32_t spif_lock()
- {
- HAL_ENTER_CRITICAL_SECTION();
- uint32_t vic_iser = NVIC->ISER[0];
- //mask all irq
- NVIC->ICER[0] = 0xFFFFFFFF;
- //enable ll irq and tim1 irq
- NVIC->ISER[0] = 0x100010;
- HAL_EXIT_CRITICAL_SECTION();
- return vic_iser;
- }
- static inline void spif_unlock(uint32_t vic_iser)
- {
- HAL_ENTER_CRITICAL_SECTION();
- NVIC->ISER[0] = vic_iser;
- HAL_EXIT_CRITICAL_SECTION();
- }
- static void hal_cache_tag_flush(void)
- {
- HAL_ENTER_CRITICAL_SECTION();
- uint32_t cb = AP_PCR->CACHE_BYPASS;
- volatile int dly = 8;
- if(cb==0)
- {
- AP_PCR->CACHE_BYPASS = 1;
- }
- AP_CACHE->CTRL0 = 0x02;
- while (dly--){;};
- AP_CACHE->CTRL0 = 0x03;
- dly = 8;while (dly--){;};
- AP_CACHE->CTRL0 = 0x00;
- if(cb==0)
- {
- AP_PCR->CACHE_BYPASS = 0;
- }
-
- HAL_EXIT_CRITICAL_SECTION();
- }
- static uint8_t _spif_read_status_reg_x(void)
- {
- uint8_t status;
- spif_cmd(FCMD_RDST, 0, 2, 0, 0, 0);
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_rddata(&status, 1);
- return status;
- }
- static int _spif_wait_nobusy_x(uint8_t flg, uint32_t tout_ns)
- {
- uint8_t status;
- volatile int tout = (int )(tout_ns);
- for(; tout ; tout --){
- status = _spif_read_status_reg_x();
- if((status & flg) == 0)
- return ERR_NONE;
- //insert polling interval
- //5*32us
- WaitRTCCount(5);
- }
- return ERR_BUSY;
- }
- static void hal_cache_init(void)
- {
- volatile int dly=100;
- //clock gate
- hal_clk_gate_enable(MOD_HCLK_CACHE);
- hal_clk_gate_enable(MOD_PCLK_CACHE);
- //cache rst ahp
- AP_PCR->CACHE_RST=0x02;
- while(dly--){};
- AP_PCR->CACHE_RST=0x03;
- hal_cache_tag_flush();
- //cache enable
- AP_PCR->CACHE_BYPASS = 0;
- }
- static void hw_spif_cache_config(void)
- {
- spif_config(s_xflashCtx.spif_ref_clk,/*div*/1,s_xflashCtx.rd_instr,0,0);
- AP_SPIF->wr_completion_ctrl=0xff010005;//set longest polling interval
- NVIC_DisableIRQ(SPIF_IRQn);
- NVIC_SetPriority((IRQn_Type)SPIF_IRQn, IRQ_PRIO_HAL);
- hal_cache_init();
- }
- int hal_flash_erase_all(void)
- {
- uint8_t retval;
- uint32_t cb = AP_PCR->CACHE_BYPASS;
- HAL_CACHE_ENTER_BYPASS_SECTION();
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
- retval = spif_erase_all();
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
- HAL_CACHE_EXIT_BYPASS_SECTION();
- if(cb == 0)
- {
- hal_cache_tag_flush();
- }
- return retval;
- }
- /**
- * @fn void HalFlashInit(void)
- * @brief flash Initialization function.
- * @param NONE.
- * @return NONE.
- */
- ErrCode_t HalFlashInit(void)
- {
- hw_spif_cache_config();
- hal_pwrmgr_register(MOD_SPIF, NULL, hw_spif_cache_config);
- return ERR_NONE;
- }
- /**
- * @fn void HalFlashRead(uint32_t offset, uint8_t *buf, uint32_t len)
- * @brief flash read function.
- * @param[offset] read address in flash.
- * @param[buf] receive data buffer.
- * @param[len] receive data length.
- * @return NONE.
- */
- void HalFlashRead(uint32_t addr, uint8_t *buf, uint32_t len)
- {
- volatile uint8_t *u8_spif_addr = (volatile uint8_t *)((addr & 0x7ffff) | FLASH_BASE_ADDR);
- uint32_t cb = AP_PCR->CACHE_BYPASS;
- uint32_t cs = spif_lock();
-
- #if(SPIF_FLASH_SIZE==FLASH_SIZE_1MB)
- uint32_t remap = addr & 0xf80000;
- if(remap)
- {
- AP_SPIF->remap = remap;
- AP_SPIF->config |= 0x10000;
- }
- #endif
- //read flash addr direct access
- //bypass cache
- if(cb == 0)
- {
- HAL_CACHE_ENTER_BYPASS_SECTION();
- }
-
- for(int i=0; i<len; i++)
- {
- buf[i]=u8_spif_addr[i];
- }
- //bypass cache
- if(cb == 0)
- {
- HAL_CACHE_EXIT_BYPASS_SECTION();
- }
- #if(SPIF_FLASH_SIZE==FLASH_SIZE_1MB)
- if(remap)
- {
- AP_SPIF->remap = 0;
- AP_SPIF->config &= ~0x10000ul;
- }
- #endif
- spif_unlock(cs);
- }
- /**
- * @fn ErrCode_t HalFlashWrite(uint32_t offset, uint8_t *buf, uint16_t len)
- * @brief flash write function.(offset + len) must be smaller than the current sector
- * @param offset: write address in flash.
- * @param buf: write data buffer.
- * @param len: write data length.
- * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
- return ERR_NONE when the operation is complete;
- */
- ErrCode_t HalFlashWrite(uint32_t addr, uint8_t* buf, uint32_t len)
- {
- ErrCode_t retval;
-
- if((buf == NULL) || (len == 0))
- return ERR_INVALID_DATA;
- uint32_t cs = spif_lock();
-
- addr &= 0x00FFFFFF;
-
- if( (addr < 0x2000) || (addr > 0x7FFFF) || ((addr+len) > 0x80000) )
- {
- return ERR_INVALID_PARAM;
- }
- if(len > 4096)
- {
- return ERR_INVALID_LENGTH;
- }
-
- HAL_CACHE_ENTER_BYPASS_SECTION();
-
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
- retval = (ErrCode_t)spif_write(addr, buf, len);
-
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
-
- HAL_CACHE_EXIT_BYPASS_SECTION();
- spif_unlock(cs);
-
- return retval;
- }
- /**
- * @fn ErrCode_t HalFlashWrite(uint32_t offset, uint8_t *buf, uint16_t len)
- * @brief flash write function.(offset + len) must be smaller than the current sector
- * @param offset: write address in flash.
- * @param buf: write data buffer.
- * @param len: write data length.
- * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
- return ERR_NONE when the operation is complete;
- */
- ErrCode_t HalFlashWriteByDma(uint32_t addr, uint8_t* buf, uint32_t len)
- {
- ErrCode_t retval;
- if(buf == NULL)
- {
- return ERR_INVALID_DATA;
- }
- if((len == 0) || (len > 4096))
- {
- return ERR_INVALID_LENGTH;
- }
- uint32_t cs = spif_lock();
- addr &= 0x00FFFFFF;
- if( (addr < 0x2000) || (addr > 0x7FFFF) || ((addr+len) > 0x80000) )
- {
- return ERR_INVALID_PARAM;
- }
- HAL_CACHE_ENTER_BYPASS_SECTION();
-
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
- retval = (ErrCode_t)spif_write_dma(addr, buf, len);
-
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
-
- HAL_CACHE_EXIT_BYPASS_SECTION();
- spif_unlock(cs);
- return retval;
- }
- /**
- * @fn ErrCode_t HalFlashWriteWord(uint32_t offset, uint32_t value)
- * @brief flash write function.(offset + len) must be smaller than the current sector
- * @param offset: write address in flash.
- * @param value: write data.
- * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
- return ERR_NONE when the operation is complete;
- */
- ErrCode_t HalFlashWriteWord(uint32_t offset, uint32_t value)
- {
- offset &= 0x00FFFFFF;
-
- if( (offset < 0x2000) || (offset > 0x7FFFC) )
- {
- return ERR_INVALID_PARAM;
- }
- uint32_t temp = value;
- return (HalFlashWrite(offset, (uint8_t *) &temp, 4));
- }
- /**
- * @fn ErrCode_t HalFlashErase(uint32_t sectorNum)
- * @brief erase one sector(4K byte) from falsh.
- * @param[sectorNum] erase sector number.
- * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
- return ERR_NONE when the operation is complete;
- */
- ErrCode_t HalFlashErase(uint32_t sectorNum)
- {
- sectorNum &= 0x00FFFFFF;
- if( (sectorNum < 2) || (sectorNum > 0x7F) )
- {
- return ERR_INVALID_PARAM;
- }
-
- uint8_t status = _spif_read_status_reg_x() & FLASH_LOCK_ALL;
- if(status)
- {
- switch(status)
- {
- case FLASH_LOCK_504K:
- if(sectorNum > 0x7D)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_496K:
- if(sectorNum > 0x7B)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_480K:
- if(sectorNum > 0x77)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_448K:
- if(sectorNum > 0x6F)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_384K:
- if(sectorNum > 0x5F)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_HALF:
- if(sectorNum > 0x3F)
- {
- return ERR_INVALID_PARAM;
- }
- break;
-
- case FLASH_LOCK_ALL:
- return ERR_INVALID_PARAM;
- }
- }
-
- ErrCode_t retval;
- uint32_t cs = spif_lock();
-
- uint32_t cb = AP_PCR->CACHE_BYPASS;
- HAL_CACHE_ENTER_BYPASS_SECTION();
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
- retval = (ErrCode_t)spif_erase_sector((sectorNum<<12));
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
- HAL_CACHE_EXIT_BYPASS_SECTION();
- if(cb == 0)
- {
- hal_cache_tag_flush();
- }
- spif_unlock(cs);
-
- return retval;
- }
- /**
- * @fn ErrCode_t HalFlashErase64K(uint32_t addr)
- * @brief erase (64 Kbyte) from falsh.
- * @param[addr] erase addr.
- * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
- return ERR_NONE when the operation is complete;
- */
- ErrCode_t HalFlashErase64K(uint32_t addr)
- {
- addr &= 0x00FFFFFF;
- if( (addr < 0x10000) || (addr > 0x70000) )
- {
- return ERR_INVALID_PARAM;
- }
- ErrCode_t retval;
- uint32_t cs = spif_lock();
- uint32_t cb = AP_PCR->CACHE_BYPASS;
- HAL_CACHE_ENTER_BYPASS_SECTION();
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
- retval = (ErrCode_t)spif_erase_block64(addr);
- SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
- spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
- HAL_CACHE_EXIT_BYPASS_SECTION();
- if(cb == 0)
- {
- hal_cache_tag_flush();
- }
- spif_unlock(cs);
- return retval;
- }
- /**
- * @fn void HalFlashLock(flash_lock_t lock)
- * @brief flash lock.
- * @param none.
- * @return none
- */
- void HalFlashLock(flash_lock_t lock)
- {
- REG_FLASH_WRITE_CTRL = WRITE_ENABLE;
- REG_FLASH_BP = lock;
- REG_FLASH_WRITE_CTRL = WRITE_PROTECT;
- }
- /**
- * @fn void HalFlashUnlock(void)
- * @brief flash unlock.
- * @param none.
- * @return none
- */
- void HalFlashUnlock(void)
- {
- while( _spif_read_status_reg_x() )
- {
- REG_FLASH_WRITE_CTRL = WRITE_ENABLE;
- REG_FLASH_BP = FLASH_UNLOCK;
- REG_FLASH_WRITE_CTRL = WRITE_PROTECT;
- WaitUs(50);
- }
- }
|