cancel
Showing results for 
Search instead for 
Did you mean: 

Writing in Eprom AT25640 with STM32F429 with SPI

SGasp.1
Senior

Hi forum I am working with micro STM32F429 and I want to read and write an external memory using SPI.

I am following the instructions on the datasheet but sometimes I am able to write sometimes it fails and I am not able to understand why..

Here there is the code of the init of the SPI

void SPI1_Init(void)
{
	/* PA2 = CS,PA5 = SCK, PA7 = SPI1_MOSI */
	GPIOA -> MODER |= ((GPIOA -> MODER) &  0xFFFF33CF) | 0x00008810; 	// AF Function: XX,AF5,AF5
	GPIOA -> OTYPER |= ((GPIOA -> OTYPER) & 0xFFFFFF5B);				// Push-Pull
	GPIOA -> OSPEEDR |= ((GPIOA -> OSPEEDR) & 0xFFFF3FFC) | 0x0000CC30; // Very High Speed
	GPIOA -> PUPDR |= ((GPIOA -> PUPDR) & 0xFFFF33CF);					// No Pull-Up
	GPIOA -> AFR[0] |= ((GPIOA -> AFR[0]) & 0x0F0FF0FF) | 0x50500000;	//
//	GPIOA -> AFR[1] |= ((GPIOA -> AFR[1]) & 0xFFFFFFFF) | 0x00000000;	//
 
	/* PB12 = WRP, PB4 = SPI1_MISO */
	GPIOB -> MODER |= ((GPIOB -> MODER) & 0xFCFFFCFF ) | 0x01000200; 	// AF Function XX,AF5
	GPIOB -> OTYPER |= ((GPIOB -> OTYPER) & 0xFFFFEFEF);				// Push-Pull
	GPIOB -> OSPEEDR |= ((GPIOB -> OSPEEDR) & 0xFCFFFCFF) | 0x03000300;	// Very High Speed
	GPIOB -> PUPDR |= ((GPIOB -> PUPDR) & 0xFCFFFCFF);					// No Pull-Up
	GPIOB -> AFR[0] |= ((GPIOB -> AFR[0]) & 0xFFF0FFFF) | 0x00050000;	//
	GPIOB -> AFR[1] |= ((GPIOB -> AFR[1]) & 0xFFF0FFFF);	//
 
	RCC-> APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1 Peripheral Clock Enable
 
    HAL_NVIC_SetPriority(SPI1_IRQn, 7, 2);
 
    /* Enable the TIMx global Interrupt */
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
 
    GPIOB -> ODR |= 0x1000; // WP = 1 : PB12
	GPIOA -> ODR |= 0x0004; // CS = 1 : PA2
    SPI1 -> CR1 = 0x0300;
    // clock / 16, bidirectional, output enable, LSB first, spi1 enable, master selection
    SPI1 -> CR1 |= (SPI_CR1_BR_1 | SPI_CR1_BR_2 | SPI_CR1_BIDIOE); // | SPI_CR1_SPE | SPI_CR1_MSTR); // | SPI_CR1_BIDIMODE | SPI_CR1_LSBFIRST);
    SPI1 -> CR1 |= SPI_CR1_MSTR;
    SPI1 -> CR1 |= SPI_CR1_SPE;
}
void SPI1_IRQHandler(void)
{
	volatile unsigned int IIR;
 
	// Checks whether the SPI1 interrupt has occurred or not
	IIR = SPI1 -> SR;
	if(IIR & SPI_SR_RXNE){ // received data
		buf_ee_rd[n_mem] = SPI1 -> DR;
		SPI1 -> SR &= ~SPI_SR_RXNE; // Reset Interrupt Flag
	}
	else;
	if(IIR & SPI_SR_TXE){ // transmit data
		SPI1 -> SR &= ~SPI_SR_TXE; // Reset Interrupt Flag
		if(++n_mem < n_max_byte){
			SPI1 -> DR = *pun_dati; /* buf_ee_wr[n_mem]; */
			pun_dati++;
		}
		else{
		    SPI1 -> CR2 &= ~SPI_CR2_TXEIE; // TX Interrupt Enable
		}
	}
	else;
}

And here there are the functions that I am using for writing

void ee_wr_codice2()
{
	GPIOA -> ODR |= 0x0004 ; //WP = 1 : EE non protetta in scrittura  GIOM
	codice[0].word = codice2;
	ee_wr_en();
	buf_ee_wr[1] = 0x1f; /* code addr hi */
	buf_ee_wr[2] = 0xfc; /* code addr lo */
	buf_ee_wr[3] = codice[0].byte[0];
	buf_ee_wr[4] = codice[0].byte[1];
	n_max_byte = 5;
	ee_wr_byte();
	sFLASH_WaitForWriteEnd(); // GIOM
	GPIOA -> ODR &= ~0x0004; //WP = 0 : EE protetta in scrittura GIOM */
}

where

void ee_wr_en()
{
	GPIOA -> ODR &= ~PA2; // CS = 0
	buf_ee_wr[0] = 0x06; /* write enable */
	pun_dati = buf_ee_wr;
	n_mem = 0;
	n_max_byte = 1;
	SPI1 -> DR = *pun_dati;
	pun_dati++;
    SPI1 -> CR2 |= SPI_CR2_TXEIE; // TX Interrupt Enable
	while((SPI1 -> SR) & SPI_SR_BSY);
	GPIOA -> ODR |= PA2; // CS = 1
}

and

void ee_wr_byte()
{
	GPIOA -> ODR &= ~PA2; // CS = 0
	buf_ee_wr[0] = 0x02; /* write data */
	pun_dati = buf_ee_wr;
	n_mem = 0;
	SPI1 -> DR = *pun_dati;
	pun_dati++;
    SPI1 -> CR2 |= SPI_CR2_TXEIE; // TX Interrupt Enable
	while((SPI1 -> SR) & SPI_SR_BSY);
	GPIOA -> ODR |= PA2; // CS = 1
}

moreover

void sFLASH_WaitForWriteEnd(void)  /
{
 	unsigned char  flashstatus = 0;
	do
	{
		flashstatus = sFLASH_StatusReg();
	}while(flashstatus & 0x01); /* Write in progress */
 
}

and last

unsigned char sFLASH_StatusReg(void) // GIOM
{
 
 unsigned char tmp;
  GPIOA -> ODR &= ~PA2; // CS = 0
  buf_ee_wr[0] = 0x05; /* Read Status Register instruction  */
  pun_dati = buf_ee_wr;
  n_mem = 0;
  n_max_byte = 1;
  SPI1 -> DR = *pun_dati;
  pun_dati++;
  SPI1 -> CR2 |= SPI_CR2_TXEIE; // TX Interrupt Enable
  while((SPI1 -> SR) & SPI_SR_BSY);
  tmp = buf_ee_rd[0];  // GIOM68 va bene indice 0 ???
  GPIOA -> ODR |= PA2; // CS = 1
 
  return(tmp);
}

I am wondering if it is iìok the code since in this project they decided to not use the HAL.

In the attachements you can find al the connection of the eprom with the pin of the mcu.

Thanks a lot if you have time to watch and help

2 REPLIES 2

>>..the code since in this project they decided to not use the HAL.

So is it your code, or someone else's?

If it's not working for you, and you're having to debug it, at some point it might be easier to implement it cleanly, yourself.

It does seem to use a mishmash of concepts.

Uses interrupts, but still blocks.

Weird use of semi-colons on the else statements..

I might watch the CS signals vs clock/data. Make sure the IO completes to the pin, probably should be using BSRR, and __DMB() memory barrier so the write buffers flush predictably.

Perhaps use scope, or logic analyzer, triggered when you see failure.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
SGasp.1
Senior

Hi Tesla thanks for the answer..

The code it is not mine they asked the hep for finding the bug.

I would use the hal lib if I could but they decided to avoid them ..

I thinks HAL_SPI_transmit() in blocking mode shoud do the job quite well

I found someone complaining the same kind of problem ..

https://forum.arduino.cc/t/having-trouble-with-a-at25640b-eeprom/170756

They fixed with a delay between the wren command and the command for writing..

But They use total different functions..

Except to watch the signals do you see something strange?

Thanks