Skip to main content
Visitor II
August 16, 2024
Solved

Memory Managament Fault during FLASH_ProgramWord on STM32F405RGT

  • August 16, 2024
  • 1 reply
  • 823 views

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?

 

    This topic has been closed for replies.
    Best answer by deamon

    Thanks Bob.

    The FLASH_ProgramWord() is called inside WriteIf_write(), which is only an interface. I've just haven't pasted this part of code, thinking, that it is unnecessary.

    Anyway, I have find out the issue -> memory management fault is strictly related to MPU or to physical memory mapping, so I've checked whether the MPU is enabled and -> it is.

    After that, it was a simple matter of disabling it.

    1 reply

    Super User
    August 16, 2024

    The code you show never calls FLASH_ProgramWord().

    Are you SURE that is was really an NMI interrupt?  If you don't have any code for any of the memory management IRQs they all will collapse into a single "while(1);" loop.  Using the CubeIDE fault analyzer may help figure things out. 

    Also, on the F4xx series, the "usage fault", "bus fault" and "memory manager fault" are not enabled by default - you have to explicitly enable them by writing to the SCB->SHCSR register.

    deamonAuthorAnswer
    Visitor II
    August 17, 2024

    Thanks Bob.

    The FLASH_ProgramWord() is called inside WriteIf_write(), which is only an interface. I've just haven't pasted this part of code, thinking, that it is unnecessary.

    Anyway, I have find out the issue -> memory management fault is strictly related to MPU or to physical memory mapping, so I've checked whether the MPU is enabled and -> it is.

    After that, it was a simple matter of disabling it.