2022-05-20 05:39 AM
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
2022-05-20 06:42 AM
>>..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.
2022-05-20 06:51 AM
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