/************************************************************************************************ * Copyright (c) Fenda Technologies Co., Ltd. 2012-2020. All rights reserved. * Description: nand flash * Author: luca.hutianjun 029191 * Create: 2021-11-27 ************************************************************************************************/ #include #include #include #include #include #include "am_util_delay.h" #include "drv_mspi.h" #include "ds35m1ga.h" /**********mspi module*****************************/ #define DS35M_MSPI_MODULE 1 #define DS35M_WR_DATA_LINE_1 0 #define DS35M_WR_DATA_LINE_4 1 #define DS35M_WR_DATA_LINE_MODE DS35M_WR_DATA_LINE_4 /**********command********************************/ #define DS35M_CMD_WRITE_ENABLE (0x06) #define DS35M_CMD_WRITE_DISABLE (0x04) #define DS35M_CMD_GET_FEATURE (0x0F) #define DS35M_CMD_SET_FEATURE (0x1F) #define DS35M_CMD_READ_PAGE_TO_CACHE (0x13) #define DS35M_CMD_READ_FROM_CACHE (0x03) // 0x0B #define DS35M_CMD_READ_FROM_CACHE_2 (0x3B) #define DS35M_CMD_READ_FROM_CACHE_4 (0x6B) #define DS35M_CMD_READ_FROM_CACHE_DTR (0xEE) #define DS35M_CMD_READ_ID (0x9F) #define DS35M_CMD_READ_PARAM_PAGE (0x13) #define DS35M_CMD_READ_UID (0x13) #define DS35M_CMD_PROGRAM_LOAD (0x02) #define DS35M_CMD_PROGRAM_LOAD_4 (0x32) #define DS35M_CMD_PROGRAM_EXECUTE (0x10) #define DS35M_CMD_PROGRAM_LOAD_RAND (0x84) #define DS35M_CMD_PROGRAM_LOAD_RAND_4 (0xC4) // 0x34 #define DS35M_CMD_ERASE_BLOCK (0xD8) #define DS35M_CMD_RESET (0xFF) #define DS35M_CMD_EN_POWER_ON_RESET (0x66) #define DS35M_CMD_POWER_ON_RESET (0x99) /**********features add***************************/ #define DS35M_FEATURES_ADD_PROTECT 0xA0 #define DS35M_FEATURES_ADD_FEATURE_0 0xB0 #define DS35M_FEATURES_ADD_STATUS_0 0xC0 #define DS35M_FEATURES_ADD_FEATURE_1 0xD0 #define DS35M_FEATURES_ADD_STATUS_1 0xF0 /**************** Protection mark******************/ #define DS35M_PROTECTION_MASK_CMP 0x02 #define DS35M_PROTECTION_MASK_INV 0x04 #define DS35M_PROTECTION_MASK_BP 0x38 #define DS35M_PROTECTION_MASK_BRWD 0x80 /***************** feature 0 mark******************/ #define DS35M_FEATURE_0_MASK_QE 0x01 #define DS35M_FEATURE_0_MASK_BPL 0x08 #define DS35M_FEATURE_0_MASK_ECC_EN 0x10 #define DS35M_FEATURE_0_MASK_OTP_EN 0x40 #define DS35M_FEATURE_0_MASK_OTP_PRT 0x80 /***************** status 0 mark******************/ #define DS35M_STATUS_0_MASK_OIP 0x01 #define DS35M_STATUS_0_MASK_WEL 0x02 #define DS35M_STATUS_0_MASK_E_FAIL 0x04 #define DS35M_STATUS_0_MASK_P_FAIL 0x08 #define DS35M_STATUS_0_MASK_ECCS0 0x10 #define DS35M_STATUS_0_MASK_ECCS1 0x20 #define DS35M_STATUS_0_MASK_ECCS 0x30 /***************** feature 1 mark******************/ #define DS35M_FEATURE_1_MASK_DS_IO 0x60 /***************** status 1 mark******************/ #define DS35M_STATUS_1_MASK_BPS 0x08 #define DS35M_STATUS_1_MASK_ECCSE0 0x10 #define DS35M_STATUS_1_MASK_ECCSE1 0x20 #if defined(EXT_FLASH_CHIP_DS35M1GA) typedef enum { DS35M_TRANS_1_1_1 = 0, DS35M_TRANS_1_1_2, DS35M_TRANS_1_1_4, DS35M_TRANS_1_1_8, DS35M_TRANS_1_4_4, DS35M_TRANS_ERR, } ds35mTransMode_e; typedef enum { DS35M_TRANS_TX = 0, DS35M_TRANS_RX, } ds35mTransDirect_e; typedef struct { uint8_t cmd; uint8_t addrByte; uint32_t addrVal; uint8_t dummyByte; ds35mTransDirect_e direct; } ds35mTransInfo_s; typedef enum { DS35M_IOCTL_QE_ENABLE = 0x10, DS35M_IOCTL_QE_DISABLE, DS35M_IOCTL_GET_READ_STA, DS35M_IOCTL_DIS_PROTECT_BLOCK, DS35M_IOCTL_ECC_ENABLE, DS35M_IOCTL_ECC_DISABLE, } DS35MIoctlEvent_e; static uint32_t ds35m_DmaBuffer[(AM_HAL_MSPI_CQ_ENTRY_SIZE / 4) * (2 + 1)] = {0}; static volatile uint8_t ds35m_dmaCompleteFlg = 0; /*spare area M2: 0-3, 16-19,32-35,48-51 M1: 4-7, 20-23,36-39,52-55 R1: 8-15,24-31,40-47,56-63 ECC(512B对应一组) */ //static bool ds35m_chipEccSw = true; static void Bsp_Ds35m_DmaComplete(void *pCallbackCtxt, uint32_t transactionStatus) { if(transactionStatus != AM_HAL_STATUS_SUCCESS) { } else { ds35m_dmaCompleteFlg = 1; } } static void Bsp_Ds35m_SwitchTransMode(ds35mTransMode_e mode) { static ds35mTransMode_e tmpMode = DS35M_TRANS_ERR; if(mode == tmpMode) { return; } switch(mode) { case DS35M_TRANS_1_1_1: MSPIn(DS35M_MSPI_MODULE)->CFG_b.DEVCFG = MSPI0_CFG_DEVCFG_SERIAL0; MSPIn(DS35M_MSPI_MODULE)->CFG_b.SEPIO = 1; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPMIXED = 0; MSPIn(DS35M_MSPI_MODULE)->PADCFG = 0; MSPIn(DS35M_MSPI_MODULE)->PADOUTEN = 0x103; break; case DS35M_TRANS_1_1_4: MSPIn(DS35M_MSPI_MODULE)->CFG_b.DEVCFG = MSPI0_CFG_DEVCFG_SERIAL0; MSPIn(DS35M_MSPI_MODULE)->CFG_b.SEPIO = 0; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPMIXED = 5; MSPIn(DS35M_MSPI_MODULE)->PADCFG = 0; MSPIn(DS35M_MSPI_MODULE)->PADOUTEN = 0x10F; break; case DS35M_TRANS_1_4_4: MSPIn(DS35M_MSPI_MODULE)->CFG_b.DEVCFG = MSPI0_CFG_DEVCFG_SERIAL0; MSPIn(DS35M_MSPI_MODULE)->CFG_b.SEPIO = 0; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPMIXED = 7; MSPIn(DS35M_MSPI_MODULE)->PADCFG = 0; MSPIn(DS35M_MSPI_MODULE)->PADOUTEN = 0x10F; break; default: break; } tmpMode = mode; } static uint32_t Bsp_Ds35m_TransSerial(ds35mTransInfo_s *pTrans, uint8_t *pData, uint32_t len) { uint32_t ui32Status; drv_mspi_t *pDs35m = &g_mspi_dev[DS35M_MSPI_MODULE]; am_hal_mspi_pio_transfer_t Transaction = {0}; // Create the individual write transaction. if(pTrans->direct == DS35M_TRANS_TX) { Transaction.eDirection = AM_HAL_MSPI_TX; } else { Transaction.eDirection = AM_HAL_MSPI_RX; } // cmd MSPIn(DS35M_MSPI_MODULE)->CFG_b.ISIZE = 0; Transaction.bSendInstr = true; Transaction.ui16DeviceInstr = pTrans->cmd; if(pTrans->addrByte) { Transaction.bSendAddr = true; Transaction.ui32DeviceAddr = pTrans->addrVal; MSPIn(DS35M_MSPI_MODULE)->CFG_b.ASIZE = pTrans->addrByte - 1; } else { Transaction.bSendAddr = false; } if((pTrans->dummyByte) && (pTrans->direct == DS35M_TRANS_TX)) { MSPIn(DS35M_MSPI_MODULE)->CFG_b.WRITELATENCY = 8; Transaction.bEnWRLatency = true; } else if((pTrans->dummyByte) && (pTrans->direct == DS35M_TRANS_RX)) { MSPIn(DS35M_MSPI_MODULE)->CFG_b.TURNAROUND = 8; Transaction.bTurnaround = true; } else { Transaction.bEnWRLatency = false; Transaction.bTurnaround = false; } Transaction.pui32Buffer = (uint32_t *)pData; Transaction.ui32NumBytes = len; Transaction.bContinue = false; Transaction.bQuadCmd = false; ui32Status = am_hal_mspi_blocking_transfer(pDs35m->pHandle, &Transaction, MSPI_TIMEOUT); return ui32Status; } #if (DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) static uint32_t byteToUintBit(uint8_t byte) { uint32_t tmpData = 0; uint8_t i; for(i = 0; i < 8; i++) { tmpData <<= 4; if(byte & 0x80) { tmpData |= 0x01; } byte <<= 1; } return tmpData; } static uint32_t Bsp_Ds35m_TransQuad(ds35mTransInfo_s *pTrans, uint8_t *pData, uint32_t len) { uint32_t ui32Status; drv_mspi_t *pDs35m = &g_mspi_dev[DS35M_MSPI_MODULE]; am_hal_mspi_dma_transfer_t Transaction = {0}; // 切换1-4-4传输模式 Bsp_Ds35m_SwitchTransMode(DS35M_TRANS_1_4_4); // dirct cmd if(pTrans->direct == DS35M_TRANS_TX) { Transaction.eDirection = AM_HAL_MSPI_TX; } else { Transaction.eDirection = AM_HAL_MSPI_RX; } // cmd 2byte = cmd(1) + dummy(1/2) + addr(11-8bit) MSPIn(DS35M_MSPI_MODULE)->XIPINSTR_b.READINSTR = (DS35M_CMD_READ_FROM_CACHE_4 << 8) | ((pTrans->addrVal >> 8) & 0x0F); MSPIn(DS35M_MSPI_MODULE)->XIPINSTR_b.WRITEINSTR = (DS35M_CMD_PROGRAM_LOAD_4 << 8) | (pTrans->addrVal >> 8) & 0x0F; MSPIn(DS35M_MSPI_MODULE)->CFG_b.ISIZE = 1; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPSENDI = 1; // address 4byte = addr(7-0bit) // MSPIn(DS35M_MSPI_MODULE)->ADDR = byteToUintBit(pTrans->addrVal&0xFF); MSPIn(DS35M_MSPI_MODULE)->CFG_b.ASIZE = 3; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPSENDA = 1; // dummy byte if((pTrans->dummyByte) && (pTrans->direct == DS35M_TRANS_TX)) { MSPIn(DS35M_MSPI_MODULE)->CFG_b.WRITELATENCY = 8; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPENWLAT = 1; } else if((pTrans->dummyByte) && (pTrans->direct == DS35M_TRANS_RX)) { MSPIn(DS35M_MSPI_MODULE)->CFG_b.TURNAROUND = 8; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPENTURN = 1; } else { MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPENWLAT = 0; MSPIn(DS35M_MSPI_MODULE)->FLASH_b.XIPENTURN = 0; } Transaction.ui32DeviceAddress = byteToUintBit(pTrans->addrVal & 0xFF); Transaction.ui32PauseCondition = 0; Transaction.ui32SRAMAddress = (uint32_t)pData; Transaction.ui32StatusSetClr = 0; Transaction.ui32TransferCount = len; Transaction.ui8Priority = 1; ds35m_dmaCompleteFlg = 0; ui32Status = am_hal_mspi_nonblocking_transfer(pDs35m->pHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, Bsp_Ds35m_DmaComplete, NULL); while(ds35m_dmaCompleteFlg == 0) { /*if(osKernelGetState() == osKernelRunning) { osDelay(1); } else { am_util_delay_ms(1); }*/ } // 切换回1-1-1传输模式 Bsp_Ds35m_SwitchTransMode(DS35M_TRANS_1_1_1); return ui32Status; } #endif int Ds35m_FeaturesGet(uint8_t u8Addr, uint8_t *u8Value); int Ds35m_FeaturesSet(uint8_t u8Addr, uint8_t u8Value); static uint32_t Bsp_Ds35m_Ioctl(DS35MIoctlEvent_e event, void *pConfig) { uint8_t u8TmpValue, u8TmpValue2; switch(event) { case DS35M_IOCTL_QE_ENABLE: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue); if(u8TmpValue & DS35M_FEATURE_0_MASK_QE) { return 0; } u8TmpValue |= DS35M_FEATURE_0_MASK_QE; Ds35m_FeaturesSet(DS35M_FEATURES_ADD_FEATURE_0, u8TmpValue); Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue2); if(u8TmpValue != u8TmpValue2) { // printf("event:%d error!!!\r\n", event); } break; case DS35M_IOCTL_QE_DISABLE: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue); if((u8TmpValue & DS35M_FEATURE_0_MASK_QE) == 0) { return 0; } u8TmpValue &= ~(DS35M_FEATURE_0_MASK_QE); Ds35m_FeaturesSet(DS35M_FEATURES_ADD_FEATURE_0, u8TmpValue); Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue2); if(u8TmpValue != u8TmpValue2) { //printf("event:%d error!!!\r\n", event); } break; case DS35M_IOCTL_GET_READ_STA: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_STATUS_0, &u8TmpValue); *((uint8_t *)pConfig) = u8TmpValue & DS35M_STATUS_0_MASK_OIP; break; case DS35M_IOCTL_DIS_PROTECT_BLOCK: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_PROTECT, &u8TmpValue); if((u8TmpValue & DS35M_PROTECTION_MASK_BP) == 0) { return 0; } u8TmpValue &= (~DS35M_PROTECTION_MASK_BP); Ds35m_FeaturesSet(DS35M_FEATURES_ADD_PROTECT, u8TmpValue); Ds35m_FeaturesGet(DS35M_FEATURES_ADD_PROTECT, &u8TmpValue2); if(u8TmpValue != u8TmpValue2) { //printf("event:%d error!!!\r\n", event); } break; case DS35M_IOCTL_ECC_ENABLE: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue); if(u8TmpValue & DS35M_FEATURE_0_MASK_ECC_EN) { return 0; } u8TmpValue |= DS35M_FEATURE_0_MASK_ECC_EN; Ds35m_FeaturesSet(DS35M_FEATURES_ADD_FEATURE_0, u8TmpValue); Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue2); if(u8TmpValue != u8TmpValue2) { //printf("event:%d error!!!\r\n", event); } break; case DS35M_IOCTL_ECC_DISABLE: Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue); if((u8TmpValue & DS35M_FEATURE_0_MASK_ECC_EN) == 0) { return 0; } u8TmpValue &= ~(DS35M_FEATURE_0_MASK_ECC_EN); Ds35m_FeaturesSet(DS35M_FEATURES_ADD_FEATURE_0, u8TmpValue); Ds35m_FeaturesGet(DS35M_FEATURES_ADD_FEATURE_0, &u8TmpValue2); if(u8TmpValue != u8TmpValue2) { //printf("event:%d error!!!\r\n", event); } break; } return 0; } int Ds35m_Reset(void) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_RESET; tmpTansInfo.addrByte = 0; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); return 0; } int Ds35m_WirteEnable(void) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_WRITE_ENABLE; tmpTansInfo.addrByte = 0; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); return 0; } int Ds35m_WirteDisable(void) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_WRITE_DISABLE; tmpTansInfo.addrByte = 0; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); return 0; } int Ds35m_EccEnable(void) { return Bsp_Ds35m_Ioctl(DS35M_IOCTL_ECC_ENABLE, NULL); } int Ds35m_EccDisable(void) { return Bsp_Ds35m_Ioctl(DS35M_IOCTL_ECC_DISABLE, NULL); } int Ds35m_PageReadToCache(uint32_t pageOffsetNum) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_READ_PAGE_TO_CACHE; tmpTansInfo.addrByte = 3; tmpTansInfo.addrVal = pageOffsetNum; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); return 0; } int Ds35m_ProgramExecute(uint32_t pageOffsetNum) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_PROGRAM_EXECUTE; tmpTansInfo.addrByte = 3; tmpTansInfo.addrVal = pageOffsetNum; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); return 0; } int Ds35m_FeaturesGet(uint8_t u8Addr, uint8_t *u8Value) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_GET_FEATURE; tmpTansInfo.addrByte = 1; tmpTansInfo.addrVal = u8Addr; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_RX; Bsp_Ds35m_TransSerial(&tmpTansInfo, u8Value, 1); return 0; } int Ds35m_FeaturesSet(uint8_t u8Addr, uint8_t u8Value) { ds35mTransInfo_s tmpTansInfo = {0}; tmpTansInfo.cmd = DS35M_CMD_SET_FEATURE; tmpTansInfo.addrByte = 1; tmpTansInfo.addrVal = u8Addr; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, &u8Value, 1); return 0; } int Ds35m_ReadId(uint16_t *u16DeviceId) { ds35mTransInfo_s tmpTansInfo = {0}; uint8_t tmpData[2] = {0}; tmpTansInfo.cmd = DS35M_CMD_READ_ID; tmpTansInfo.addrByte = 0; tmpTansInfo.dummyByte = 1; tmpTansInfo.direct = DS35M_TRANS_RX; Bsp_Ds35m_TransSerial(&tmpTansInfo, tmpData, 2); *u16DeviceId = (tmpData[0] << 8) & 0xFF00; *u16DeviceId |= tmpData[1]; return 0; } int Ds35m_InitConfig(void) { uint16_t u16DeviceId = 0; // reset flash chip Ds35m_Reset(); am_util_delay_ms(10); // read id // Ds35m_ReadId(&u16DeviceId); // //printf("u16DeviceId:%X\r\n", u16DeviceId); // if(u16DeviceId != BSP_DS35M_CHIP_ID) { // return -1; // } // am_util_stdio_printf("-----------------------ds35id =%d\r\n",u16DeviceId); // set QE #if(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_1) Bsp_Ds35m_Ioctl(DS35M_IOCTL_QE_DISABLE, NULL); #elif(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) Bsp_Ds35m_Ioctl(DS35M_IOCTL_QE_ENABLE, NULL); #endif // disable protect block Bsp_Ds35m_Ioctl(DS35M_IOCTL_DIS_PROTECT_BLOCK, NULL); //disable chip Ecc Ds35m_EccDisable(); return 0; } int Ds35m_Init(void) { drv_mspi_t *pDs35m = &g_mspi_dev[DS35M_MSPI_MODULE]; // config mspi pDs35m->module = DS35M_MSPI_MODULE; pDs35m->hal_config.eSpiMode = AM_HAL_MSPI_SPI_MODE_0; pDs35m->hal_config.eClockFreq = AM_HAL_MSPI_CLK_48MHZ; pDs35m->hal_config.ui8TurnAround = 8, pDs35m->hal_config.eAddrCfg = AM_HAL_MSPI_ADDR_1_BYTE; pDs35m->hal_config.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE; pDs35m->hal_config.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0; //pDs35m->hal_config.eXipMixedMode = AM_HAL_MSPI_XIPMIXED_NORMAL; //pDs35m->hal_config.bSeparateIO = true; pDs35m->hal_config.bSendInstr = true; pDs35m->hal_config.bSendAddr = true; pDs35m->hal_config.bTurnaround = true; pDs35m->hal_config.ui8ReadInstr = DS35M_CMD_READ_FROM_CACHE_4; pDs35m->hal_config.ui8WriteInstr = DS35M_CMD_PROGRAM_LOAD_4; pDs35m->hal_config.ui32TCBSize = sizeof(ds35m_DmaBuffer) / sizeof(uint32_t); pDs35m->hal_config.pTCB = ds35m_DmaBuffer; pDs35m->hal_config.scramblingStartAddr = 0; pDs35m->hal_config.scramblingEndAddr = 0; pDs35m->hal_config.ui16DMATimeLimit = 0; pDs35m->hal_config.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE; pDs35m->hal_config.ui8WriteLatency = 8; pDs35m->hal_config.bEnWriteLatency = false; if(mspi_open(pDs35m->module)) { // am_util_stdio_printf("-------------open pDs35m fail =%d\r\n",pDs35m->module); return AM_HAL_STATUS_FAIL; } // am_util_stdio_printf("-------------open pDs35m suss =%d\r\n",pDs35m->module); am_bsp_mspi_pins_enable(pDs35m->module, AM_HAL_MSPI_FLASH_QUAD_CE0); // am_hal_mspi_interrupt_clear(pDs35m->pHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR); // am_hal_mspi_interrupt_enable(pDs35m->pHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR); NVIC_EnableIRQ(mspi_interrupts[pDs35m->module]); return Ds35m_InitConfig(); } int Ds35m_Deinit(void) { Ds35m_WirteEnable(); Ds35m_Reset(); NVIC_DisableIRQ(mspi_interrupts[DS35M_MSPI_MODULE]); mspi_close(DS35M_MSPI_MODULE); return 0; } int Ds35m_ReadPageData(uint32_t pageOffsetNum, uint16_t addrOffset, uint8_t *outData, uint16_t len) { uint8_t u8TmpSta = 0; ds35mTransInfo_s tmpTansInfo = {0}; uint8_t tmpCnt = 200; Ds35m_PageReadToCache(pageOffsetNum); // am_util_delay_us(20); // ?会耗时一点时间 while(tmpCnt--) { Ds35m_FeaturesGet(DS35M_FEATURES_ADD_STATUS_0, &u8TmpSta); if((u8TmpSta & DS35M_STATUS_0_MASK_OIP) == 0) { if((u8TmpSta & DS35M_STATUS_0_MASK_ECCS) == 0x20) { // am_util_stdio_printf("read err:ecc\r\n"); return -1; } break; } } if(tmpCnt == 0) { // am_util_stdio_printf("read timeout err. page:%d",pageOffsetNum); return -2; } #if(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_1) tmpTansInfo.cmd = DS35M_CMD_READ_FROM_CACHE; #elif(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) tmpTansInfo.cmd = DS35M_CMD_READ_FROM_CACHE_4; #endif tmpTansInfo.addrByte = 2; tmpTansInfo.addrVal = addrOffset; tmpTansInfo.dummyByte = 1; tmpTansInfo.direct = DS35M_TRANS_RX; #if(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_1) Bsp_Ds35m_TransSerial(&tmpTansInfo, (uint8_t*)outData, len); #elif(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) Bsp_Ds35m_TransQuad(&tmpTansInfo, (uint8_t*)outData, len); #endif return 0; } int Ds35m_WritePageData(uint32_t pageOffsetNum, uint16_t addrOffset, uint8_t *inData, uint16_t len) { uint8_t u8TmpSta = 0; ds35mTransInfo_s tmpTansInfo = {0}; uint8_t tmpCnt = 200; Ds35m_WirteEnable(); #if(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_1) tmpTansInfo.cmd = DS35M_CMD_PROGRAM_LOAD; #elif(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) tmpTansInfo.cmd = DS35M_CMD_PROGRAM_LOAD_4; #endif tmpTansInfo.addrByte = 2; tmpTansInfo.addrVal = addrOffset; tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; #if(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_1) Bsp_Ds35m_TransSerial(&tmpTansInfo, (uint8_t*)inData, len); #elif(DS35M_WR_DATA_LINE_MODE == DS35M_WR_DATA_LINE_4) Bsp_Ds35m_TransQuad(&tmpTansInfo, (uint8_t*)inData, len); #endif // Ds35m_WirteEnable(); Ds35m_ProgramExecute(pageOffsetNum); while(tmpCnt--) { Ds35m_FeaturesGet(DS35M_FEATURES_ADD_STATUS_0, &u8TmpSta); if(u8TmpSta & DS35M_STATUS_0_MASK_P_FAIL) { Ds35m_WirteDisable(); // am_util_stdio_printf("%s:write fail 1\r\n", __func__); return -1; } else if((u8TmpSta & DS35M_STATUS_0_MASK_OIP) == 0) { break; } //am_util_delay_ms(1); // datasheet的写时间no ecc:300-600us/have ecc:400-600us } if(tmpCnt == 0) { Ds35m_WirteDisable(); // am_util_stdio_printf("%s:write fail 2\r\n", __func__); return -2; } Ds35m_WirteDisable(); return 0; } int Ds35m_ReadOnePage(uint32_t chunkNum, uint8_t *outData) { return Ds35m_ReadPageData(chunkNum, 0, outData, BSP_DS35M_BYTES_PER_PAGE_DATA); } int Ds35m_WriteOnePage(int chunkNum, uint8_t *inData) { return Ds35m_WritePageData(chunkNum, 0, inData, BSP_DS35M_BYTES_PER_PAGE_DATA); } int Ds35m_ReadSpare(uint32_t chunkNum, uint8_t *outData, uint8_t len) { return Ds35m_ReadPageData(chunkNum, BSP_DS35M_BYTES_PER_PAGE_DATA, outData, len); } int Ds35m_WriteSpare(int chunkNum, uint8_t *inData, uint8_t len) { return Ds35m_WritePageData(chunkNum, BSP_DS35M_BYTES_PER_PAGE_DATA, inData, len); } int Ds35m_EraseBlock(int blockNum) { ds35mTransInfo_s tmpTansInfo = {0}; uint8_t u8TmpSta = 0; uint8_t tmpCnt = 100; Ds35m_WirteEnable(); tmpTansInfo.cmd = DS35M_CMD_ERASE_BLOCK; tmpTansInfo.addrByte = 3; tmpTansInfo.addrVal = blockNum << 6; // 换算page地址 tmpTansInfo.dummyByte = 0; tmpTansInfo.direct = DS35M_TRANS_TX; Bsp_Ds35m_TransSerial(&tmpTansInfo, NULL, 0); while(tmpCnt--) { Ds35m_FeaturesGet(DS35M_FEATURES_ADD_STATUS_0, &u8TmpSta); if(u8TmpSta & DS35M_STATUS_0_MASK_E_FAIL) { //printf("%s:erase fail 1 :%d\r\n", __func__,blockNum); return -1; } else if((u8TmpSta & DS35M_STATUS_0_MASK_OIP) == 0) { break; } am_util_delay_ms(1); // datasheet的块擦除时间3-10ms } if(tmpCnt == 0) { // printf("%s:erase fail 2\r\n", __func__); return -2; } Ds35m_WirteDisable(); return 0; } int Ds35m_SwitchEcc(bool sw) { if(sw) { Bsp_Ds35m_Ioctl(DS35M_IOCTL_ECC_ENABLE, NULL); } else { Bsp_Ds35m_Ioctl(DS35M_IOCTL_ECC_DISABLE, NULL); } // ds35m_chipEccSw = sw; return 0; } #endif //defined(EXT_FLASH_CHIP_DS35M1GA)