Giter Site home page Giter Site logo

spif's Introduction

SPI FLASH Library for STM32


Please Do not Forget to get STAR, DONATE and support me on social networks. Thank you. 💖



  • I have tested on w25q64. please test other devices and tell me.

  • Install Library from https://github.com/nimaltd/STM32-PACK/raw/main/SPIF/NimaLTD.I-CUBE-SPIF.pdsc
  • Add and enable it.
  • Enable SPI and a GPIO as output-pushpull (CS pin).Connect WP and HOLD to VCC.
  • Select 'Generate peripheral initialization as a pair of .c/.h files per peripheral' on the Code Generator Tab.
  • Generate Code.
  • Define a structure of SPIF_HandleTypeDef.
  • Call SPIF_Init() and enjoy.

Watch the Video:

Video

The old Version: https://github.com/nimaltd/SPIF/archive/refs/tags/1.20.0.zip

spif's People

Contributors

nimaltd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spif's Issues

w25qxxConfig.h

hi nima, thanks for your nice lib.
why didn't you put codes of w25qxxConfig.h in the w25qxx.h file?

W25qxx_WriteDisable func never used

hi nima
i add W25qxx_WriteDisable to end of your function and in works properly
but befor w25q64 doesnt send any thing
am i right?
please describe me a little bit

W25qxx_IsEmptySector problem

in w25qxx.c file, line 464 W25qxx_Spi(0x0B); must be commented till W25qxx_IsEmptySector() function works fine!

printf->_W25QXX_PRINT

#define _W25QXX_DEBUG 0
#define _W25QXX_PRINT(...) rt_kprintf(VA_ARGS)
Is a good choice

W25qxx_WriteStatusRegister

Doesn't W25qxx_WriteStatusRegister need "write enable" before attempting to write the register?
W25qxx_WriteEnable(); in the first line

How to read and write structs

This is a fantastic library, but as i had mentioned earlier "It lacks a working example"

I want to use this library to write and read content in pages.

I have structs (they are less than 256 byes in size) i want to write and read them.

How do you suggest to do the same?

I am using 0 as starting address for the page and for every page i increment it by 100(hexa) for the next address.

uint32_t base_address = 0x00000000;
uint32_t page_offset = 0x100;

W25qxx_WritePage( (uint8_t *) &c, base_address + ( page_offset*0 ), 0, sizeof(c)); HAL_Delay(100);
W25qxx_ReadPage( (uint8_t *) &c, base_address + ( page_offset*0 ), 0, sizeof(c));

Judgment of w25q512

Hello.

W25qxx_ReadID() issues a 0x9f command to read the JEDEC ID.

The judgment of w25q512 is based on JEDEC ID.

		case 0x401A:	// 	w25q512
			w25qxx.ID=W25Q512;
			w25qxx.BlockCount=1024;
			#if (_W25QXX_DEBUG==1)
			printf("w25qxx Chip: w25q512\r\n");
			#endif
		break;

There is W25Q512JV datasheet.
https://www.winbond.com/resource-files/W25Q512JV%20SPI%20RevB%2006252019%20KMS.pdf

In page24, JEDEC ID of W25Q512JV is 4020h.

Is this a datasheet mistake?

Is it not necessary to issue B7H (Enter 4-byte address mode) for W25Q256 and W25Q512?

W25Q512 datasheet description:

Upon power up, the W25Q512JV can operate in either 3-Byte Address Mode or 4-Byte Address Mode, depending on the Non-Volatile Status Register Bit ADP (S17) setting. 
If ADP=0, the device will operate in 3-Byte Address Mode; if ADP=1, the device will operate in 4-Byte Address Mode. 
The factory default value for ADP is 0. 
To switch between the 3-Byte or 4-Byte Address Modes, “Enter 4-Byte Mode (B7h)” or “Exit 4-Byte Mode (E9h)” instructions must be used. 
The current address mode is indicated by the Status Register Bit ADS (S16). 

Read "0xFF" or "0x00"

Hi,
Thank you for this library.
I add this to my project.
My MCU is STM32F103C8T6 and I use SPI2 for connect to W25Q128.

Code:

uint8_t rBuff[256]="";
#define PAGE(_x) _x* 0x100;
#define SEC(_x)  _x* 0x1000;
#define BLK(_x)  _x* 0x10000;
//----------------------------------------------
StartAddress=SEC(7);

W25qxx_EraseSector(StartAddress);
W25qxx_WritePage("0123456789", StartAddress, 0, 10);

sprintf(rBuff,"");
W25qxx_ReadPage(rBuff, StartAddress,0,10);

But I have a problem, After call "W25qxx_ReadPage" function , the all values of "rBuff" elements is "0xFF" or "0x00" (Null).

Thanks!

spi.h

Hi, tnx for your lib.
I want use this for stm32f103, I need to "spi.h" file.
Where to get this file?
tnx

Error with w2q16jv interface

Hi,
Thank you for your support.
I am using STM32L432KC with W2q16jV. But I am not able to read the device ID. Please can you look it my code, I don't know where I am doing the mistake?

static void MX_SPI1_Init(void)
{

/* USER CODE BEGIN SPI1_Init 0 */

/* USER CODE END SPI1_Init 0 */

/* USER CODE BEGIN SPI1_Init 1 */

/* USER CODE END SPI1_Init 1 /
/
SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */

/* USER CODE END SPI1_Init 2 */

}

In main

W25qxx_Init();

Output:
w25qxx Init Begin...
w25qxx ID:0xFFFFFF
w25qxx Unknown ID

HAL_GetTick() Should not be used

bool W25qxx_Init(void)
{
w25qxx.Lock=1;
while(HAL_GetTick()<100)//here ,i maybe use other os
W25qxx_Delay(1);
after:
W25qxx_Delay(100);
is good!

Suggestion: Adding an working example would be highly helpful.

Thank you very much for helpful library, but for a beginners like me an working example would be very helpful to understand how it works.

Like the SPI.h file which needs to be replaced with the correct SPI header, i found this after trying many things and still i cant get it to work.

I am sure i am missing few things here and there but since i am a beginner an example would help a lot :)

Error while building

I am getting this type of errors that 48 errors
Description Resource Path Location Type
unknown type name 'HAL_LockTypeDef' stm32g0xx_hal_dma.h /Flash_Mem_Nuc/Drivers/STM32G0xx_HAL_Driver/Inc line 119 C/C++ Problem
Description Resource Path Location Type
unknown type name 'HAL_LockTypeDef' stm32g0xx_hal_dma.h /Flash_Mem_Nuc/Drivers/STM32G0xx_HAL_Driver/Inc line 119 C/C++ Problem

Erase Block for 32KB

Hello,

I noticed that it has only the 64 KB block erase function,

Would it be possible to create a function for 32KB?

I cloned the 64KB function and replaced the command 0xD8 with 0x52, it seems to have worked.

Sometimes it is necessary to erase a number of sectors above 32KB and below 64KB, and this function can save some execution time.

check the status of every HAL_SPI_ call

Hi,
First thanks for the drivers, I didnt check them yet by hardware, but i want to suggest some things:

  1. All the HAL_SPI_ calls has return of success\fail status, it's important to verify them.
  2. If there is RTOS, it's better to use mutex.
    What do you think about it?

How to write to 2nd block

Can you please tell how to write to 2nd block and also 2nd page or how to map them so that we can use it accordingly

W25qxx_ReadID work wrong on high speed

Hello!

I have stm32f302c8 and W25Q512 flash. If my stm chip configured to work on 8MHz (from HSI) all ok. If I change clock source to PLL and use 56MHz (x14) W25qxx_ReadID (and probably all other functions that use W25qxx_Spi()) - work wrong. For example W25qxx_ReadID receives only first byte with manufacturer ID, two next bytes are zero.

It can be fixed with increasing timeout from 100 to 150 in the call of
HAL_SPI_TransmitReceive(&_W25QXX_SPI,&Data,&ret,1,150);

JEDEC ID

Dear experts,

My own serial flash is w25q64 combine with STM32G071RB nucleo board. I try to read the JEDEC ID (0x9F). Based on datasheet, the output of JEDEC ID instruction is Manufacture ID, Memory Type, and Capacity. In fact, the module give me 0xEF0018.
Manufacture ID = 0xEF
Memory Type = 0x00
Capacity = 0x18

Based on the w25qxx.c file, the 0xEF0018 & 0x0x0000FFFF results 0x18. If the module give me 0xEF4018 then the result is 0x4018. What should I do ? to make it 0xEF4018.

Thanks & Best Regards,
Octarudin

debug %d

when debug set to 1, on cubeide it show as warning. so i change it to %ld

Sector erase not working

Hello!

I have w25q512 and sector erase function does not work for me.

I think we need to use 0x21 (Sector Erase (4KB) - with 4-Byte Address) opcode instead of 0x20 (Sector Erase (4KB)) in the W25qxx_EraseSector function, or provide 3-byte address

W25qxx_Spi(0x20);
if(w25qxx.ID>=W25Q256)
W25qxx_Spi((SectorAddr & 0xFF000000) >> 24);
W25qxx_Spi((SectorAddr & 0xFF0000) >> 16);
W25qxx_Spi((SectorAddr & 0xFF00) >> 8);
W25qxx_Spi(SectorAddr & 0xFF);

Cheers,
Youl

How to determine sector, page and block address for programming flash ?

Hi Nima... I am trying to create a file system in external flash namely w25q16. I am facing issue in writing address for block, sector and page. I am totally confused regarding the address of 15 sectors in one block . How the address assigned start , where it end??....

I have attached a screenshot regarding the block diagram of flash address system.. I want to know the address of all sectors, so that it will be easy to program that. Like I want to program sector 3 of block 2 , then what will it address.. How can I determine it??....

Screenshot (127)

WriteBytes

There is no Function to Write Bytes.It just WriteByte.

If using For(){} , it's too slow.

Could you please add a function
void W25qxx_WriteBytes(uint8_t *pBuffer, uint32_t WriteAddr_inBytes,uint32_t NumByteToWrite);

Thank you!

Please check this: "Add the GPLv3 header to the top of each source code file"

https://gist.github.com/ometa/286e626520e2eb89964e7d23e88c242f

Copyright 200X My Name

This file is part of Foobar.

Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Foobar. If not, see http://www.gnu.org/licenses/.

Use with LittleFS

Hi
Thanks for you great library. I am struggling to use your library in combination with littlefs.
Have you ever implemented the littlefs filesystem with your driver?

Data is not compared after the sector read

Hey, there
Thanks for the universal driver for the Winbond flash
I'm using the driver with W25Q16 chip, for me everything works well and I'm detecting id and able to write and read read the data
for all flash operation I have commands from serial terminal the test flow is as follow
(1) Command 'F' to Fotomat the Entire flash ->Working well
(2) Command 'W' to write 1024 bytes buffer in sector 0x030000h-> Working well
(3)Command 'R' to read the 1024 bytes buffer from sector 0x030000h-> Working well
and i can compare the buffer with memcmp with the buffer that i have wrote previously

(4) Command 'A' to write 1024 byte(different from 1st one) to sector Add. 0x030000h-> working well

(5) Command 'C' to read 1024 bytes from sector 0x030000h-> working well
i can compare the 2nd bytes buffer with the derived data at 0x010000h via memcmp

(6) Now when i apply the previous Command 'R' to read the data from 0x030000h sector then the buffer that i have devised is as same as i wrote in 2nd sector location (i.e 0x030000h) and memcmp condition gets fail

I have 2 separate buffer of 1024 bytes to read and separate buffer to read. I'm also erasing the entire sector before write

result seems same at all
Here is the snippet for my code
Can you please help me here?
Tanks

`uint8_t test[]="STM32 IS25LP016D Code test\r\n";
uint8_t temp;
uint8_t Dump_string[]="STM32 IS25LP016D SPI flash test HBDHVFHDVHFDSVHDSVHF DSNFBDHJSFVDSHVFDSVFDSVF DHNSFBDHSFHdfjbdhjfdhs dsfjdnsfjdbfdsbfhbhfdsbsddsfdsfdsfdsfdsfdsffhdbshfdvhfdvshfdvsfvdshvfdsvfdsvf hdsbfhdshfvdshjfvdshvfdhsvdhsvfhdvfhdsvhdvfsh bfvdhsfvdhsv hjdsbfhdsfh 1454 HBFHDBHFDVHJDVSHFVDSHFVDHSFVDHSVFDHS DSNFBDHJSFBHDSBFHDSBHDSBFHDBVFHDSVFH DSNJFNDJSFBDSHJBFDHSBFDHSBHDSBFDHS DSJFNDJSFBDJSBFDHSBDHBFDHSBFH DSFJBDSHJFBDHJSBHDSBFHDSBFHDS DSJFNJDSBDHJSBHDSBHDBF DJSFJDSBFJDSBFHDSBH DSDJFBDHJSBFDHSBHDSBF DSJFBDHJSBFDHSBFHDSB DJSBFDHJSBHDSBH DHJSBFHDBDHJSBF DSJFBJDSBFDHJS DJSBFJDSBFJDSBJ DMJSNFJDSBFJDSBJ DJSBFJDSBFHJDS JDSBFJDSBHJ DJSFJDSBJ JDSBFJDSBFJ HJDSBFDHJSB HDSBHFBDSH dhfbdhfdhsfhdsfhdvshfds gfvsdgdfvdgasvfgasvfgsvfgdsvfgdvgfdvsgfdvsgfvdsgvfdgsvfdgsvgdsvgfdvsgvdgfsvgdsvg hbdhfbdhfdhsbfhdsbfhdshfd sdfdhsbfdhsbfhdsbfhbdshfbhdsbfhdsbhfbdshfdhsfdhsbfhdsbfhdsbhfbdshdhbhfdshfdshfbdshfdh hfbvhdsavfghdvgfdvgfdvsgfvdsgvfdgsvfdgsvfdsvfgdsvgdsvfgdvsgfdvsgfvdsgfvdsgvdgsvgfdsvgfdvsgfvdgfvdsvdgfdvsgfvdsgfvdgsvdgsvgdsvgdvsgvdgsvtgvfdgds";
uint8_t Read_string[30];
uint32_t StartAddress=0x000000;
uint32_t rBuff[1024];
uint32_t rbuff2[1024];
uint8_t Dump_String2[1024]="Although flash memory is technically a type of EEPROM, the term EEPROM is generally used to refer specifically to non-flash EEPROM which is erasable in small blocks, typically bytes.[citation needed] Because erase cycles are slow, the large block sizes used in flash memory erasing give it a significant speed advantage over non-flash EEPROM when writing large amounts of data. As of 2013, flash memory costs much less than byte-programmable EEPROM and had become the dominant memory type wherever a system required a significant amount of non-volatile solid-state storage While EPROMs had to be completely erased before being rewritten, NAND-type flash memory may be written and read in blocks (or pages) which are generally much smaller than the entire device. NOR-type flash allows a single machine word (byte) to be written – to an erased location – or read independently Compared to NOR flash, replacing single transistors with serial-linked groups adds an extra level of addressing. Whereas NOR flash might Hello world";

/* USER CODE END 0 */

/**

  • @brief The application entry point.
  • @RetVal None
    /
    int main(void)
    {
    /
    USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals /
MX_GPIO_Init();
MX_SPI2_Init();
MX_USART3_UART_Init();
/
USER CODE BEGIN 2 */
HAL_Delay(100);
HAL_UART_Receive_IT(&huart3, (uint8_t *)aRXdata, 1);
HAL_UART_Transmit(&huart3, test, sizeof(test), 100);

printf("SPI Flash demo\r\n");

W25qxx_Init();

/* USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE */
while (1)
{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

	if(SerialAvailable==true){
			printf("--------------------------\r\n");
			printf("Command =%c\r\n", aRXdata[0]);
			printf("--------------------------\r\n");
		
		switch(aRXdata[0]){
			case ('F'):
				printf("--------------------------\r\n");
				printf("Formating Flash\r\n");
			  printf("--------------------------\r\n");
			  W25qxx_EraseChip();
			  break;
			case ('M'):
				printf("--------------------------\r\n");
				printf("Getting Menufacturer\r\n");
		  	printf("--------------------------\r\n");
			  W25qxx_GetManufacturer();
			  break;
			
			case ('W'):
				printf("--------------------------\r\n");
				printf("Writing the Flash\r\n");
			  printf("--------------------------\r\n");
			  StartAddress=0x000000;
			  W25qxx_EraseBlock(StartAddress);
			  W25qxx_WriteSector(Dump_string, StartAddress, 0, 1024);
			  break;
				
			case ('R'):
				printf("--------------------------\r\n");
				printf("Reading the Flash\r\n");
			  printf("--------------------------\r\n");
			  StartAddress=0x000000;
			  memset(rBuff, 0x00, sizeof(rBuff));
			  W25qxx_ReadSector((uint8_t *)&rBuff, StartAddress,0,1024);
			  if(memcmp(Dump_string, rBuff, 1024)==0){
					printf("\r\nBoth data identical\r\n");
				}else{
					printf("\r\nData are not identical");
				}
			  break;
			
			case ('A'):
				printf("--------------------------\r\n");
				printf("Writing the Flash\r\n");
			  printf("--------------------------\r\n");
			  StartAddress=0x030000;
			  W25qxx_EraseBlock(StartAddress);
			  W25qxx_WriteSector(Dump_String2, StartAddress, 0, sizeof(Dump_String2));
				break;
			
			case ('C'):
				printf("--------------------------\r\n");
				printf("Reading the Flash\r\n");
			  printf("--------------------------\r\n");
			  StartAddress=0x030000;
			  memset(rbuff2, 0x00, sizeof(rbuff2));
			  W25qxx_ReadSector((uint8_t *)&rbuff2, StartAddress,0,1024);
				  if(memcmp(Dump_String2, rbuff2, 1024)==0){
					printf("\r\nBoth data identical\r\n");
				}else{
					printf("\r\nData are not identical");
				}
				break;
			
			case ('G'):
				printf("Storing the Magic Number\r\n");
			  StartAddress=EXT_OTA_MAGIC_NUM_POS;
			  W25qxx_WriteSector(MAGIC_NO, StartAddress,0,4);
			  break;
			
			case ('B'):
				StartAddress=EXT_OTA_MAGIC_NUM_POS;
				printf("Reading the Magic No\r\n"); memset(rBuff, 0x00, sizeof(rBuff));
			  HAL_Delay(10);
			  W25qxx_ReadSector((uint8_t *)&rBuff, StartAddress,0,4);
				break;
			
			default:
				printf("--------------------------\r\n");
				printf("Default case!\r\n");  
			  printf("--------------------------\r\n");
		}
		SerialAvailable=false;
	}

}
/* USER CODE END 3 */

}`

Here is the logs file from my code

w25qxx Page Count: 8192
w25qxx Sector Size: 4096 Bytes
w25qxx Sector Count: 512
w25qxx Block Size: 65536 Bytes
w25qxx Block Count: 32
w25qxx Capacity: 2048 KiloBytes
w25qxx Init Done

Command =F


Formating Flash

w25qxx EraseChip Begin...
w25qxx EraseBlock done after 2994 ms!

Command =W


Writing the Flash

w25qxx EraseSector 65536 Begin...
w25qxx EraseSector done after 73 ms
+++w25qxx WriteSector:10000, Offset:0 ,Write 1024 Bytes, begin...
w25qxx WritePage:100000, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:100001, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:100002, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:100003, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
---w25qxx WriteSector Done

Command =R


Reading the Flash

+++w25qxx ReadSector:10000, Offset:0 ,Read 1024 Bytes, begin...
w25qxx ReadPage:100000, Offset:0 ,Read 256 Bytes, begin...
STM32 IS25LP016D SPI flash test HBDHVFHDVHFDSVHDSVHF DSNFBDHJSFVDSHVFDSVFDSVF DHNSFBDHSFHdfjbdhjfdhs dsfjdnsfjdbfdsbfhbhfdsbsddsfdsfdsfdsfdsfdsffhdbshfdvhfdvshfdvsfvdshvfdsvfdsvf hdsbfhdshfvdshjfvdshvfdhsvdhsvfhdvfhdsvhdvfsh bfvdhsfvdhsv hjdsbfhdsfh 1454 w25qxx ReadPage:100001, Offset:0 ,Read 256 Bytes, begin...
HBFHDBHFDVHJDVSHFVDSHFVDHSFVDHSVFDHS DSNFBDHJSFBHDSBFHDSBHDSBFHDBVFHDSVFH DSNJFNDJSFBDSHJBFDHSBFDHSBHDSBFDHS DSJFNDJSFBDJSBFDHSBDHBFDHSBFH DSFJBDSHJFBDHJSBHDSBFHDSBFHDS DSJFNJDSBDHJSBHDSBHDBF DJSFJDSBFJDSBFHDSBH DSDJFBDHJSBFDHSBHDSBF DSJFBDHJSBFDHSBFHDSB Dw25qxx ReadPage:100002, Offset:0 ,Read 256 Bytes, begin...
JSBFDHJSBHDSBH DHJSBFHDBDHJSBF DSJFBJDSBFDHJS DJSBFJDSBFJDSBJ DMJSNFJDSBFJDSBJ DJSBFJDSBFHJDS JDSBFJDSBHJ DJSFJDSBJ JDSBFJDSBFJ HJDSBFDHJSB HDSBHFBDSH dhfbdhfdhsfhdsfhdvshfds gfvsdgdfvdgasvfgasvfgsvfgdsvfgdvgfdvsgfdvsgfvdsgvfdgsvfdgsvgdsvgfdvsgvdgfsvgdsvg w25qxx ReadPage:100003, Offset:0 ,Read 256 Bytes, begin...
hbdhfbdhfdhsbfhdsbfhdshfd sdfdhsbfdhsbfhdsbfhbdshfbhdsbfhdsbhfbdshfdhsfdhsbfhdsbfhdsbhfbdshdhbhfdshfdshfbdshfdh hfbvhdsavfghdvgfdvgfdvsgfvdsgvfdgsvfdgsvfdsvfgdsvgdsvfgdvsgfdvsgfvdsgfvdsgvdgsvgfdsvgfdvsgfvdgfvdsvdgfdvsgfvdsgfvdgsvdgsvgdsvgdvsgvdgsvtgvfdgds
Both data identical

Command =A


Writing the Flash

w25qxx EraseSector 196608 Begin...
w25qxx EraseSector done after 72 ms
+++w25qxx WriteSector:30000, Offset:0 ,Write 1024 Bytes, begin...
w25qxx WritePage:300000, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:300001, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:300002, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
w25qxx WritePage:300003, Offset:0 ,Writes 256 Bytes, begin...

w25qxx WritePage done after 10 ms
---w25qxx WriteSector Done

Command =C


Reading the Flash

+++w25qxx ReadSector:30000, Offset:0 ,Read 1024 Bytes, begin...
w25qxx ReadPage:300000, Offset:0 ,Read 256 Bytes, begin...
Although flash memory is technically a type of EEPROM, the term EEPROM is generally used to refer specifically to non-flash EEPROM which is erasable in small blocks, typically bytes.[citation needed] Because erase cycles are slow, the large block sizes usew25qxx ReadPage:300001, Offset:0 ,Read 256 Bytes, begin...
d in flash memory erasing give it a significant speed advantage over non-flash EEPROM when writing large amounts of data. As of 2013, flash memory costs much less than byte-programmable EEPROM and had become the dominant memory type wherever a system requiw25qxx ReadPage:300002, Offset:0 ,Read 256 Bytes, begin...
red a significant amount of non-volatile solid-state storage While EPROMs had to be completely erased before being rewritten, NAND-type flash memory may be written and read in blocks (or pages) which are generally much smaller than the entire device. NOR-tw25qxx ReadPage:300003, Offset:0 ,Read 256 Bytes, begin...
ype flash allows a single machine word (byte) to be written – to an erased location – or read independently Compared to NOR flash, replacing single transistors with serial-linked groups adds an extra level of addressing. Whereas NOR flash might Hello world
Both data identical

Command =R


Reading the Flash

+++w25qxx ReadSector:10000, Offset:0 ,Read 1024 Bytes, begin...
w25qxx ReadPage:100000, Offset:0 ,Read 256 Bytes, begin...
Although flash memory is technically a type of EEPROM, the term EEPROM is generally used to refer specifically to non-flash EEPROM which is erasable in small blocks, typically bytes.[citation needed] Because erase cycles are slow, the large block sizes usew25qxx ReadPage:100001, Offset:0 ,Read 256 Bytes, begin...
d in flash memory erasing give it a significant speed advantage over non-flash EEPROM when writing large amounts of data. As of 2013, flash memory costs much less than byte-programmable EEPROM and had become the dominant memory type wherever a system requiw25qxx ReadPage:100002, Offset:0 ,Read 256 Bytes, begin...
red a significant amount of non-volatile solid-state storage While EPROMs had to be completely erased before being rewritten, NAND-type flash memory may be written and read in blocks (or pages) which are generally much smaller than the entire device. NOR-tw25qxx ReadPage:100003, Offset:0 ,Read 256 Bytes, begin...
ype flash allows a single machine word (byte) to be written – to an erased location – or read independently Compared to NOR flash, replacing single transistors with serial-linked groups adds an extra level of addressing. Whereas NOR flash might Hello world
Data are not identical

Bug : SPIF_WriteAddress()

Thank you for sharing your project.

I found a bug using SPIF_WriteAddress() with the address not aligned to SPIF_PAGE_SIZE.

The problem is that "remaining" is compared to SPIF_PAGE_SIZE instead of ( SPIF_PAGE_SIZE - offset).

The corrected code looks like this
image

Problem with W25qxx_WriteSector. For 4096 about 100 fail bytes

Hi,

I have problem with W25qxx_WriteSector. Below you can read my unit test with this function. Very often during writing all sector (4096 bytes) I have about 100-120 mistakes.

void W25qxx_Unit_Test2 (void)
{
int i,j;
bool match;
uint8_t u8rbuf[4096];
uint8_t u8wbuf[4096] = {0xff,};

for(i=0; i<sizeof(u8wbuf); i++) u8wbuf[i] = 0xaa;
printf("\r\nW25qxx_Unit_Test2");
W25qxx_Init();
for (i=0; i<2; i++)
	{
		printf("\r\nW25qxx_EraseSector:%d",i);
		W25qxx_EraseSector(i);
	}

printf("\r\nTEST 1 TEST 1 TEST 1");
printf("\r\nW25qxx_Write_Sector: %d", 0);
W25qxx_WriteSector(u8wbuf, 0, 0, sizeof(u8wbuf));
W25qxx_ReadSector(u8rbuf, 0, 0, sizeof(u8rbuf));
match = true;
j = 0;
for (i=0; i<sizeof(u8rbuf); i++)
	{
		if (u8rbuf[i] != 0xaa)
			{
				match = false;
				j++;
				//break;
			}
	}
if (match) printf("\r\nData1 match");
else printf("\r\nData1 does not match!!! %d",j);
printf("\r\nW25qxx_Unit_Test2 Done... Get back to work");

}

I am using W25Q128 made by Winbond. In function W25qxx_Init i hade to add code:

while (id!=0xEF7018) id = W25qxx_ReadID();

Summary: my flash doesn`t work stable. Have any idea why?

Not working in release.

I'm using stm32f103 and in release it's not initializing. I made empty project with: 36MHz core freq, in perepherial i enabled usart1, spi1, spi2 and usb.

Compatibility with the N series

Hi, for a project i'm currently working on I need a bigger capacity memory and i found the N01 chip. It has 1G-bit of memory available. Considering that both the 25n01 and the 25q use quad-spi i was wandering if I could still use your driver.

HARD FAULT HANDLER CALLED

Hi! Thank you for your support.
I am using w25q32fv with STM32F103C(BLUEPILL). After configuring w25qxxConfig.h, I have called W25qxx_Init(), but I am unable to read id. Fault analyzer is showing Hard fault error. I am attaching CubeMx configuration for SPI. Please have a look and tell me if I am doing something wrong in code or configuration for SPI.

SPI configurations:
void MX_SPI2_Init(void)
{

hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}

}

Main.c:
/* USER CODE BEGIN Header /
/
*



  • @attention
  • © Copyright (c) 2020 STMicroelectronics.

  • All rights reserved.
  • This software component is licensed by ST under BSD 3-Clause license,
  • the "License"; You may not use this file except in compliance with the
  • License. You may obtain a copy of the License at:
  •                    opensource.org/licenses/BSD-3-Clause
    

/
/
USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------/
/
USER CODE BEGIN Includes /
#include "w25qxx.h"
/
USER CODE END Includes */

/* Private typedef -----------------------------------------------------------/
/
USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------/
/
USER CODE BEGIN PD /
/
USER CODE END PD */

/* Private macro -------------------------------------------------------------/
/
USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------/
void SystemClock_Config(void);
/
USER CODE BEGIN PFP /
extern void initialise_monitor_handles(void);
/
USER CODE END PFP */

/* Private user code ---------------------------------------------------------/
/
USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**

  • @brief The application entry point.
  • @RetVal int
    /
    int main(void)
    {
    /
    USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

W25qxx_Init();
/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals /
MX_GPIO_Init();
MX_SPI2_Init();
/
USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE /
while (1)
{
/
USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */
}

/**

  • @brief System Clock Configuration
  • @RetVal None
    */
    void SystemClock_Config(void)
    {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the CPU, AHB and APB busses clocks
/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/
* Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

  • @brief This function is executed in case of error occurrence.
  • @RetVal None
    /
    void Error_Handler(void)
    {
    /
    USER CODE BEGIN Error_Handler_Debug /
    /
    User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**

  • @brief Reports the name of the source file and the source line number
  •     where the assert_param error has occurred.
    
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @RetVal None
    */
    void assert_failed(uint8_t file, uint32_t line)
    {
    /
    USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *END OF FILE/
OUTPUT:
w25qxx Init Begin...

(After this hard fault handler is called.)
Hard Fault handler called
cubeMx configuration

SPIF_WritePage corrupting source buffer

Hi all,

I experience that SPIF_WritePage function corrupts the source buffer (other write operations will do so aswell).
This is due to the fact that SPIF_WriteFn calls SPIF_TransmitReceive() which in turn sets its rx and tx buffer to source buffer, and by this corrupts the source buffer.
Wouldn't it be better to call a transmit only function here?

Best regards.

Wolf

Library don't work

Hello! I wanted to use this library to create the Mass Storage Device, but when I insert all the necessary functions (initialization, reading, writing, erasing) the device is not recognized on the PC - the functions simply are not executed. I turned off the use of freeTROS and debug mode, and yet nothing works and the functions are not performed. With what it can be connected?
I use stm32f103c8, flash-chip is W25Q64
Thanks for the help!

Can i get a full example of it?

Hello,
I need to configure with Quad SPI my W25Q256JVEIQ chip.
I read the readme and i think i understood all of it. However, i don't know where to insert the W25qxx_Init() function, i think after the general initialization like

static void MX_QUADSPI_Init(void)
{

  /* USER CODE BEGIN QUADSPI_Init 0 */

  /* USER CODE END QUADSPI_Init 0 */

  /* USER CODE BEGIN QUADSPI_Init 1 */

  /* USER CODE END QUADSPI_Init 1 */
  /* QUADSPI parameter configuration*/
  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 255;
  hqspi.Init.FifoThreshold = 1;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
  hqspi.Init.FlashSize = 1;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN QUADSPI_Init 2 */
  W25qxx_Init();
  /* USER CODE END QUADSPI_Init 2 */

}

but, as you can see i don't know the right parameters to put in this initial configuration.
I need to use it for touchgfx external flash. Is this initialization sufficient for this purpose?

Read no work?

Hi i'm try use this code with w25q128 and stm32f107rc and test this -

uint8_t pbuf[256];

pbuf[0] = 0xee;

W25qxx_EraseSector(0);

W25qxx_WritePage(pbuf,0,0,0);

W25qxx_ReadByte(pbuf,0);

And always i'm get pbuf[0] = 0x00 after read data from flash

W25qxx_WriteSector

Hi,
I found a problem with W25qxx_WriteSector. When NumByteToWrite_up_to_SectorSize is 0, the actual number of bytes to be written is PageSize minus OffsetInByte.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.