mcu_hi3321_watch/tjd/driver/nandflash/ds35m1ga/ds35m1ga.c
2025-05-26 20:15:20 +08:00

770 lines
24 KiB
C

/************************************************************************************************
* Copyright (c) Fenda Technologies Co., Ltd. 2012-2020. All rights reserved.
* Description: nand flash
* Author: luca.hutianjun 029191
* Create: 2021-11-27
************************************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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)