#include "yc11xx_qspi.h" #define QSPI_BUSYTIMEOUT (0x1000000) #define DMA_WAIT_TIMEOUT (0x10000) void __attribute__((noinline)) SetLockQSPI( ) { HWRITE(mem_lock_qspi, 1); } void __attribute__((noinline)) SetReleaseQSPI( ) { HWRITE(mem_lock_qspi, 0); } void __attribute__((noinline)) prefetch(void *start_addr, void *end_addr) { int addr= 0; for(addr = (int)start_addr & (~0x1f);addr < (int)end_addr + 96;addr += 32) { *(volatile int*)addr = 0; } } void qspi_dma_start(void *src,int srclen,void *dst,int dstlen) { HWRITEW(CORE_QSPI_TXADDR,(int)src); HWRITEW(CORE_QSPI_TXLEN,srclen); HWRITEW(CORE_QSPI_RXADDR,(int)dst); HWRITEW(CORE_QSPI_RXLEN,dstlen); HWRITE(CORE_DMA_START,8); } uint8_t qspi_dma_wait(void) { int timeout = 0; while(!(HREAD(CORE_DMA_STATUS) & 8)) { timeout++; if(timeout>DMA_WAIT_TIMEOUT) { return ERROR; } } return SUCCESS; } /* * @brief: qspi_write (spi mode) * @param: tbuf data buffer * @param: len data len * @return: ERROR ,SUCCESS */ uint8_t qspi_write(uint8_t *tbuf,uint32_t len) { uint8_t ctrl = HREAD(CORE_QSPI_CTRL); uint8_t delay = HREAD(CORE_QSPI_DELAY); uint8_t ret = 0; HWRITE(CORE_QSPI_CTRL, 0x44); HWRITE(CORE_QSPI_DELAY,0x80); qspi_dma_start(tbuf, len, 0, 0); ret = qspi_dma_wait(); HWRITE(CORE_QSPI_CTRL, ctrl); HWRITE(CORE_QSPI_DELAY, delay); return ret; } /* * @brief:qspi_read_write (spi mode) * @param:tbuf * @param:tlen * @param:rbuf * @param:rlen * @return: none */ uint8_t qspi_read_write(uint8_t *tbuf,uint32_t tlen,uint8_t *rbuf,uint32_t rlen) { uint8_t ctrl = HREAD(CORE_QSPI_CTRL); uint8_t delay = HREAD(CORE_QSPI_DELAY); uint8_t ret = 0; HWRITE(CORE_QSPI_CTRL, 0x44); HWRITE(CORE_QSPI_DELAY,0x80); qspi_dma_start(tbuf, tlen, rbuf, rlen); ret = qspi_dma_wait(); HWRITE(CORE_QSPI_CTRL, ctrl); HWRITE(CORE_QSPI_DELAY,delay); return ret; } /* * @brief: write flash cmd * @param: cmd * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_cmd(uint8_t cmd) { uint8_t tbuf[1]; tbuf[0] = cmd; return qspi_write(tbuf, 1); } /* * @brief:read flash status1 * @param:cmd * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_readstatus1(uint8_t *rbuf) { uint8_t tbuf[1]; tbuf[0] = FlashCMD_ReadRegister1; return qspi_read_write(tbuf, 1, rbuf, 1); } /* * @brief:read flash status2 * @param:cmd * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_readstatus2(uint8_t *rbuf) { uint8_t tbuf[1]; tbuf[0] = FlashCMD_ReadRegister2; return qspi_read_write(tbuf, 1, rbuf, 1); } uint8_t qspi_flash_waitfinish(void) { uint32_t timeout = 0; uint8_t status1=1; while(status1 & 1) { qspi_flash_readstatus1(&status1); if(++timeout > QSPI_BUSYTIMEOUT) { return ERROR; } } return SUCCESS; } /* * @brief:write flash reg reg[0] s7~0 reg[1] s15~0 * @param:rxbuf * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_writestatus(uint8_t *reg) { uint8_t tbuf[3]; tbuf[0] = FlashCMD_WriteRegister; tbuf[1] = reg[0]; tbuf[2] = reg[1]; if(ERROR == qspi_flash_cmd(FlashCMD_WriteEnable)) return ERROR; qspi_write(tbuf, 3); return qspi_flash_waitfinish(); } /* * @brief:flash write enable * @param:none * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_writeenable(void) { return qspi_flash_cmd(FlashCMD_WriteEnable); } /* * @brief:flash write disable * @param:none * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_writedisable(void) { return qspi_flash_cmd(FlashCMD_WriteDisable); } void qspi_flash_precmd(uint8_t *buf,uint8_t cmd,uint32_t addr) { buf[0] = cmd; buf[1] = addr >> 16; buf[2] = addr >> 8; buf[3] = addr; } /* * @brief: flash write * @param: flash_addr * @param: len * @param: txbuf * @return: ERROR ,SUCCESS */ #define BLOCK_UNIT (256) uint8_t _qspi_flash_write(uint32_t flash_addr,uint32_t len,uint8_t *tbuf) { uint8_t buf[BLOCK_UNIT+4] = {0}; uint32_t packnum = 0; uint32_t packlen = 0; packlen = (BLOCK_UNIT - flash_addr % BLOCK_UNIT); packlen = packlen>len?len:packlen; qspi_flash_precmd(buf,FlashCMD_PageProgram,flash_addr); for(uint32_t j = 0;j BLOCK_UNIT?BLOCK_UNIT:len; qspi_flash_precmd(buf,FlashCMD_PageProgram,flash_addr+i*BLOCK_UNIT); for(uint32_t j = 0;j> 16; tbuf[2] = flash_addr >> 8; tbuf[3] = flash_addr; HWRITE(CORE_QSPI_CTRL,0x45); HWRITE(CORE_QSPI_DELAY,0x8); qspi_dma_start(tbuf, tlen, rbuf, rlen); ret = qspi_dma_wait(); HWRITE(CORE_QSPI_CTRL, ctrl); HWRITE(CORE_QSPI_DELAY, delay); return ret; } /* * @brief:read flash id * @param:cmd * @return: ERROR ,SUCCESS */ uint32_t _qspi_flash_ManufactureID(void) { uint8_t tbuf[4]={0,0,0,0}; uint8_t rbuf[2]; uint32_t ret; tbuf[0] = FlashCMD_REMS; qspi_read_write(tbuf, 4, rbuf, 2); ret = ((rbuf[0]<<8) | rbuf[1]); return ret; } /* * @brief:page erase 256byte * @param:flash addr * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_pageerase(uint32_t flash_addr) { prefetch(qspi_dma_start, qspi_flash_sectorerase); return _qspi_flash_erase(FlashCMD_PageErase,flash_addr); } /* * @brief:sector erase 4kB * @param:flash addr * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_sectorerase(uint32_t flash_addr) { prefetch(qspi_dma_start, qspi_flash_sectorerase); return _qspi_flash_erase(FlashCMD_SectorErase,flash_addr); } /* * @brief:block erase 32K * @param:flash addr * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_blockerase32k(uint32_t flash_addr) { prefetch(qspi_dma_start, qspi_flash_blockerase32k); return _qspi_flash_erase(FlashCMD_32kErase,flash_addr); } /* * @brief:block erase 64K * @param:flash addr * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_blockerase64k(uint32_t flash_addr) { prefetch(qspi_dma_start, qspi_flash_blockerase64k); return _qspi_flash_erase(FlashCMD_64kErase,flash_addr); } uint8_t qspi_flash_chiperase(void) { prefetch(qspi_dma_start, qspi_flash_chiperase); return _qspi_flash_chiperase(); } uint8_t qspi_flash_write(uint32_t flash_addr,uint32_t len,uint8_t *tbuf) { prefetch(qspi_dma_start, qspi_flash_write); return _qspi_flash_write(flash_addr,len,tbuf); } /* * @brief: flash read * @param: flash_addr * @param: len * @param: rxbuf * @return: ERROR ,SUCCESS */ uint8_t qspi_flash_read(uint32_t flash_addr,uint32_t rlen,uint8_t *rbuf) { prefetch(qspi_dma_start, qspi_flash_read); return _qspi_flash_read(flash_addr,rlen,rbuf); } /* * @brief:read flash id * @param:cmd * @return: ERROR ,SUCCESS */ uint32_t qspi_flash_ManufactureID(void) { prefetch(qspi_dma_start, qspi_flash_ManufactureID); return _qspi_flash_ManufactureID(); } uint8_t QSPI_ReadFlashData(uint32_t flash_addr,uint32_t rlen,uint8_t *rbuf) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_read(flash_addr, rlen, rbuf); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; } uint8_t QSPI_WriteFlashData(uint32_t flash_addr,uint32_t len,uint8_t *tbuf) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_write(flash_addr, len, tbuf); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; } uint8_t QSPI_SectorEraseFlash(uint32_t flash_addr) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_sectorerase(flash_addr); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; } uint8_t QSPI_PageEraseFlash(uint32_t flash_addr) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_pageerase(flash_addr); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; } uint8_t QSPI_BlockEraseFlash32k(uint32_t flash_addr) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_blockerase32k(flash_addr); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; } uint8_t QSPI_BlockEraseFlash64k(uint32_t flash_addr) { uint8_t ret; OS_ENTER_CRITICAL(); SetLockQSPI( ); ret = qspi_flash_blockerase64k(flash_addr); SetReleaseQSPI( ); OS_EXIT_CRITICAL(); return ret; }