Files
banban/ql-kernel/threadx/nor_flash/quec_spi_nor.c
T

242 lines
7.2 KiB
C

/*================================================================
Copyright (c) 2022, Quectel Wireless Solutions Co., Ltd. All rights reserved.
Quectel Wireless Solutions Proprietary and Confidential.
=================================================================*/
#include <string.h>
#include "ssp_host.h"
#include "quec_spi_nor.h"
#include "quec_rtos.h"
#include "quec_debug.h"
#include "loadTable.h"
extern unsigned int SPINOR_Wipe(int sspport);
extern unsigned int SPINOR_EraseByBlock(int sspport, unsigned int Address, unsigned int Size);
extern unsigned int SPINOR_EraseBySector(int sspport, unsigned int Address, unsigned int Size);
extern unsigned int SPINOR_Read(int sspport, unsigned int FlashOffset, unsigned int Buffer, unsigned int Size);
extern unsigned int SPINOR_Write(int sspport, unsigned int Address, unsigned int Buffer, unsigned int Size);
extern void SPINOR_ReadId(int sspport, unsigned int *pID);
extern int InitializeSPIDevice(int sspport, int sspclock);
extern unsigned int SPINOR_Read_PIO(int sspport, unsigned int FlashOffset, unsigned int Buffer, unsigned int Size);
/********************************
变量ql_spi_pin_selflag功能描述
0:默认配置,SSP0使用GPIO16~19引脚
1: SSP0使用GPIO33~36
2: SSP2使用GPIO33~36
3: SSP2使用GPIO12~15
4: SSP1使用GPIO4~7
...:待新的配置
**********************************/
extern int quec_spi_pin_selflag;
unsigned int quec_spi_pin_select(int port)
{
quec_spi_pin_selflag = port;
if(port == 1)//33~36 ssp0
{
return 0;
}
else if((port == 0)||(port == 2))
{
return port;
}
else if(port == 4)
{
return 1;
}
else//12~15 for SSP2
{
return 2;
}
}
#define SPINOR_PIN_REMAP(A) quec_spi_pin_select(A)
//初始化SPI FLASH的IO Quec_Spi_Nor_Init
unsigned int QUEC_SPI_NOR_Init(int port, int clk)
{
int ret = 0;
unsigned char *id;
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
switch (clk)
{
case _APBC_SSP_FNCLKSEL_6_5MHZ:
case _APBC_SSP_FNCLKSEL_13MHZ:
case _APBC_SSP_FNCLKSEL_3_25MHZ:
case _APBC_SSP_FNCLKSEL_1_625MHZ:
case _APBC_SSP_FNCLKSEL_812_5KHZ:
ret = InitializeSPIDevice(port, 0x0); //SSP_CLOCK_13M
break;
case _APBC_SSP_FNCLKSEL_26MHZ:
ret = InitializeSPIDevice(port, 0x1); //SSP_CLOCK_26M
break;
case _APBC_SSP_FNCLKSEL_52MHZ:
default:
ret = InitializeSPIDevice(port, 0x2); //SSP_CLOCK_52M
break;
}
if (ret != 0)
{
quec_debug_print_uart("[%s][%d]InitializeSPIDevice failed \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
return Retval;
}
//读取芯片ID
//返回值如丿
//void W25QXX_ReadID(u8 *id)
unsigned char *QUEC_SPI_NOR_ReadID(int port)
{
unsigned int flash_id = 0;
static unsigned char id[3] = {0};
port = SPINOR_PIN_REMAP(port);
memset(id, 0, sizeof(id));
SPINOR_ReadId(port, &flash_id);
id[0] = flash_id & 0xFF;
id[1] = (flash_id>>8) & 0xFF;
id[2] = (flash_id>>16) & 0xFF;
return id;
}
//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储匿
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节敿最夿5535)
static char buffer[4096] = {0};
static int i;
unsigned int QUEC_SPI_NOR_Read(int port, unsigned char* pBuffer,unsigned int ReadAddr,unsigned int NumByteToRead)
{
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
if (NULL == pBuffer)
{
quec_debug_print_uart("[%s][%d]invalid param, pBuffer is NULL \r\n", __func__, __LINE__);
return QUEC_SSPBufferParamInvalidError;
}
Retval = SPINOR_Read(port, ReadAddr, (unsigned int)pBuffer, NumByteToRead);
return Retval;
}
//读取SPI FLASH
//在指定地址开始读取指定长度的数据(fifo模式)
//pBuffer:数据存储匿
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节敿最夿5535)
unsigned int QUEC_SPI_NOR_Read_PIO(int port, unsigned char* pBuffer,unsigned int ReadAddr,unsigned int NumByteToRead)
{
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
if (NULL == pBuffer)
{
quec_debug_print_uart("[%s][%d]invalid param, pBuffer is NULL \r\n", __func__, __LINE__);
return QUEC_SSPBufferParamInvalidError;
}
Retval = SPINOR_Read_PIO(port, ReadAddr, (unsigned int)pBuffer, NumByteToRead);
return Retval;
}
//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储匿
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节敿最夿5535)
unsigned int QUEC_SPI_NOR_Write(int port, unsigned char* pBuffer,unsigned int WriteAddr,unsigned int NumByteToWrite)
{
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
if (NULL == pBuffer)
{
quec_debug_print_uart("[%s][%d]invalid param, pBuffer is NULL \r\n", __func__, __LINE__);
return QUEC_SSPBufferParamInvalidError;
}
SPINOR_Write(port, WriteAddr, (unsigned int)pBuffer, NumByteToWrite);
return Retval;
}
//擦除整个芯片
//等待时间超长...
unsigned int QUEC_SPI_NOR_Erase_Chip(int port)
{
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
Retval = SPINOR_Wipe(port);
return Retval;
}
//擦除一个扇匿
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个山区的最少时闿150ms
unsigned int QUEC_SPI_NOR_Erase_Sector(int port, unsigned int Dst_Addr)
{
unsigned int Retval = 0;
port = SPINOR_PIN_REMAP(port);
if ((port < EXTERNAL_NORFLASH_SSP0) || (port > EXTERNAL_NORFLASH_SSP2))
{
quec_debug_print_uart("[%s][%d]invalid port \r\n", __func__, __LINE__);
return QUEC_SSPPortInvalidError;
}
Retval = SPINOR_EraseBySector(port, Dst_Addr, 1);
return Retval;
}
void QUEC_SPI_NOR_Tese(void)
{
unsigned char tx_buf[300] = {0};
unsigned char rx_buf[300] = {0};
int port_index = 2;
memset(tx_buf, '2', 256);
memset(rx_buf, '0', 256);
QUEC_SPI_NOR_Init(port_index, _APBC_SSP_FNCLKSEL_1_625MHZ);
QUEC_SPI_NOR_Erase_Chip(port_index);
//QUEC_SPI_NOR_Erase_Sector(port_index,0x1000);
//quec_debug_print_uart("write \r\n");
//QUEC_SPI_NOR_Write_NoCheck(port_index, tx_buf, 0x1000, 1);
QUEC_SPI_NOR_Write(port_index, tx_buf, 0x1000, 256);
//quec_debug_print_uart("read \r\n");
QUEC_SPI_NOR_Read(port_index, rx_buf, 0x1000, 256);
quec_debug_print_uart("read: 0x%02x 0x%02x\r\n", rx_buf[0], rx_buf[255]);
}