cancel
Showing results for 
Search instead for 
Did you mean: 

Memory Managament Fault during FLASH_ProgramWord on STM32F405RGT

deamon
Visitor

Hi,

during implementation of a bootloader I have encountered a problem.

I'm using stm32 standard peripheral library.

During writing to flash, for example at address: 0x0800C000 or 0x08010000 when the 18th line:

 

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
  FLASH_Status status = FLASH_COMPLETE;

  /* Check the parameters */
  assert_param(IS_FLASH_ADDRESS(Address));

  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_WORD;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint32_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 
  /* Return the Program Status */
  return status;
}

static void flashPage(void){
  //flash page if collected
  FlashPage* const page = &gFlData.flashPage;
  uint32_t addr = page->flashTargetAddress
      + ((uint32_t)page->pageCounter * FLASH_PAGE_SIZE);
  page->pageCounter++;

  DEBUG(DLT_LOG_INFO,"Pc:%d, flashPageAddr:0x%x", page->pageCounter, addr);
  int sector = FLASH_If_Address2Sector(addr);
  ASSERT(sector != -1);

  int ret = 0;
  do
  {
    if(IsSectorErased(sector))
    {
      DEBUG(DLT_LOG_INFO,"eraseSector:%x", sector);
#if 0
      MEMDUMP(DLT_LOG_INFO, (uint8_t*)0x0800C000, 32);
#endif
#if 1

      ENTER_CRITICAL_SECTION();
      FLASH_Unlock();
      ret = FlashIf_Erase((uint16_t)sector);
      FLASH_Lock();
      EXIT_CRITICAL_SECTION();
#endif
      if(ret < 0)
      {
        DERROR("erasePage:0x%x, err:%d - ERROR", addr, ret);
        break;
      }
      else{
        gFlData.lastErasedSector = sector;
        DEBUG(DLT_LOG_INFO,"Success erasure");
      }
    }
    
    ENTER_CRITICAL_SECTION();
    FLASH_Unlock();
    ret = FlashIf_Write(addr, page->buff, page->idx);
    FLASH_Lock();
    EXIT_CRITICAL_SECTION();
#endif
    if(ret < 0)
    {
      ERROR("writePage:0x%x, err:%d - ERROR", addr, ret);
      break;
    }

    DEBUG(DLT_LOG_INFO,"L:%x", page->idx);

    page->idx = 0;
  }while(false);
}

 

is executed, I receive a NMI interrupt, always.

The function 'flashPage' is a main func(at line 30).

The erase at line 54 works perfectly. I have checked it by reading whole sector, byte after byte, and checking if there is different value than 0xFF.

 

Here is some dump from registers during the hard fault:

BFAR: 08010000
MMFAR: 08010000
CFSR: 00000082
HFSR: 00000000
DFSR: 00000008
AFSR: 00000000
SHCSR: 00070001
From CFSR I can see  Data access violation fault  MMFAR valid

 

The uC has 3.3V Vcc.

It doesn't matter whether I use internal HCI or external HSE. Main clock set to 160MHz.

Main power regulator set to PWR_Regulator_Voltage_Scale1 -> so up to 168Mhz -> and again, the page erase works fine.

 

I've checked option bytes, whether there is some write protection enabled, but when I read the WriteProtectionBytes,(FLASH_OB_GetWRP()) I receive 0xFFF, so the write protection is not enabled.

 

Has anyone an idea, what is a source of my issue?

 

0 REPLIES 0