#include "stm32f1xx_hal.h"
#include "cmsis_os.h"
#include "main.h"
#include "MX25LXX.h"
/*****************************************************/
extern SPI_HandleTypeDef hspi1;
#define MX25XX_SPI hspi1
#define MX25LxxCS(x) HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,x)
#define MX25LxxLockEnable 1
#define MX25Lxx4BytesMode 1
/*****************************************************/
/******************flash cmd *************************/
#define COMMAND_WREN 0x06
#define COMMAND_WRDI 0x04
#define COMMAND_RDSR 0x05
#define COMMAND_WRSR 0x01
#define COMMAND_READ 0x03
#define COMMAND_FREAD 0x0B
#define COMMAND_FREAD4B 0x0C
#define COMMAND_READ4B 0x13
#define COMMAND_PP4B 0x12
#define COMMAND_SE4B 0x21
#define COMMAND_EN4B 0xB7
#define COMMAND_RDSCUR 0x2B
#define COMMAND_RSTQIO 0xF5
#define COMMAND_WRITE 0x02
#define COMMAND_RDID 0x9F
#define COMMAND_SE 0x20 //sector erase
#define COMMAND_BE 0x52 //block erase
#define COMMAND_CE 0x60 //chip erase
#define COMMAND_RDCR 0x15
#define STATUS_WIP 0b00000001
#define STATUS_WEL 0b00000010
#define STATUS_BP0 0b00000100
#define STATUS_BP1 0b00001000
#define STATUS_BP2 0b00010000
#define STATUS_BP3 0b00100000
#define STATUS_RES 0b01000000
#define STATUS_SWRD 0b10000000
#define CONFIG_4BYTE 0b00100000
#define RDSCUR_P_FAIL 0b00100000
#define RDSCUR_E_FAIL 0b01000000
#define DUMMY 0xFF
/******************end flash cmd *********************/
#if MX25LxxLockEnable
static osMutexId MX25lxxMutex;
#define MX25LxxLock() osMutexWait(MX25lxxMutex , osWaitForever)
#define MX25LxxUnLock() osMutexRelease(MX25lxxMutex)
#else
#define MX25LxxLock()
#define MX25LxxUnLock()
#endif
uint8_t MX25LxxConfigeRegister();
uint8_t MX25LxxStatus();
uint8_t MX25LxxRSTQIO();
int MX25LxxWriteEnable();
#if MX25Lxx4BytesMode
static int MX25LxxEnter4B();
#endif
static int MX25LxxWaitForDecieReady()
{
do{
if (IS_MASK_CLEAR(MX25LxxStatus(), STATUS_WIP)) //wait write done
break;
}while(1);
return 0;
}
#if MX25Lxx4BytesMode
static int MX25LxxEnter4B()
{
uint8_t d[2] = {COMMAND_EN4B,0};
MX25LxxLock() ;
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
MX25LxxCS(1);
MX25LxxUnLock();
MX25LxxWaitForDecieReady();
return 0;
}
#endif
int MX25LxxInit()
{
#if MX25LxxLockEnable
/* Create Mutex lock */
osMutexDef(MX25MUTEX);
/* Create the Mutex used by the two threads */
MX25lxxMutex = osMutexCreate(osMutex(MX25MUTEX));
#endif
#if MX25Lxx4BytesMode
MX25LxxEnter4B();
if(IS_MASK_SET( MX25LxxConfigeRegister(), CONFIG_4BYTE) )
return 0;
//MX25LxxRSTQIO();
return -1;
#else
return 0;
#endif
}
/**
*Read chip id
*return chip id
**/
uint32_t MX25LxxReadChipID()
{
uint8_t d[4] = {COMMAND_RDID,0};
MX25LxxLock();
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
HAL_SPI_Receive(&MX25XX_SPI, d, 3, 0xff);
MX25LxxCS(1);
MX25LxxUnLock();
return (d[0] << 16) | (d[1] << 8) | d[2];
}
uint8_t MX25LxxConfigeRegister()
{
uint8_t d[2] = {COMMAND_RDCR,0};
MX25LxxLock();
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
HAL_SPI_Receive(&MX25XX_SPI, d, 1, 0xff);
MX25LxxCS(1);
MX25LxxUnLock();
return d[0];
}
/**
* RDSCUR register
* return RDSCUR_P_FAIL RDSCUR_E_FAIL
**/
uint8_t MX25LxxRDSCUR()
{
uint8_t d[2] = {COMMAND_RDSCUR,0};
MX25LxxLock();
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
HAL_SPI_Receive(&MX25XX_SPI, d, 1, 0xff);
MX25LxxCS(1);
MX25LxxUnLock();
return d[0];
}
/**
* Read flash Status
* return status regiter STATUS_WIP STATUS_WEL STATUS_XXX
**/
uint8_t MX25LxxStatus()
{
uint8_t d[2] = {COMMAND_RDSR,0};
MX25LxxLock();
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
HAL_SPI_Receive(&MX25XX_SPI, d, 1, 0xff);
MX25LxxCS(1);
MX25LxxUnLock();
return d[0];
}
int MX25LxxWriteEnable()
{
uint8_t d[2] = {COMMAND_WREN,0};
resend:
MX25LxxLock();
MX25LxxCS(0);
HAL_SPI_Transmit(&MX25XX_SPI,d,1,0xff);
MX25LxxCS(1);
MX25LxxUnLock();
#if 0
goto end;
#endif
if( IS_MASK_SET(MX25LxxStatus(),STATUS_WEL))
{
goto end;
}
goto resend;
end:
return 0;
}
int MX25LxxWrite256(const uint8_t *buff, uint32_t address )
{
#if MX25Lxx4BytesMode
uint8_t d[5] = {COMMAND_WRITE ,(uint8_t)(address >> 24) ,(uint8_t)(address >> 16 ), (uint8_t)(address >> 8), (uint8_t)address };
#else
uint8_t d[5] = {COMMAND_WRITE ,(uint8_t)(address >> 16), (uint8_t)(address >> 8), (uint8_t)address };
#endif
MX25LxxWriteEnable();
MX25LxxLock();
MX25LxxCS(0);
#if MX25Lxx4BytesMode
HAL_SPI_Transmit(&MX25XX_SPI,d,5,0xff); //send command and address
#else
HAL_SPI_Transmit(&MX25XX_SPI,d,4,0xff);
#endif
HAL_SPI_Transmit(&MX25XX_SPI,buff,256,0xff);
MX25LxxCS(1);
MX25LxxUnLock();
MX25LxxWaitForDecieReady();
return 0;
}
int MX25LxxWritePage(const uint8_t *buff,uint32_t address)
{
int i = 0;
MX25LxxErasePage(address);
for (i = 0; i < 16; i++)
{
MX25LxxWrite256(&buff[i*256],address + i*256);
}
return 0;
}
int MX25LxxWriteSectors(const uint8_t *buff, uint32_t sector, uint32_t count)
{
int i=0;
for (i = 0; i < count; i++)
{
MX25LxxWritePage(buff,sector*MX25_PAGE_SIZE + i*MX25_PAGE_SIZE);
}
return 0;
}
/**
* 4K for each page
**/
int MX25LxxErasePage(uint32_t address)
{
#if MX25Lxx4BytesMode
uint8_t d[5] = {COMMAND_SE , (uint8_t)(address >> 24), (uint8_t)(address >> 16 ), (uint8_t)(address >> 8), (uint8_t)address };
#else
uint8_t d[5] = {COMMAND_SE , (uint8_t)(address >> 16), (uint8_t)(address >> 8), (uint8_t)address };
#endif
MX25LxxWriteEnable();
MX25LxxLock();
MX25LxxCS(0);
#if MX25Lxx4BytesMode
HAL_SPI_Transmit(&MX25XX_SPI,d,5,0xff);
#else
HAL_SPI_Transmit(&MX25XX_SPI,d,4,0xff);
#endif
MX25LxxCS(1);
MX25LxxUnLock();
MX25LxxWaitForDecieReady();
return 0;
}
int MX25LxxRead(uint8_t *buff,uint32_t sector,uint32_t count)
{
uint32_t address = sector*MX25_PAGE_SIZE;
int i = 0;
#if MX25Lxx4BytesMode
uint8_t d[6] = {COMMAND_FREAD,(uint8_t)(address >> 24), (uint8_t)(address >> 16 ), (uint8_t)(address >> 8),(uint8_t)address,DUMMY};
#else
uint8_t d[6] = {COMMAND_FREAD,(uint8_t)(address >> 16), (uint8_t)(address >> 8),(uint8_t)address,DUMMY,DUMMY};
#endif
//MX25LxxWaitForDecieReady();
MX25LxxLock();
MX25LxxCS(0);
#if MX25Lxx4BytesMode
HAL_SPI_Transmit(&MX25XX_SPI,d,6,0xff);
#else
HAL_SPI_Transmit(&MX25XX_SPI,d,5,0xff); //send command and address
#endif
for(i = 0; i < count; i++)
HAL_SPI_Receive(&MX25XX_SPI, &buff[i*MX25_PAGE_SIZE], MX25_PAGE_SIZE, 0xff);
MX25LxxCS(1);
MX25LxxUnLock();
return 0;
}
/*********************************start DMA **********************************************/
enum {
TRANSFER_WAIT,
TRANSFER_COMPLETE,
TRANSFER_ERROR
};
static __IO uint32_t wTransferState = TRANSFER_WAIT;
extern DMA_HandleTypeDef hdma_spi1_rx;
#define MX25XX_SPI_DMA_RX hdma_spi1_rx
/**
* @brief TxRx Transfer completed callback.
* @param hspi: SPI handle
* @note This example shows a simple way to report end of DMA TxRx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
/* Turn LED2 on: Transfer in transmission/reception process is complete */
wTransferState = TRANSFER_COMPLETE;
}
int MX25LxxReadDMA(uint8_t *buff,uint32_t sector,uint32_t count)
{
uint32_t address = sector*MX25_PAGE_SIZE;
#if MX25Lxx4BytesMode
uint8_t d[6] = {COMMAND_FREAD,(uint8_t)(address >> 24), (uint8_t)(address >> 16 ), (uint8_t)(address >> 8),(uint8_t)address,DUMMY};
#else
uint8_t d[6] = {COMMA