/*================================================================ Copyright (c) 2022, Quectel Wireless Solutions Co., Ltd. All rights reserved. Quectel Wireless Solutions Proprietary and Confidential. =================================================================*/ #include #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]); }