242 lines
7.2 KiB
C
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]);
|
|
}
|
|
|