cancel
Showing results for 
Search instead for 
Did you mean: 

Regarding FLASH Writing to the STM32F410

shank
Associate III

I have a question about writing to the STM32F410's FLASH.
I'm creating a program to write data received via USART to FLASH, but it's not working correctly.
The writing to FLASH itself is happening, but the written data differs from what I expect.
This different written data contains a large number of “0xAA” values that are not present in the original data.
Do you know what might be causing this phenomenon?

void FLASH_UNLOCK(){
  
      while ((FLASH->SR & FLASH_SR_BSY) != 0){
      }
      if ((FLASH->CR & FLASH_CR_LOCK) != 0)
      {
        FLASH->KEYR = 0x45670123; 
        FLASH->KEYR = 0xCDEF89AB;
      }
}


void FLASH_DELETE(uint32_t address){
  
      while ((FLASH->SR & FLASH_SR_BSY) != 0){
      }
      
      FLASH->CR |= FLASH_CR_SER;
      FLASH->CR |= (FLASH_CR_SNB & 0x8);
      FLASH->CR |= FLASH_CR_STRT;
      while ((FLASH->SR & FLASH_SR_BSY) != 0){
      }
      
      if ((FLASH->SR & FLASH_SR_EOP) != 0)
      {
      FLASH->SR |= FLASH_SR_EOP;
      }
      else
      {
      }
      FLASH->CR &= ~FLASH_CR_SER;
}


void FLASH_Write(uint32_t address, uint8_t data){
  
      while ((FLASH->SR & FLASH_SR_BSY) != 0){
      }
      FLASH->CR |= FLASH_CR_PG; 

      *(__IO uint8_t*)address = data;
      
      while ((FLASH->SR & FLASH_SR_BSY) != 0){
      }
      
      if ((FLASH->SR & FLASH_SR_EOP) != 0)
      {
      FLASH->SR |= FLASH_SR_EOP;
      }
      else
      {
      }
      FLASH->CR &= ~FLASH_CR_PG;
}

 

const uint32_t main_address = 0x08004000; //sector1 start 
const uint32_t end_adress = 0x08007FFF; //sector1  end 
const uint32_t next_code = 0x00000100; // 256B=0x100B

void binary_write(){
   uint16_t i;
 
  for(i=0;i<256;i++){
     bin_data[i] = send_data[i+0x9];
  }
  
  switch(send_data[8]){
    
          case 1:  re_address = main_address + next_code * 0; break; //0x08004000~0x080040F0
          case 2:  re_address = main_address + next_code * 1; break; //0x08004100~0x080041F0
          case 3:  re_address = main_address + next_code * 2; break;
          case 4:  re_address = main_address + next_code * 3; break;
          case 5:  re_address = main_address + next_code * 4; break;
          case 6:  re_address = main_address + next_code * 5; break;
          case 7:  re_address = main_address + next_code * 6; break;
          case 8:  re_address = main_address + next_code * 7; break;
          case 9:  re_address = main_address + next_code * 8; break;
          case 10: re_address = main_address + next_code * 9; break;
          case 11: re_address = main_address + next_code * 10; break;
          case 12: re_address = main_address + next_code * 11; break;
          case 13: re_address = main_address + next_code * 12; break;
          case 14: re_address = main_address + next_code * 13; break;
          case 15: re_address = main_address + next_code * 14; break;
          case 16: re_address = main_address + next_code * 15; break;
          case 17: re_address = main_address + next_code * 16; break;
          case 18: re_address = main_address + next_code * 17; break;
          case 19: re_address = main_address + next_code * 18; break;
          case 20: re_address = main_address + next_code * 19; break;
          case 21: re_address = main_address + next_code * 20; break;
          case 22: re_address = main_address + next_code * 21; break;
          case 23: re_address = main_address + next_code * 22; break;
          case 24: re_address = main_address + next_code * 23; break;
          case 25: re_address = main_address + next_code * 24; break;
          case 26: re_address = main_address + next_code * 25; break;
          case 27: re_address = main_address + next_code * 26; break;
          case 28: re_address = main_address + next_code * 27; break;
          case 29: re_address = main_address + next_code * 28; break;
          case 30: re_address = main_address + next_code * 29; break;
          case 31: re_address = main_address + next_code * 30; break;
          case 32: re_address = main_address + next_code * 31; break;
          case 33: re_address = main_address + next_code * 32; break;
          case 34: re_address = main_address + next_code * 33; break;
          case 35: re_address = main_address + next_code * 34; break;
          case 36: re_address = main_address + next_code * 35; break;
          case 37: re_address = main_address + next_code * 36; break;
          case 38: re_address = main_address + next_code * 37; break;
          case 39: re_address = main_address + next_code * 38; break;
          case 40: re_address = main_address + next_code * 39; break;
          case 41: re_address = main_address + next_code * 40; break;
          case 42: re_address = main_address + next_code * 41; break;
          case 43: re_address = main_address + next_code * 42; break;
          case 44: re_address = main_address + next_code * 43; break;
          case 45: re_address = main_address + next_code * 44; break;
          case 46: re_address = main_address + next_code * 45; break;
          case 47: re_address = main_address + next_code * 46; break;
          case 48: re_address = main_address + next_code * 47; break;
          case 49: re_address = main_address + next_code * 48; break;
          case 50: re_address = main_address + next_code * 49; break;
          case 51: re_address = main_address + next_code * 50; break;
          case 52: re_address = main_address + next_code * 51; break;
          case 53: re_address = main_address + next_code * 52; break;
          case 54: re_address = main_address + next_code * 53; break;
          case 55: re_address = main_address + next_code * 54; break;
          case 56: re_address = main_address + next_code * 55; break;
          case 57: re_address = main_address + next_code * 56; break;
          case 58: re_address = main_address + next_code * 57; break;
          case 59: re_address = main_address + next_code * 58; break;
          case 60: re_address = main_address + next_code * 59; break;
          case 61: re_address = main_address + next_code * 60; break;
          case 62: re_address = main_address + next_code * 61; break;
          case 63: re_address = main_address + next_code * 62; break;
          case 64: re_address = main_address + next_code * 63; break;
          default:                                            break;
  }
        
   __disable_irq();
  
   FLASH_UNLOCK();
   
  for(i=0;i<256;i++){
    FLASH_Write(re_address+i,bin_data[i]);
  }
  sum_match++;
  
  __enable_irq();
}


void StartCode_222(){
  
  if((st222>30) && (Ready_flg==0)){
     Ready_flg = 1;
     HAL_TIM_Base_Stop_IT(&htim11);//timer stop!!
  }
    
  if(Ready_flg==1){
    
    if((send_data[1]==0x54)&&(send_data[2]==0x45)&&(send_data[3]==0x4c)&&(send_data[4]==0x4d)&&(send_data[5]==0x49)&&(send_data[6]==0x43)){
       
     if((send_data[7]==0x7F)&&(delete_flag==0)){
            
       __disable_irq();
      
      FLASH_UNLOCK();   
      FLASH_DELETE(0x01); 
      
      __enable_irq();
      delete_flag = 1;
      }

    if((send_data[8]>0)&&(send_data[8]<65)){
      binary_write();
    }
   }
  }
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

> it appears the data was already different at the point of UART reception before writing to flash.

At 1 Msps, clock needs to be more accurate. However, a clock mismatch should show up as frame errors or parity errors. If those aren't happening (you are checking, yes?) then there's likely a bug in the sending code or a bug in the reception code (e.g. not ready to receive when data starts).

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

7 REPLIES 7
TDK
Super User

You have to erase before wring to flash. You can only write to a particular flash location once. Your program logic doesn't seem to enforce this.

I recommend verifying the location you are writing to is erased (all 0xFF) before writing. Write out the values before/after to a uart log.

If you feel a post has answered your question, please click "Accept as Solution".
shank
Associate III

Thank you for your response.
Flash erasure is performed prior to flash writing, and we have confirmed it is functioning correctly.
Upon checking the UART logs, it appears the data was already different at the point of UART reception before writing to flash.
The USART primarily operates at 1Mbps, writing to the FLASH in 256KB chunks. However, the written sections and the unwritten sections (remaining erased) alternate in 256KB blocks.
Do you know the cause of this?
I have attached a portion of the program as an attachment.

TDK
Super User

> it appears the data was already different at the point of UART reception before writing to flash.

At 1 Msps, clock needs to be more accurate. However, a clock mismatch should show up as frame errors or parity errors. If those aren't happening (you are checking, yes?) then there's likely a bug in the sending code or a bug in the reception code (e.g. not ready to receive when data starts).

If you feel a post has answered your question, please click "Accept as Solution".
shank
Associate III

The data to be written to the flash memory is being received via USART and written to the flash memory sequentially.
However, it appears that the next 256KB of data is being missed when the USART is received while the flash memory is being written.
Consequently, written and unwritten sections alternate.
Since interrupts are disabled during FLASH writing, I don't believe USART interrupt reception is possible. Is there a way to resolve this issue?

Ozone
Principal III

> You have to erase before wring to flash. You can only write to a particular flash location once

This is not entirely correct.

You can always "re-program" individual bits in each cell to zero (1 -> 0).
But "programming" cannot set any bit from state zero to state one (0 -> 1).
This is only achieved via "erase" - but this can only be done sector-wise.

Perhaps you will need to debug your code more. Separate the flash writing from the USART reception so you can convince yourself that flash write operations are correct.

If you feel a post has answered your question, please click "Accept as Solution".
shank
Associate III

Since both USART reception and FLASH writing functioned correctly when performed separately, I resolved this issue by writing to the FLASH only after all USART reception had completed.
Thank you for your advice.